--* From postmaster%watson.vnet.ibm.com@yktvmv.watson.ibm.com  Tue Jul  5 09:20:28 1994
--* Received: from yktvmv-ob.watson.ibm.com by asharp.watson.ibm.com (AIX 3.2/UCB 5.64/930311)
--*           id AA25812; Tue, 5 Jul 1994 09:20:28 -0400
--* Received: from watson.vnet.ibm.com by yktvmv.watson.ibm.com (IBM VM SMTP V2R3)
--*    with BSMTP id 2883; Tue, 05 Jul 94 09:20:30 EDT
--* Received: from YKTVMV by watson.vnet.ibm.com with "VAGENT.V1.0"
--*           id <A.JENKS.NOTE.VAGENT2.6953.Jul.05.09:20:29.-0400>
--*           for asbugs@watson; Tue, 05 Jul 94 09:20:30 -0400
--* Received: from YKTVMV by watson.vnet.ibm.com with "VAGENT.V1.0"
--*           id 6947; Tue, 5 Jul 1994 09:20:29 EDT
--* Received: from leonardo.watson.ibm.com by yktvmv.watson.ibm.com
--*    (IBM VM SMTP V2R3) with TCP; Tue, 05 Jul 94 09:20:28 EDT
--* Received: by leonardo.watson.ibm.com (AIX 3.2/UCB 5.64/920123)
--*           id AA12891; Tue, 5 Jul 1994 09:15:44 -0400
--* Date: Tue, 5 Jul 1994 09:15:44 -0400
--* From: jenks@leonardo.watson.ibm.com
--* X-External-Networks: yes
--* Message-Id: <9407051315.AA12891@leonardo.watson.ibm.com>
--* To: asbugs@watson.ibm.com
--* Subject: [3] segmentation violation [/u/jenks/dimacs94/ex.pm/xtree.as][?]

--@ Fixed  by:  SSD   Tue Mar 21 12:32:52 EST 1995 
--@ Tested by:  none 
--@ Summary:    Segmentation fault no longer appears. Now gives valid user error messages. 


--+ --> testint
--+ --> testrun
--+ #include "aslib.as"
--+
--+ Xtree(S: BasicType): BasicType with {
--+ 	empty: %;
--+ 	tree:  S  -> %;
--+         tree:  (S, List %) -> %;
--+         bracket: Tuple Union(S,%) -> %;
--+         leaf?: % -> Boolean;
--+ 	empty?: % -> Boolean;
--+         generator: % -> Generator S;
--+ 	node:   % -> S;
--+         child: (%, Integer) -> %;
--+         preorder: % -> Generator S
--+ } == add {
--+ 	Rep ==> Record(node: S, args: List %);
--+ 	import from Rep;
--+         import from List %;
--+ 	tree(s: S): % == per [s, nil];
--+ 	tree(s: S, l: List %): % == per [s, l];
--+ 	empty: % == nil$Pointer pretend %;
--+ 	sample: % == empty;
--+ 	empty?(t: %): Boolean == nil?(t pretend Pointer)$Pointer;
--+         leaf? (t: %): Boolean == empty? ((rep t).args);
--+         node(t: %): S == (rep t) . node;
--+
--+         child(t: %, n: Integer): % == {
--+ 		empty? t => error "Taking a part of a non-empty tree";
--+                 n <= 0   => error "child must take a positive index";
--+                 apply((rep t) . args, n pretend SingleInteger)
--+         }
--+
--+         bracket(tup: Tuple Union(S, %)): % == {
--+           u: List Tuple Union(S, %) := [tup];
--+           root := {
--+             first u case S => first u;
--+             error "first element must be a scalar"
--+           }
--+           branches := {
--+             acc: List % := nil;
--+             for x in rest u repeat {
--+               y: % := {
--+                 x case S => tree x;
--+                 x
--+               }
--+               acc := cons(x,acc);
--+             }
--+             reverse acc
--+           }
--+           tree(root, branches)
--+         }
--+
--+         generator(l: %): Generator S == generate {
--+                 yield l . node;
--+                 for x in l . args repeat yield x
--+         }
--+
--+ 	(t1: %) = (t2: %): Boolean == {
--+ 		import from S;
--+ 		empty? t1 and  empty? t2 => true;
--+ 		empty? t1 or   empty? t2 => false;
--+ 		(rep t1).node = (rep t2).node and (rep t1).args = (rep t2).args
--+ 	}
--+
--+         preorder(t: %) : Generator S == generate { not empty? t => {
--+                 yield node t;
--+                 for branch in (rep t).args repeat
--+                    for val in preorder branch repeat yield val
--+         }}
--+
--+ 	(outp: TextWriter) << (t: %): TextWriter == {
--+ 		import from String;
--+ 		import from S;
--+ 		empty? t => outp << "empty";
--+                 leaf? t  => outp << (rep t) . node;
--+                 outp << "[" << (rep t) . node;
--+                 for x in (rep t) . args repeat outp << ", " << x;
--+                 outp << "]"
--+ 	}
--+ }
--+
--+ -- Testing your solution
--+ f(): () == {
--+         import from String;
--+         import from TextWriter;
--+         import from Xtree(String);
--+         import from List(Xtree(String));
--+         t := tree "a";
--+         print << "The tree is " << t;
--+ --        t := tree("*", [tree("+", [tree "a",tree "b"]),
--+ --                                      tree("-", [tree "c",tree "d"])]);
--+         print << "The tree is " << t;
--+         print << "Preorder: ";
--+         for s in preorder t repeat print << s << " ";
--+         print << newline;
--+
--+ }
--+
--+ f();
--+
--> testint
--> testrun
#include "aslib.as"

