Merge remote branch 'master'
[prop.git] / tests / poly1.pcc
blob8862535f10ec52d3eab35a576384bb04d901f138
1 /////////////////////////////////////////////////////////////////////////////
2 //  Testing polymorphic datatypes.
3 //  (and garbage collection, reference counting etc.)
4 /////////////////////////////////////////////////////////////////////////////
6 //
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
18    = num  (int)          => _
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
26    ;
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 /////////////////////////////////////////////////////////////////////////////
39 template <class T>
40    int length(LIST<T> l)
41    {  match (l) 
42       {  #[]:         { return 0; }
43       |  #[h ... t]:  { return 1 + length(t); }
44       }
45    }
47 /////////////////////////////////////////////////////////////////////////////
48 //  Sum an integer list
49 /////////////////////////////////////////////////////////////////////////////
50 int sum (LIST<int> l)
51 {  match (l)
52    {  #[]:        { return 0; }
53    |  #[h ... t]: { return h + sum(t); }
54    } 
57 /////////////////////////////////////////////////////////////////////////////
58 //  Append two lists
59 /////////////////////////////////////////////////////////////////////////////
60 template <class T>
61    LIST<T> append (LIST<T> x, LIST<T> y)
62    {  match (x) {
63          case #[]:        return y;
64          case #[h ... t]: return #[h ... append(t,y)];
65       }
66    }
68 /////////////////////////////////////////////////////////////////////////////
69 //   Exercise the list patterns
70 /////////////////////////////////////////////////////////////////////////////
71 int dummy_len (LIST<int> l)
72 {  match (l) 
73    {  #[]:              { return 0; }
74    |  #[_]:             { return 1; }
75    |  #[_,_]:           { return 2; }
76    |  #[_,_,_]:         { return 3; }
77    |  #[_,_,_,_]:       { return 4; }
78    |  #[_,_,_,_ ... _]: { return 5; }
79    }
82 /////////////////////////////////////////////////////////////////////////////
83 //  Depth of a tree
84 /////////////////////////////////////////////////////////////////////////////
85 template <class X, class Y>
86    int depth (TREE<X,Y> t)
87    {  match (t) {
88          case empty:       return 0;
89          case leaf _:      return 1;
90          case node(x,_,y): int a = depth(x), b = depth(y);
91                            return 1 + (a > b ? a : b);
92       }
93    }
96 int main()
97 {  
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) ];
112   
113    cout << "tree1 = " << tree1 << "\tdepth = " << depth(tree1) << '\n';
114    cout << "tree2 = " << tree2 << "\tdepth = " << depth(tree2) << '\n';
115   
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';
124    return 0;