[m-rev.] Performance, layout and code improvements to pprint.m

Ralph Becket rafe at cs.mu.OZ.AU
Mon Oct 29 17:16:46 AEDT 2001


Estimated hours taken: 24
Branches: main

I've fixed a performance bug, tidied up the code somewhat, fixed a bug
in the `group' doc semantics, added some improved list formatting
functions and used them to improve the default formatting for lists,
arrays, tuples and maps.

library/pprint.m:
	- Tidied up the code somewhat, including the removal of several
	  now-useless functions.
	- Fixed a performance bug in be//3 where what looked tail recursion
	  actually wasn't.
	- Added a suite of packed_xxx functions to support placing as many
	  items as possible on a line.
	- Used those functions to improve the default formatting of lists,
	  tuples, maps, arrays, etc.

tests/hard_coded/pretty_printing.m:
	Added.

tests/hard_coded/pretty_printing.exp:
	Added (expected output of the above).

tests/hard_coded/Mmakefile:
	Added `pretty_printing' to list of ORDINARY_PROGS.

Index: pprint.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/pprint.m,v
retrieving revision 1.5
diff -u -r1.5 pprint.m
--- pprint.m	26 Apr 2001 14:55:13 -0000	1.5
+++ pprint.m	29 Oct 2001 05:47:00 -0000
@@ -188,6 +188,9 @@
     %
 :- func label(string, doc)  = doc.
 
+    % A group doc gives the pretty printer a choice: if
+    % the doc can be printed without line wrapping then
+
     % A group doc may be flattened out in the sense
     % described for line, above, at the discretion of the
     % pretty printer.  A group doc, therefore, defines a
@@ -216,14 +219,40 @@
 :- func brackets(doc)                   = doc.
 :- func braces(doc)                     = doc.
 
-    % separated(PP, Sep, [X1,...,Xn]) =
-    %   PP(X1) `<>` (Sep `<>` ... (Sep `<>` PP(Xn)) ... )
+    % packed(Sep, [X1, X2, .., Xn]) = G1 `<>` G2 `<>` .. `<>` Gn where
+    % Gi = group(line `<>` Xi `<>` Sep), except for Gn where
+    % Gn = group(line `<>` Xn).
+    %
+    % For the singleton list case, packed(Sep, [X]) = group(line `<>` X).
+    %
+    % The resulting doc tries to pack as many items on a line as
+    % possible.
     %
-    % Note that if you want to pack as many things on one
-    % line as possible with some sort of separator, the
-    % following example illustrates a suitable idiom:
+:- func packed(doc, list(doc)) = doc.
+
+    % 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.
+
+    % packed_cs(Xs) = packed(comma_space, Xs).
     %
-    %   separated(PP, group(comma_space_line), Xs)
+    % For example, to pretty print a Mercury list of docs
+    % one might use
+    %
+    %   brackets(nest(2, packed_cs(Xs)))
+    % 
+:- func packed_cs(list(doc)) = doc.
+
+    % 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.
+
+    % separated(PP, Sep, [X1,...,Xn]) =
+    %   PP(X1) `<>` Sep `<>` ... Sep `<>` PP(Xn)
     %
 :- func separated(func(T) = doc, doc, list(T)) = doc.
 
@@ -244,14 +273,7 @@
 :- func comma_space_line    = doc.
 :- func semic_space_line    = doc.
 :- func colon_space_line    = doc.
