1 /////////////////////////////////////////////////////////////////////////////
2 // Testing polymorphic datatypes.
3 // (and garbage collection, reference counting etc.)
4 /////////////////////////////////////////////////////////////////////////////
7 // Define some polymorphic datatypes
8 // Polymorphic datatypes are not restricted to one type parameter.
9 // We test the ability to use these types in the context
11 datatype TREE<X,Y> :: printable collectable // garbage collected
12 = empty | leaf (X) | node (TREE<X,Y>, Y, TREE<X,Y>)
14 and LIST<T> :: printable collectable // garbage collected
15 = #[] | #[ T ... LIST<T> ]
17 and EXP :: printable traced // reference counted
19 | var (const char *) => _
20 | add (EXP, EXP) => "(" _ " + " _ ")"
21 | sub (EXP, EXP) => "(" _ " - " _ ")"
22 | mul (EXP, EXP) => "(" _ " * " _ ")"
23 | div (EXP, EXP) => "(" _ " / " _ ")"
24 | list (LIST<EXP>) => _
25 // note the polymorphic list type here
28 /////////////////////////////////////////////////////////////////////////////
29 // Instantiate the datatypes.
30 // This will generate a bunch of methods, functions and classes
31 // to implement printing and garbage collection.
32 /////////////////////////////////////////////////////////////////////////////
33 instantiate extern datatype TREE<int, const char *>, LIST<int>, LIST< EXP >;
34 instantiate datatype TREE<int, const char *>, LIST<int>, LIST< EXP >, EXP;
36 /////////////////////////////////////////////////////////////////////////////
37 // Define functions to test pattern matching
38 /////////////////////////////////////////////////////////////////////////////
43 | #[h ... t]: { return 1 + length(t); }
47 /////////////////////////////////////////////////////////////////////////////
48 // Sum an integer list
49 /////////////////////////////////////////////////////////////////////////////
53 | #[h ... t]: { return h + sum(t); }
57 /////////////////////////////////////////////////////////////////////////////
59 /////////////////////////////////////////////////////////////////////////////
61 LIST<T> append (LIST<T> x, LIST<T> y)
64 case #[h ... t]: return #[h ... append(t,y)];
68 /////////////////////////////////////////////////////////////////////////////
69 // Exercise the list patterns
70 /////////////////////////////////////////////////////////////////////////////
71 int dummy_len (LIST<int> l)
75 | #[_,_]: { return 2; }
76 | #[_,_,_]: { return 3; }
77 | #[_,_,_,_]: { return 4; }
78 | #[_,_,_,_ ... _]: { return 5; }
82 /////////////////////////////////////////////////////////////////////////////
84 /////////////////////////////////////////////////////////////////////////////
85 template <class X, class Y>
86 int depth (TREE<X,Y> t)
89 case leaf _: return 1;
90 case node(x,_,y): int a = depth(x), b = depth(y);
91 return 1 + (a > b ? a : b);
98 // Due to a compiler problem in g++ 2.5.8, I'm unable to use a
99 // typedef to abbreviate TREE<int, const char *>.
100 TREE<int, const char *> E = empty;
101 const char * This = "this";
102 const char * That = "that";
103 TREE<int, const char *> tree1 = node( E, This, leaf(2) );
104 TREE<int, const char *> tree2 = node( E, That, E );
106 EXP e1 = add(var("x"),num(1));
107 EXP e2 = sub(var("y"),num(2));
109 LIST<int> list1 = #[ 1, 2 ];
110 LIST<EXP> list2 = #[ e1, e2, var("z") ];
111 LIST<EXP> list3 = #[ num(-1), list(list2), list(list2) ];
113 cout << "tree1 = " << tree1 << "\tdepth = " << depth(tree1) << '\n';
114 cout << "tree2 = " << tree2 << "\tdepth = " << depth(tree2) << '\n';
116 cout << "list1 = " << list1
117 << "\tlength = " << length(list1)
118 << "\tsum = " << sum(list1) << '\n';
119 cout << "list2 = " << list2 << "\tlength = " << length(list2) << '\n';
120 cout << "list3 = " << list3 << "\tlength = " << length(list3) << '\n';
121 cout << "list1 + list1 = " << append(list1, list1) << '\n';
122 cout << "list2 + list3 = " << append(list2, list3) << '\n';