Xtree(S: BasicType): BasicType with {
	empty: %;
	tree:  S  -> %;
        tree:  (S, List %) -> %;
        bracket: Tuple Union(S,%) -> %;
        leaf?: % -> Boolean;
	empty?: % -> Boolean;
        generator: % -> Generator S;
	node:   % -> S;
        child: (%, Integer) -> %;
        preorder: % -> Generator S
} == add {
	Rep ==> Record(node: S, args: List %);
	import from Rep;
        import from List %;
	tree(s: S): % == per [s, nil];
	tree(s: S, l: List %): % == per [s, l];
	empty: % == nil$Pointer pretend %;
	sample: % == empty;
	empty?(t: %): Boolean == nil?(t pretend Pointer)$Pointer;
        leaf? (t: %): Boolean == empty? ((rep t).args);
        node(t: %): S == (rep t) . node;

        child(t: %, n: Integer): % == {
		empty? t => error "Taking a part of a non-empty tree";
                n <= 0   => error "child must take a positive index";
                apply((rep t) . args, n pretend SingleInteger)
        }

        bracket(tup: Tuple Union(S, %)): % == {
          u: List Tuple Union(S, %) := [tup];
          root := {
            first u case S => first u;
            error "first element must be a scalar"
          }
          branches := {
            acc: List % := nil;
            for x in rest u repeat {
              y: % := {
                x case S => tree x;
                x
              }
              acc := cons(x,acc);
            }
            reverse acc
          }
          tree(root, branches)
        }

        generator(l: %): Generator S == generate {
                yield l . node;
                for x in l . args repeat yield x
        }

	(t1: %) = (t2: %): Boolean == {
		import from S;
		empty? t1 and  empty? t2 => true;
		empty? t1 or   empty? t2 => false;
		(rep t1).node = (rep t2).node and (rep t1).args = (rep t2).args
	}

        preorder(t: %) : Generator S == generate { not empty? t => {
                yield node t;
                for branch in (rep t).args repeat
                   for val in preorder branch repeat yield val
        }}

	(outp: TextWriter) << (t: %): TextWriter == {
		import from String;
		import from S;
		empty? t => outp << "empty";
                leaf? t  => outp << (rep t) . node;
                outp << "[" << (rep t) . node;
                for x in (rep t) . args repeat outp << ", " << x;
                outp << "]"
	}
}

-- Testing your solution
f(): () == {
        import from String;
        import from TextWriter;
        import from Xtree(String);
        import from List(Xtree(String));
        t := tree "a";
        print << "The tree is " << t;
--        t := tree("*", [tree("+", [tree "a",tree "b"]),
--                                      tree("-", [tree "c",tree "d"])]);
        print << "The tree is " << t;
        print << "Preorder: ";
        for s in preorder t repeat print << s << " ";
        print << newline;

}

f();

 