-
-    % Example: if one wanted to pretty print a Mercury list
-    % then one might write
-    %
-    %   brackets(nest(2, separated(MyPP, comma_space_line, MyList)))
-    %
-    % where `MyPP' would be a function from MyList members
-    % to docs.
+:- func ellipsis            = doc.      % "...".
 
     % Performs word wrapping at the end of line, taking
     % whitespace sequences as delimiters separating words.
@@ -305,6 +327,15 @@
 :- type simple_doc
     ==      list(string).
 
+:- type rev_simple_doc
+    ==      simple_doc.
+
+    % This type is used to format key-value pairs in maps when
+    % using the generic to_doc/[1,2] functions.
+    %
+:- type map_pair(K, V)
+    --->    map_pair(K, V).
+
 %------------------------------------------------------------------------------%
 
 nil                     = 'NIL'.
@@ -352,7 +383,8 @@
 
 best(W, K, X)           = Best
 :-
-    be(W, K, ["" - X], Best, []).
+    be(W, K, ["" - X], [], RevBest),
+    Best = list__reverse(RevBest).
 
 %------------------------------------------------------------------------------%
 
@@ -362,81 +394,72 @@
     % running times under a strict language.  The second important
     % change is that be/5 is now a predicate that accumulates its output
     % as a list of strings, doing away with the need for a more elaborate
-    % simple_doc type.
+    % simple_doc type.  The accumulated strings must be reversed to obtain
+    % the printing order.
+    %
+    % W is the number of characters on a line.
+    % K is the number of characters for output on the current line so far.
+    % I is the current indentation string as affected by NEST and LABEL.
+
+:- pred be(int, int, list(pair(string, doc)), rev_simple_doc, rev_simple_doc).
+:- mode be(in, in, in, in, out) is det.
+
+be(_, _, [])                      -->
+    [].
+
+be(W, K, [_ - 'NIL'         | Z]) -->
+    be(W, K, Z).
 
-:- pred be(int, int, list(pair(string, doc)), simple_doc, simple_doc).
-:- mode be(in, in, in, out, in) is det.
+be(W, K, [I - 'SEQ'(X, Y)   | Z]) -->
+    be(W, K, [I - X, I - Y | Z]).
+
+be(W, K, [I - 'NEST'(J, X)  | Z]) -->
+    be(W, K, [extend(I, J) - X | Z]).
+
+be(W, K, [I - 'LABEL'(L, X) | Z]) -->
+    be(W, K, [(I ++ L) - X | Z]).
+
+be(W, K, [_ - 'TEXT'(S)     | Z]) -->
+    push_string(S),
+    be(W, (K + string__length(S)), Z).
+
+be(W, _, [I - 'LINE'        | Z]) -->
+    push_string("\n"),
+    push_string(I),
+    be(W, string__length(I), Z).
 
-be(_, _, [], Out, In)             :-  Out = list__reverse(In).
-be(W, K, [_ - 'NIL'         | Z]) --> be(W, K, Z).
-be(W, K, [I - 'SEQ'(X, Y)   | Z]) --> be(W, K, [I - X, I - Y | Z]).
-be(W, K, [I - 'NEST'(J, X)  | Z]) --> be(W, K, [extend(I, J) - X | Z]).
-be(W, K, [I - 'LABEL'(L, X) | Z]) --> be(W, K, [string__append(I, L) - X | Z]).
-be(W, K, [_ - 'TEXT'(S)     | Z]) --> [S], be(W, (K + string__length(S)), Z).
-be(W, _, [I - 'LINE'        | Z]) --> ["\n", I], be(W, string__length(I), Z).
 be(W, K, [I - 'GROUP'(X)    | Z]) -->
-    ( if { flattening_works(X, Z, W - K) } then
-        be(W, K, [I - flatten(X) | Z])
-      else
-        be(W, K, [I - X | Z])
+    ( if   { fits_flattened([X], W - K) }
+      then be(W, K, [I - flatten(X) | Z])
+      else be(W, K, [I - X | Z])
     ).
 
-%------------------------------------------------------------------------------%
-
-    % Decide whether flattening a given doc will allow it and
-    % up to the next possible 'LINE' in the following docs to
-    % fit on the remainder of the line.
-    %
-    % XXX This solution is necessary to avoid crippling performance
-    % problems on large terms.  A spot of laziness would do away
-    % with the need for the next three predicates.
-    %
-:- pred flattening_works(doc, list(pair(string, doc)), int).
-:- mode flattening_works(in, in, in) is semidet.
-
-flattening_works(DocToFlatten, FollowingDocs, RemainingWidth) :-
-    fits_flattened([DocToFlatten], RemainingWidth, RemainingWidth0),
-    fits_on_rest(FollowingDocs, RemainingWidth0).
 
-%------------------------------------------------------------------------------%
 
-    % Decide if a flattened list of docs will fit on the remainder
-    % of the line.  Computes the space left over if so.
-    %
-:- pred fits_flattened(list(doc), int, int).
-:- mode fits_flattened(in, in, out) is semidet.
+:- pred push_string(string, rev_simple_doc, rev_simple_doc).
+:- mode push_string(in, in, out) is det.
 
-fits_flattened([]                 ) --> [].
-fits_flattened(['NIL'         | Z]) --> fits_flattened(Z).
-fits_flattened(['SEQ'(X, Y)   | Z]) --> fits_flattened([X, Y | Z]).
-fits_flattened(['NEST'(_, X)  | Z]) --> fits_flattened([X | Z]).
-fits_flattened(['LABEL'(_, X) | Z]) --> fits_flattened([X | Z]).
-fits_flattened(['LINE'        | Z]) --> fits_flattened(Z).
-fits_flattened(['GROUP'(X)    | Z]) --> fits_flattened([X | Z]).
-fits_flattened(['TEXT'(S)     | Z], R0, R) :-
-    L = string__length(S),
-    R0 > L,
-    fits_flattened(Z, R0 - L, R).
+push_string(S, Ss, [S | Ss]).
 
 %------------------------------------------------------------------------------%
 
-    % Decide if a list of indent-doc pairs, up to the first 'LINE',
-    % will fit on the remainder of the line.
+    % Decide if a flattened list of docs will fit on the remainder
+    % of the line.
     %
-:- pred fits_on_rest(list(pair(string, doc)), int).
-:- mode fits_on_rest(in, in) is semidet.
+:- pred fits_flattened(list(doc), int).
+:- mode fits_flattened(in, in) is semidet.
 
-fits_on_rest([]                     , _).
-fits_on_rest([_ - 'NIL'         | Z], R) :- fits_on_rest(Z, R).
-fits_on_rest([I - 'SEQ'(X, Y)   | Z], R) :- fits_on_rest([I - X, I - Y | Z], R).
-fits_on_rest([I - 'NEST'(_, X)  | Z], R) :- fits_on_rest([I - X | Z], R).
-fits_on_rest([I - 'LABEL'(_, X) | Z], R) :- fits_on_rest([I - X | Z], R).
-fits_on_rest([_ - 'LINE'        | _], _).
-fits_on_rest([I - 'GROUP'(X)    | Z], R) :- fits_on_rest([I - X | Z], R).
-fits_on_rest([_ - 'TEXT'(S)     | Z], R) :-
+fits_flattened([]                 , _).
+fits_flattened(['NIL'         | Z], R) :- fits_flattened(Z,          R).
+fits_flattened(['SEQ'(X, Y)   | Z], R) :- fits_flattened([X, Y | Z], R).
+fits_flattened(['NEST'(_, X)  | Z], R) :- fits_flattened([X | Z],    R).
+fits_flattened(['LABEL'(_, X) | Z], R) :- fits_flattened([X | Z],    R).
+fits_flattened(['LINE'        | Z], R) :- fits_flattened(Z,          R).
+fits_flattened(['GROUP'(X)    | Z], R) :- fits_flattened([X | Z],    R).
+fits_flattened(['TEXT'(S)     | Z], R) :-
     L = string__length(S),
     R > L,
-    fits_on_rest(Z, R - L).
+    fits_flattened(Z, R - L).
 
 %------------------------------------------------------------------------------%
 
@@ -454,7 +477,7 @@
 
 :- func extend(string, int) = string.
 
-extend(I, J) = string__append(I, string__duplicate_char(' ', J)).
+extend(I, J) = I ++ string__duplicate_char(' ', J).
 
 %------------------------------------------------------------------------------%
 
@@ -478,6 +501,55 @@
 
 %------------------------------------------------------------------------------%
 
+packed(_N, _Sep, []           ) =
+    nil.
+
+packed(N,  _Sep, [X]          ) =
+    group(line `<>` (if 0 < N then 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)
+    ).
+
+%------------------------------------------------------------------------------%
+
+packed(Sep, Xs) = packed(int__max_int, Sep, Xs).
+
+%------------------------------------------------------------------------------%
+
+packed_cs(N, Xs) = packed(N, comma_space, Xs).
+
+%------------------------------------------------------------------------------%
+
+packed_cs(Xs) = packed(comma_space, Xs).
+
+%------------------------------------------------------------------------------%
+
+    % This is like a depth-limited version of packed_cs/1 that first
+    % calls to_doc/2 on each member of the argument list.
+    %
+:- func packed_cs_to_depth(int, list(T)) = doc.
+
+packed_cs_to_depth(Depth, Xs) =
+    packed_cs(Depth, list__map(to_doc(Depth), Xs)).
+
+%------------------------------------------------------------------------------%
+
+    % This is like a version of packed_cs_to_depth/1 that first
+    % calls univ_value/1 for each member of the argument list.
+    %
+:- func packed_cs_univ_args(int, list(univ)) = doc.
+
+packed_cs_univ_args(Depth, UnivArgs) = 
+    packed_cs(
+        Depth,
+        list__map(func(UnivArg) = to_doc(Depth, univ_value(UnivArg)), UnivArgs)
+    ).
+
+%------------------------------------------------------------------------------%
+
 comma                   = text(",").
 semic                   = text(";").
 colon                   = text(":").
@@ -492,6 +564,7 @@
 comma_space_line        = text(", ") `<>` line.
 semic_space_line        = text("; ") `<>` line.
 colon_space_line        = text(": ") `<>` line.
+ellipsis                = text("...").
 
 %------------------------------------------------------------------------------%
 
@@ -501,37 +574,31 @@
 
     % This may throw an exception or cause a runtime abort if the term
     % in question has user-defined equality.
+    %
+to_doc(Depth, X) =
+    (
+      if      dynamic_cast_to_list(X, List)
+      then    list_to_doc(Depth, List)
 
-to_doc(Depth, X) = Doc :-
-    deconstruct(X, Name, Arity, UnivArgs),
-    (      if dynamic_cast_to_list(X, List) then
-        Doc = list_to_doc(Depth, List)
-      else if dynamic_cast_to_array(X, Array) then
-        Doc = array_to_doc(Depth, Array)
-      else if dynamic_cast_to_tuple(X, Tuple) then
-        Doc = tuple_to_doc(Depth, Tuple)
-      else if dynamic_cast_to_map(X, Map) then
-        Doc = map_to_doc(Depth, Map)
-      else if Arity = 0 then
-        Doc = text(Name)
-      else if Depth =< 0 then
-        Doc = text(Name) `<>` text("/") `<>` poly(i(Arity))
-      else
-        Args = list__map(
-            ( func(UnivArg) = to_doc(Depth - 1, univ_value(UnivArg)) ),
-            UnivArgs
-        ),
-        Doc = text(Name) `<>`
-            parentheses(
-                group(
-                    nest(2,
-                        line `<>` separated(id, comma_space_line, Args)
-                    )
-                )
-        )
+      else if dynamic_cast_to_array(X, Array)
+      then    array_to_doc(Depth, Array)
+
+      else if dynamic_cast_to_tuple(X, Tuple)
+      then    tuple_to_doc(Depth, Tuple)
+
+      else if dynamic_cast_to_map(X, Map)
+      then    map_to_doc(Depth, Map)
+
+      else if dynamic_cast_to_map_pair(X, MapPair)
+      then    map_pair_to_doc(Depth, MapPair)
+
+      else if Depth =< 0
+      then    out_of_depth_term_to_doc(X)
+
+      else    generic_term_to_doc(Depth, X)
     ).
 
-% ---------------------------------------------------------------------------- %
+%------------------------------------------------------------------------------%
 
 :- some [T2] pred dynamic_cast_to_array(T1, array(T2)).
 :-           mode dynamic_cast_to_array(in, out) is semidet.
@@ -594,6 +661,27 @@
 
 %------------------------------------------------------------------------------%
 
+:- some [T2, T3] pred dynamic_cast_to_map_pair(T1, map_pair(T2, T3)).
+:-               mode dynamic_cast_to_map_pair(in, out) is semidet.
+
+dynamic_cast_to_map_pair(X, MP) :-
+
+        % If X is a map_pair then it has a type with two type arguments.
+        %
+    [KeyTypeDesc, ValueTypeDesc] = type_args(type_of(X)),
+
+        % Convert the TypeDescs to type variables.
+        %
+    (_ `with_type` KeyType) `has_type` KeyTypeDesc,
+    (_ `with_type` ValueType) `has_type` ValueTypeDesc,
+
+        % Constrain the type of MP to be map_pair(KeyType, ValueType)
+        % and do the cast.
+        %
+    dynamic_cast(X, MP `with_type` map_pair(KeyType, ValueType)).
+
+%------------------------------------------------------------------------------%
+
 :- pred dynamic_cast_to_tuple(T, T).
 :- mode dynamic_cast_to_tuple(in, out) is semidet.
 
@@ -605,44 +693,79 @@
 
 %------------------------------------------------------------------------------%
 
+:- func out_of_depth_term_to_doc(T) = doc.
+
+out_of_depth_term_to_doc(X) = Doc :-
+
+    deconstruct(X, Name, Arity, _UnivArgs),
+
+    Doc = ( if Arity = 0 then text(Name)
+                         else text(Name) `<>` text("/") `<>` poly(i(Arity))
+    ).
+
+%------------------------------------------------------------------------------%
+
+:- func generic_term_to_doc(int, T) = doc.
+
+generic_term_to_doc(Depth, X) = Doc :-
+
+    deconstruct(X, Name, Arity, UnivArgs),
+
+    Doc =
+        ( if    Arity = 0
+          then  text(Name)
+          else  group(
+                    text(Name) `<>` parentheses(
+                        nest(2, packed_cs_univ_args(Depth - 1, UnivArgs))
+                    )
+                )
+        ).
+
+%------------------------------------------------------------------------------%
+
     % XXX Ideally we'd just walk the array.  But that's an optimization
     % for another day.
     %
 :- func array_to_doc(int, array(T)) = doc.
 
 array_to_doc(Depth, A) =
-    text("array") `<>` parentheses(list_to_doc(Depth, array__to_list(A))).
+    group(
+        text("array") `<>`
+            parentheses(list_to_doc(Depth - 1, array__to_list(A)))
+    ).
 
 %------------------------------------------------------------------------------%
 
 :- func list_to_doc(int, list(T)) = doc.
 
 list_to_doc(Depth, Xs) =
-    brackets(separated_to_depth(to_doc, group(comma_space_line), Depth, Xs)).
+    brackets(nest(1, packed_cs_to_depth(Depth - 1, Xs))).
 
 %------------------------------------------------------------------------------%
 
 :- func map_to_doc(int, map(T1, T2)) = doc.
 
-map_to_doc(Depth, X) =
-    text("map") `<>` parentheses(
+map_to_doc(Depth, X) = Doc :-
+    KVs = list__map(mk_map_pair, map__to_assoc_list(X)),
+    Doc =
         group(
-            nest(2, 
-                line `<>`
-                separated_to_depth(map_pair_to_doc, comma_space_line, Depth,
-                    map__to_assoc_list(X)
-                )
-            )
-        )
-    ).
+            text("map") `<>`
+                parentheses(list_to_doc(Depth - 1, KVs))
+        ).
+
+
+
+:- func mk_map_pair(pair(K, V)) = map_pair(K, V).
 
+mk_map_pair(K - V) = map_pair(K, V).
 
 
-:- func map_pair_to_doc(int, pair(T1, T2)) = doc.
 
-map_pair_to_doc(Depth, Key - Value) =
+:- 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(" -> ") `<>`
-        nest(2, group(line `<>` to_doc(Depth - 1, Value))).
+        group(nest(2, line `<>` to_doc(Depth - 1, Value))).
 
 %------------------------------------------------------------------------------%
 
@@ -653,39 +776,20 @@
 
 tuple_to_doc(Depth, Tuple) = Doc :-
     deconstruct(Tuple, _Name, _Arity, UnivArgs),
-    Args = list__map(
-        ( func(UnivArg) = to_doc(Depth - 1, univ_value(UnivArg)) ),
-        UnivArgs
-    ),
-    Doc = braces(separated(id, group(comma_space_line), Args)).
-
-%------------------------------------------------------------------------------%
-
-    % This is pretty much the same as separated/3 except that it
-    % takes a depth parameter (q.v. to_doc/2) and replaces the
-    % tail of the list below the depth limit with ellipsis.
-    %
-:- func separated_to_depth(func(int, T) = doc, doc, int, list(T)) = doc.
-
-separated_to_depth(_,  _,   _,     []) = nil.
-
-separated_to_depth(PP, Sep, Depth, [X | Xs]) = Doc :-
-    ( if Depth =< 0 then
-        Doc = text("...")
-      else if Xs = [] then
-        Doc = PP(Depth, X)
-      else
-        Doc = PP(Depth, X) `<>`
-              (Sep `<>` separated_to_depth(PP, Sep, Depth - 1, Xs))
-    ).
+    Doc =
+        group(
+            braces(nest(1, packed_cs_univ_args(Depth - 1, UnivArgs)))
+        ).
 
 %------------------------------------------------------------------------------%
 
 word_wrapped(String) =
-    separated(
-        text,
-        group(space_line),
-        string__words(char__is_whitespace, String)
+    packed(
+        space,
+        list__map(
+            func(Word) = text(Word),
+            string__words(char__is_whitespace, String)
+        )
     ).
 
 %------------------------------------------------------------------------------%

Index: Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.131
diff -u -r1.131 Mmakefile
--- Mmakefile	12 Oct 2001 05:23:49 -0000	1.131
+++ Mmakefile	29 Oct 2001 06:06:19 -0000
@@ -91,6 +91,7 @@
 	pragma_export \
 	pragma_import \
 	pragma_inline \
+	pretty_printing \
 	qual_adv_test \
 	qual_basic_test \
 	qual_is_test \

pretty_printing.m
===================================================================
%------------------------------------------------------------------------------%
% pretty_printing.m
% Ralph Becket <rbeck at microsoft.com>
% Fri Oct 26 12:57:35 EST 2001
% vim: ft=mercury ff=unix ts=4 sw=4 et tw=0 wm=0
%
% Test code for pprint.
%
%------------------------------------------------------------------------------%

:- module pretty_printing.

:- interface.

:- import_module io.



:- pred main(io::di, io::uo) is det.

%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%

:- implementation.

:- import_module pprint.
:- import_module int, list, map, array, string, rbtree, std_util.

:- type tree(T) ---> branch(tree(T), T, tree(T)) ; leaf.

%------------------------------------------------------------------------------%

:- func list_doc(int, int) = doc.

list_doc(M, D) = to_doc(D, 1 `..` M).

%------------------------------------------------------------------------------%

:- func array_doc(int, int, int) = doc.

array_doc(M, N, D) = to_doc(D, array(duplicate(M, 1 `..` N))).

%------------------------------------------------------------------------------%

:- func tuple_doc_0(int) = doc.
:- func tuple_doc_1(int) = doc.
:- func tuple_doc_2(int) = doc.
:- func tuple_doc_3(int) = doc.
:- func tuple_doc_10(int) = doc.

tuple_doc_0(D)  = to_doc(D, {}).
tuple_doc_1(D)  = to_doc(D, {1}).
tuple_doc_2(D)  = to_doc(D, {1, 2}).
tuple_doc_3(D)  = to_doc(D, {1, 2, 3}).
tuple_doc_10(D) = to_doc(D, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).

%------------------------------------------------------------------------------%

:- func map_doc(int, int, int) = doc.

map_doc(M, N, D) = to_doc(D, gen_map(1, M, 1 `..` N, map__init)).

:- func gen_map(int, int, list(int), map(int, list(int))) = map(int, list(int)).

gen_map(I, M, Ns, Map) =
    ( if M < I then Map
               else gen_map(I + 1, M, Ns, Map ^ elem(I) := Ns) ).

%------------------------------------------------------------------------------%

:- func tree_doc(int, int) = doc.

tree_doc(M, D) = to_doc(D, gen_tree(M)).

:- func gen_tree(int) = tree(int).

gen_tree(M) =
    ( if M =< 0 then leaf
                else branch(gen_tree(M - 1), M, gen_tree(M - 1)) ).

%------------------------------------------------------------------------------%

:- func word_wrapped_doc = doc.

word_wrapped_doc = word_wrapped("
    In Xanadu did Kubla Khan
    A stately pleasure-dome decree:
    Where Alph, the sacred river, ran
    Through caverns measureless to man
    Down to a sunless sea.
    So twice five miles of fertile ground
    With walls and towers were girdled round:
    And here were gardens bright with sinuous rills
    Where blossomed many an incense-bearing tree;
    And here were forests ancient as the hills,
    Enfolding sunny spots of greenery.
    But oh! that deep romantic chasm which slanted
    Down the green hill athwart a cedarn cover!
    A savage place! as holy and enchanted
    As e'er beneath a waning moon was haunted
    By woman wailing for her demon-lover!
").

%------------------------------------------------------------------------------%

:- func test_string({int, int, int}) = string.

test_string({D, S, W}) = to_string(W, test_doc(D, S, W)).



:- func test_doc(int, int, int) = doc.

test_doc(D, S, W) =
    line `<>`
    line `<>`
    text(string__format("depth %d, size %d, width %d", [i(D), i(S), i(W)])) `<>`
    line `<>`
    list_doc(S, D) `<>` line `<>`
    array_doc(S, 1, D) `<>` line `<>`
    array_doc(S, S, D) `<>` line `<>`
    tuple_doc_0(D) `<>` line `<>`
    tuple_doc_1(D) `<>` line `<>`
    tuple_doc_2(D) `<>` line `<>`
    tuple_doc_3(D) `<>` line `<>`
    tuple_doc_10(D) `<>` line `<>`
    map_doc(S, 1, D) `<>` line `<>`
    map_doc(S, S, D) `<>` line `<>`
    ( if 10 < S then nil else tree_doc(S, D) `<>` line ) `<>`
    word_wrapped_doc `<>` line.

%------------------------------------------------------------------------------%

:- pred depth_size_width({int, int, int}::out) is multi.

depth_size_width({D, S, W}) :-
    depth(D),
    size(S),
    width(W).

:- pred depth(int::out) is multi.

depth(0).
depth(5).
depth(1000).

:- pred size(int::out) is multi.

size(0).
size(1).
size(3).
size(5).

:- pred width(int::out) is multi.

width(20).
width(40).
width(80).

%------------------------------------------------------------------------------%

main -->
    foldl(io__write_string, map(test_string, solutions(depth_size_width))).

%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%

pretty_printing.exp
===================================================================


depth 0, size 0, width 20
[]
array([])
array([])
{}
{...}
{...}
{...}
{...}
map([])
map([])
leaf
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 0, size 0, width 40
[]
array([])
array([])
{}
{...}
{...}
{...}
{...}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 0, size 0, width 80
[]
array([])
array([])
{}
{...}
{...}
{...}
{...}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 0, size 1, width 20
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 0, size 1, width 40
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 0, size 1, width 80
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 0, size 3, width 20
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 0, size 3, width 40
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 0, size 3, width 80
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 0, size 5, width 20
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 0, size 5, width 40
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 0, size 5, width 80
[...]
array([...])
array([...])
{}
{...}
{...}
{...}
{...}
map([...])
map([...])
branch/3
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 5, size 0, width 20
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([])
map([])
leaf
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 5, size 0, width 40
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 5, size 0, width 80
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 5, size 1, width 20
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, 
  leaf)
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 5, size 1, width 40
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, leaf)
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 5, size 1, width 80
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, leaf)
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 5, size 3, width 20
[1, 2, 3]
array([[1], [1], 
 [1]])
array([
 [1, 2, ...], 
 [1, 2, ...], 
 [1, 2, ...]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 
 2 -> [1], 3 -> [1]])
map([
 1 -> [1, ...], 
 2 -> [1, ...], 
 3 -> [1, ...]])
branch(
  branch(
    branch(leaf, 
      1, ...), 2, 
    branch(leaf, 
      1, ...)), 3, 
  branch(
    branch(leaf, 
      1, ...), 2, 
    branch(leaf, 
      1, ...)))
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 5, size 3, width 40
[1, 2, 3]
array([[1], [1], [1]])
array([[1, 2, ...], [1, 2, ...], 
 [1, 2, ...]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 2 -> [1], 3 -> [1]])
map([1 -> [1, ...], 2 -> [1, ...], 
 3 -> [1, ...]])
branch(
  branch(branch(leaf, 1, ...), 2, 
    branch(leaf, 1, ...)), 3, 
  branch(branch(leaf, 1, ...), 2, 
    branch(leaf, 1, ...)))
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 5, size 3, width 80
[1, 2, 3]
array([[1], [1], [1]])
array([[1, 2, ...], [1, 2, ...], [1, 2, ...]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 2 -> [1], 3 -> [1]])
map([1 -> [1, ...], 2 -> [1, ...], 3 -> [1, ...]])
branch(branch(branch(leaf, 1, ...), 2, branch(leaf, 1, ...)), 3, 
  branch(branch(leaf, 1, ...), 2, branch(leaf, 1, ...)))
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 5, size 5, width 20
[1, 2, 3, 4, ...]
array([[1], [1], 
 [1], ...])
array([
 [1, 2, ...], 
 [1, 2, ...], 
 [1, 2, ...], ...])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 
 2 -> [1], 
 3 -> [1], ...])
map([
 1 -> [1, ...], 
 2 -> [1, ...], 
 3 -> [1, ...], ...])
branch(
  branch(
    branch(
      branch(
        branch(...), 
        ...), 3, 
      ...), 4, 
    branch(
      branch(
        branch(...), 
        ...), 3, 
      ...)), 5, 
  branch(
    branch(
      branch(
        branch(...), 
        ...), 3, 
      ...), 4, 
    branch(
      branch(
        branch(...), 
        ...), 3, 
      ...)))
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 5, size 5, width 40
[1, 2, 3, 4, ...]
array([[1], [1], [1], ...])
array([[1, 2, ...], [1, 2, ...], 
 [1, 2, ...], ...])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 2 -> [1], 3 -> [1], ...])
map([1 -> [1, ...], 2 -> [1, ...], 
 3 -> [1, ...], ...])
branch(
  branch(
    branch(branch(branch(...), ...), 
      3, ...), 4, 
    branch(branch(branch(...), ...), 
      3, ...)), 5, 
  branch(
    branch(branch(branch(...), ...), 
      3, ...), 4, 
    branch(branch(branch(...), ...), 
      3, ...)))
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 5, size 5, width 80
[1, 2, 3, 4, ...]
array([[1], [1], [1], ...])
array([[1, 2, ...], [1, 2, ...], [1, 2, ...], ...])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, ...}
map([1 -> [1], 2 -> [1], 3 -> [1], ...])
map([1 -> [1, ...], 2 -> [1, ...], 3 -> [1, ...], ...])
branch(
  branch(branch(branch(branch(...), ...), 3, ...), 4, 
    branch(branch(branch(...), ...), 3, ...)), 5, 
  branch(branch(branch(branch(...), ...), 3, ...), 4, 
    branch(branch(branch(...), ...), 3, ...)))
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 1000, size 0, width 20
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 
 7, 8, 9, 10}
map([])
map([])
leaf
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 1000, size 0, width 40
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 1000, size 0, width 80
[]
array([])
array([])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([])
map([])
leaf
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 1000, size 1, width 20
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 
 7, 8, 9, 10}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, 
  leaf)
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 1000, size 1, width 40
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, leaf)
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 1000, size 1, width 80
[1]
array([[1]])
array([[1]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1]])
map([1 -> [1]])
branch(leaf, 1, leaf)
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 1000, size 3, width 20
[1, 2, 3]
array([[1], [1], 
 [1]])
array([[1, 2, 3], 
 [1, 2, 3], 
 [1, 2, 3]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 
 7, 8, 9, 10}
map([1 -> [1], 
 2 -> [1], 3 -> [1]])
map([
 1 -> [1, 2, 3], 
 2 -> [1, 2, 3], 
 3 -> [1, 2, 3]])
branch(
  branch(
    branch(leaf, 
      1, leaf), 2, 
    branch(leaf, 
      1, leaf)), 
  3, 
  branch(
    branch(leaf, 
      1, leaf), 2, 
    branch(leaf, 
      1, leaf)))
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 1000, size 3, width 40
[1, 2, 3]
array([[1], [1], [1]])
array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1], 2 -> [1], 3 -> [1]])
map([1 -> [1, 2, 3], 2 -> [1, 2, 3], 
 3 -> [1, 2, 3]])
branch(
  branch(branch(leaf, 1, leaf), 2, 
    branch(leaf, 1, leaf)), 3, 
  branch(branch(leaf, 1, leaf), 2, 
    branch(leaf, 1, leaf)))
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 1000, size 3, width 80
[1, 2, 3]
array([[1], [1], [1]])
array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1], 2 -> [1], 3 -> [1]])
map([1 -> [1, 2, 3], 2 -> [1, 2, 3], 3 -> [1, 2, 3]])
branch(branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)), 3, 
  branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)))
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!


depth 1000, size 5, width 20
[1, 2, 3, 4, 5]
array([[1], [1], 
 [1], [1], [1]])
array([
 [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 
 7, 8, 9, 10}
map([1 -> [1], 
 2 -> [1], 
 3 -> [1], 
 4 -> [1], 5 -> [1]])
map([
 1 -> 
   [1, 2, 3, 4, 5], 
 2 -> 
   [1, 2, 3, 4, 5], 
 3 -> 
   [1, 2, 3, 4, 5], 
 4 -> 
   [1, 2, 3, 4, 5], 
 5 -> 
   [1, 2, 3, 4, 5]])
branch(
  branch(
    branch(
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)), 
      3, 
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf))), 
    4, 
    branch(
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)), 
      3, 
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)))), 
  5, 
  branch(
    branch(
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)), 
      3, 
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf))), 
    4, 
    branch(
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)), 
      3, 
      branch(
        branch(
          leaf, 1, 
          leaf), 
        2, 
        branch(
          leaf, 1, 
          leaf)))))
In Xanadu did 
Kubla Khan A 
stately 
pleasure-dome 
decree: Where 
Alph, the sacred 
river, ran Through 
caverns 
measureless to man 
Down to a sunless 
sea. So twice five 
miles of fertile 
ground With walls 
and towers were 
girdled round: And 
here were gardens 
bright with 
sinuous rills 
Where blossomed 
many an 
incense-bearing 
tree; And here 
were forests 
ancient as the 
hills, Enfolding 
sunny spots of 
greenery. But oh! 
that deep romantic 
chasm which 
slanted Down the 
green hill athwart 
a cedarn cover! A 
savage place! as 
holy and enchanted 
As e'er beneath a 
waning moon was 
haunted By woman 
wailing for her 
demon-lover!


depth 1000, size 5, width 40
[1, 2, 3, 4, 5]
array([[1], [1], [1], [1], [1]])
array([[1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1], 2 -> [1], 3 -> [1], 
 4 -> [1], 5 -> [1]])
map([1 -> [1, 2, 3, 4, 5], 
 2 -> [1, 2, 3, 4, 5], 
 3 -> [1, 2, 3, 4, 5], 
 4 -> [1, 2, 3, 4, 5], 
 5 -> [1, 2, 3, 4, 5]])
branch(
  branch(
    branch(
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf))), 4, 
    branch(
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)))), 5, 
  branch(
    branch(
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf))), 4, 
    branch(
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, 
        branch(leaf, 1, leaf)))))
In Xanadu did Kubla Khan A stately 
pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns 
measureless to man Down to a sunless 
sea. So twice five miles of fertile 
ground With walls and towers were 
girdled round: And here were gardens 
bright with sinuous rills Where 
blossomed many an incense-bearing 
tree; And here were forests ancient as 
the hills, Enfolding sunny spots of 
greenery. But oh! that deep romantic 
chasm which slanted Down the green 
hill athwart a cedarn cover! A savage 
place! as holy and enchanted As e'er 
beneath a waning moon was haunted By 
woman wailing for her demon-lover!


depth 1000, size 5, width 80
[1, 2, 3, 4, 5]
array([[1], [1], [1], [1], [1]])
array([[1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], 
 [1, 2, 3, 4, 5]])
{}
{1}
{1, 2}
{1, 2, 3}
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
map([1 -> [1], 2 -> [1], 3 -> [1], 4 -> [1], 5 -> [1]])
map([1 -> [1, 2, 3, 4, 5], 2 -> [1, 2, 3, 4, 5], 3 -> [1, 2, 3, 4, 5], 
 4 -> [1, 2, 3, 4, 5], 5 -> [1, 2, 3, 4, 5]])
branch(
  branch(
    branch(branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf))), 4, 
    branch(branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)))), 5, 
  branch(
    branch(branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf))), 4, 
    branch(branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)), 3, 
      branch(branch(leaf, 1, leaf), 2, branch(leaf, 1, leaf)))))
In Xanadu did Kubla Khan A stately pleasure-dome decree: Where Alph, the 
sacred river, ran Through caverns measureless to man Down to a sunless sea. So 
twice five miles of fertile ground With walls and towers were girdled round: 
And here were gardens bright with sinuous rills Where blossomed many an 
incense-bearing tree; And here were forests ancient as the hills, Enfolding 
sunny spots of greenery. But oh! that deep romantic chasm which slanted Down 
the green hill athwart a cedarn cover! A savage place! as holy and enchanted 
As e'er beneath a waning moon was haunted By woman wailing for her demon-lover!

----- End forwarded message -----
--------------------------------------------------------------------------
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