[m-rev.] for review: improvementstopprintinterface

Ralph Becket rafe at cs.mu.OZ.AU
Mon May 6 12:31:55 AEST 2002


Estimated hours taken: 2
Branches: main

Extended the interface to pprint to reduce the syntactic burden of
constructing docs by introducing the doc/1 type class and the ++/2
doc instance concatenation operator.

NEWS:
	Mentioned the new changes.

library/pprint.m:
	Added the doc/1 typeclass.
	Made docs, strings, chars, ints and floats instances of doc/1.
	Added the ++/2 operator which is analogous to `<>`/2, but operates
	on doc/1 instances.
	Used the new facilities to simplify the various doc construction
	combinators provided by pprint.

Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.255
diff -u -r1.255 NEWS
--- NEWS	15 Apr 2002 05:03:58 -0000	1.255
+++ NEWS	6 May 2002 02:28:11 -0000
@@ -108,6 +108,8 @@
 
 Changes to the Mercury standard library:
 
+* We have added the type class `pprint__doc/1' and a new concatenation
+  operator, `++/2', which should make it easier to construct doc values.
 * Performance bugs in `pprint__to_doc' have now been fixed.  Even
   very large terms can now be converted to docs and pretty printed without
   causing a machine to thrash or run out of memory.

Index: pprint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.9
diff -u -r1.9 pprint.m
--- pprint.m	8 Mar 2002 01:10:37 -0000	1.9
+++ pprint.m	6 May 2002 02:17:58 -0000
@@ -163,13 +163,27 @@
 
 :- interface.
 
-:- import_module std_util, int, string, list, io.
+:- import_module std_util, int, string, char, float, list, io.
 
     % Clients must translate data structures into docs for
     % the pretty printer to display.
     %
 :- type doc.
 
+    % This typeclass can be used to simplify the construction of docs.
+    %
+:- typeclass doc(T) where [ func doc(T) = doc ].
+:- instance doc(doc).
+:- instance doc(string).
+:- instance doc(int).
+:- instance doc(float).
+:- instance doc(char).
+
+    % An alternative to the <>/2 concatenation operator that works
+    % on members of the doc/1 typeclass.
+    %
+:- func T1 ++ T2 = doc <= (doc(T1), doc(T2)).
+
     % The empty document corresponding to the null string.
     %
 :- func nil                 = doc.
@@ -226,10 +240,10 @@
     %          brackets(Doc) = bracketed("[", "]", Doc)
     %            braces(Doc) = bracketed("{", "}", Doc)
     %
-:- func bracketed(string, string, doc)  = doc.
-:- func parentheses(doc)                = doc.
-:- func brackets(doc)                   = doc.
-:- func braces(doc)                     = doc.
+:- func bracketed(T1, T2, T3)  = doc <= (doc(T1), doc(T2), doc(T3)).
+:- func parentheses(T)         = doc <= (doc(T)).
+:- func brackets(T)            = doc <= (doc(T)).
+:- func braces(T)              = doc <= (doc(T)).
 
     % packed(Sep, [X1, X2, .., Xn]) = G1 `<>` G2 `<>` .. `<>` Gn where
     % Gi = group(line `<>` Xi `<>` Sep), except for Gn where
@@ -240,13 +254,13 @@
     % The resulting doc tries to pack as many items on a line as
     % possible.
     %
-:- func packed(doc, list(doc)) = doc.
+:- func packed(T1, list(T2)) = doc <= (doc(T1), doc(T2)).
 
     % A variant of the above whereby only the first N elements of
     % the list are formatted and the rest are replaced by a single
     % ellipsis.
     %
-:- func packed(int, doc, list(doc)) = doc.
+:- func packed(int, T1, list(T2)) = doc <= (doc(T1), doc(T2)).
 
     % packed_cs(Xs) = packed(comma_space, Xs).
     %
@@ -255,13 +269,13 @@
     %
     %   brackets(nest(2, packed_cs(Xs)))
     % 
-:- func packed_cs(list(doc)) = doc.
+:- func packed_cs(list(T)) = doc <= (doc(T)).
 
     % A variant of the above whereby only the first N elements of
     % the list are formatted and the rest are replaced by a single
     % ellipsis.
     %
-:- func packed_cs(int, list(doc)) = doc.
+:- func packed_cs(int, list(T)) = doc <= (doc(T)).
 
     % This is like a depth-limited version of packed_cs/1 that first
     % calls to_doc/2 on each member of the argument list.
@@ -276,7 +290,7 @@
     % separated(PP, Sep, [X1,...,Xn]) =
     %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
     %
-:- func separated(func(T) = doc, doc, list(T)) = doc.
+:- func separated(func(T1) = doc, T2, list(T1)) = doc <= (doc(T2)).
 
     % Handy punctuation docs and versions with following
     % spaces and/or line breaks.
@@ -335,7 +349,7 @@
 
 :- implementation.
 
-:- import_module char, array, map, exception.
+:- import_module array, map, exception.
 
 :- type doc
     --->    'NIL'
@@ -360,6 +374,18 @@
 
 %------------------------------------------------------------------------------%
 
+:- instance doc(doc)    where [ doc(Doc)    = Doc            ].
+:- instance doc(string) where [ doc(String) = text(String)   ].
+:- instance doc(int)    where [ doc(Int)    = poly(i(Int))   ].
+:- instance doc(float)  where [ doc(Float)  = poly(f(Float)) ].
+:- instance doc(char)   where [ doc(Char)   = poly(c(Char))  ].
+
+%------------------------------------------------------------------------------%
+
+Doc1 ++ Doc2 = doc(Doc1) `<>` doc(Doc2).
+
+%------------------------------------------------------------------------------%
+
 nil                     = 'NIL'.
 X `<>` Y                = 'SEQ'(X, Y).
 nest(I, X)              = 'NEST'(I, X).
@@ -512,11 +538,11 @@
 
 %------------------------------------------------------------------------------%
 
-X `</>` Y               = X `<>` line `<>` Y.
+X `</>` Y               = X ++ line ++ Y.
 
 %------------------------------------------------------------------------------%
 
-bracketed(L, R, D)      = text(L) `<>` D `<>` text(R).
+bracketed(L, R, D)      = L ++ D ++ R.
 parentheses(D)          = bracketed("(", ")", D).
 brackets(D)             = bracketed("[", "]", D).
 braces(D)               = bracketed("{", "}", D).
@@ -527,7 +553,7 @@
 
 separated(PP, Sep, [X | Xs]) =
     ( if Xs = [] then PP(X)
-                 else PP(X) `<>` (Sep `<>` separated(PP, Sep, Xs))
+                 else PP(X) ++ (Sep ++ separated(PP, Sep, Xs))
     ).
 
 %------------------------------------------------------------------------------%
@@ -536,12 +562,12 @@
     nil.
 
 packed(N,  _Sep, [X]          ) =
-    group(line `<>` (if 0 < N then X else ellipsis)).
+    group(line ++ (if 0 < N then doc(X) else ellipsis)).
 
 packed(N,  Sep,  [X1, X2 | Xs]) =
     ( if   0 < N
-      then group(line `<>` X1 `<>` Sep) `<>` packed(N - 1, Sep, [X2 | Xs])
-      else group(line `<>` ellipsis)
+      then group(line ++ X1 ++ Sep) ++ packed(N - 1, Sep, [X2 | Xs])
+      else group(line ++ ellipsis)
     ).
 
 %------------------------------------------------------------------------------%
@@ -550,11 +576,11 @@
 
 %------------------------------------------------------------------------------%
 
-packed_cs(N, Xs) = packed(N, comma_space, Xs).
+packed_cs(N, Xs) = packed(N, ", ", Xs).
 
 %------------------------------------------------------------------------------%
 
-packed_cs(Xs) = packed(comma_space, Xs).
+packed_cs(Xs) = packed(", ", Xs).
 
 %------------------------------------------------------------------------------%
 
@@ -575,13 +601,13 @@
 comma_space             = text(", ").
 semic_space             = text("; ").
 colon_space             = text(": ").
-comma_line              = comma `<>` line.
-semic_line              = semic `<>` line.
-colon_line              = colon `<>` line.
-space_line              = space `<>` line.
-comma_space_line        = text(", ") `<>` line.
-semic_space_line        = text("; ") `<>` line.
-colon_space_line        = text(": ") `<>` line.
+comma_line              = "," ++ line.
+semic_line              = ";" ++ line.
+colon_line              = ":" ++ line.
+space_line              = " " ++ line.
+comma_space_line        = ", " ++ line.
+semic_space_line        = "; " ++ line.
+colon_space_line        = ": " ++ line.
 ellipsis                = text("...").
 
 %------------------------------------------------------------------------------%
@@ -719,7 +745,7 @@
     functor(X, Name, Arity),
 
     Doc = ( if Arity = 0 then text(Name)
-                         else text(Name) `<>` text("/") `<>` poly(i(Arity))
+                         else Name ++ "/" ++ Arity
     ).
 
 %------------------------------------------------------------------------------%
@@ -734,7 +760,7 @@
         ( if    Arity = 0
           then  text(Name)
           else  group(
-                    text(Name) `<>` parentheses(
+                    Name ++ parentheses(
                         nest(2, packed_cs_univ_args(Depth - 1, UnivArgs))
                     )
                 )
@@ -748,10 +774,7 @@
 :- func array_to_doc(int, array(T)) = doc.
 
 array_to_doc(Depth, A) =
-    group(
-        text("array") `<>`
-            parentheses(list_to_doc(Depth - 1, array__to_list(A)))
-    ).
+    group("array" ++ parentheses(list_to_doc(Depth - 1, array__to_list(A)))).
 
 %------------------------------------------------------------------------------%
 
@@ -768,7 +791,7 @@
     KVs = list__map(mk_map_pair, map__to_assoc_list(X)),
     Doc =
         group(
-            text("map") `<>` parentheses(list_to_doc(Depth - 1, KVs))
+            "map" ++ parentheses(list_to_doc(Depth - 1, KVs))
         ).
 
 
@@ -781,8 +804,8 @@
 :- func map_pair_to_doc(int, map_pair(T1, T2)) = doc.
 
 map_pair_to_doc(Depth, map_pair(Key, Value)) =
-    to_doc(Depth - 1, Key) `<>` text(" -> ") `<>`
-        group(nest(2, line `<>` to_doc(Depth - 1, Value))).
+    to_doc(Depth - 1, Key) ++ text(" -> ") ++
+        group(nest(2, line ++ to_doc(Depth - 1, Value))).
 
 %------------------------------------------------------------------------------%
 
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list