[m-dev.] diff: use pretty printer in mdb

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Tue May 23 16:28:24 AEST 2000


Please ignore my previous post, it was sent by mistake.

Mark Anthony BROWN writes:
> 
> As for the performance problem, I think it can be solved by threading
> the available width through flatten, which should fail if there is not
> enough room for the flattened document.  This will allow the 
> condition (in be/3) to fail before the recursive call.
> 

This solution appears to work OK.  If there are no objections,
I shall commit this change soon.

Cheers,
Mark.


Estimated hours taken: 3

library/pprint.m:
	Fix a bug which led to exponential worst-case performance.
	We check the size of a document as it is being flattened,
	rather than afterward.  This means failure can occur earlier,
	which usually avoids an unnecessary recursive call while
	processing 'GROUP' documents.

Index: library/pprint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.2
diff -u -r1.2 pprint.m
--- library/pprint.m	2000/05/09 13:06:47	1.2
+++ library/pprint.m	2000/05/23 05:51:30
@@ -346,13 +346,6 @@
 
 %------------------------------------------------------------------------------%
 
-    % XXX We could do with a spot of laziness to avoid exponential
-    % run-times in the worst case here.  The problem is that flatten/1
-    % need only be evaluated to the point where it can be decided
-    % (by better/4 and fits/2) whether a structure is going to fit on
-    % the remainder of the line or not.  In practice, eagerness doesn't
-    % seem to be a problem.
-
 :- func be(int, int, list(pair(string, doc))) = simple_doc.
 
 be(_, _, [])                      = nil.
@@ -364,8 +357,8 @@
 be(W, _, [I - 'LINE'        | Z]) = I `line` be(W, string__length(I), Z).
 be(W, K, [I - 'GROUP'(X)    | Z]) =
     ( if
-        K =< W,                         % Really want an ordered conjunction...
-        Flattened = be(W, K, [I - flatten(X) | Z]),
+        try_flatten(X, FlatX, W - K, _),
+        Flattened = be(W, K, [I - FlatX | Z]),
         fits(W - K, Flattened)
       then
         Flattened
@@ -380,16 +373,32 @@
 extend(I, J) = string__append(I, string__duplicate_char(' ', J)).
 
 %------------------------------------------------------------------------------%
-
-:- func flatten(doc) = doc.
 
-flatten('NIL')          = 'NIL'.
-flatten('SEQ'(X, Y))    = 'SEQ'(flatten(X), flatten(Y)).
-flatten('NEST'(_, X))   = flatten(X).
-flatten('LABEL'(_, X))  = flatten(X).
-flatten('TEXT'(S))      = 'TEXT'(S).
-flatten('LINE')         = 'NIL'.
-flatten('GROUP'(X))     = flatten(X).
+    % While flattening documents, we keep track of the amount of
+    % space available on the line.  This predicate fails if there
+    % is not enough space for the flattened term.
+    %
+:- pred try_flatten(doc, doc, int, int).
+:- mode try_flatten(in, out, in, out) is semidet.
+
+try_flatten('NIL', 'NIL') -->
+    [].
+try_flatten('SEQ'(X, Y), 'SEQ'(FX, FY)) -->
+    try_flatten(X, FX),
+    try_flatten(Y, FY).
+try_flatten('NEST'(_, X), FX) -->
+    try_flatten(X, FX).
+try_flatten('LABEL'(_, X), FX) -->
+    try_flatten(X, FX).
+try_flatten('TEXT'(S), 'TEXT'(S)) -->
+    =(W0),
+    { W = W0 - string__length(S) },
+    { W >= 0 },
+    :=(W).
+try_flatten('LINE', 'NIL') -->
+    [].
+try_flatten('GROUP'(X), FX) -->
+    try_flatten(X, FX).
 
 %------------------------------------------------------------------------------%
 
-- 
Mark Brown, PhD student            )O+  |  "Another of Fortran's breakthroughs
(m.brown at cs.mu.oz.au)                   |  was the GOTO statement, which was...
Dept. of Computer Science and Software  |  uniquely simple and understandable"
Engineering, University of Melbourne    |              -- IEEE, 1994
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list