initial
[prop.git] / tests / prop6.pcc
blobf0b3c387286b7ac6fd9db03854c59f70edf058f0
1 //
2 //  Test the view mechanism
3 //
5 #include <assert.h>
6 #include <iostream.h>
8 enum exp_tag { Int = 1, Ident, Add, Sub, Mul, Div };
10 struct exp {
11    enum exp_tag tag;
12    union {
13       int number;
14       const char * ident;
15       struct { struct exp * l, * r; } children;
16    } u;
19 typedef struct exp * Exp;
21 Exp INT(int i) 
22 {  Exp e = new exp; e->tag = Int; e->u.number = i; return e; }
24 Exp ID(const char * id) 
25 {  Exp e = new exp; e->tag = Ident; e->u.ident = id; return e; }
27 Exp ADD(Exp a, Exp b)
28 {  Exp e = new exp; e->tag = Add; e->u.children.l = a; e->u.children.r = b;
29    return e;
31    
32 Exp SUB(Exp a, Exp b)
33 {  Exp e = new exp; e->tag = Sub; e->u.children.l = a; e->u.children.r = b;
34    return e;
36    
37 Exp MUL(Exp a, Exp b)
38 {  Exp e = new exp; e->tag = Mul; e->u.children.l = a; e->u.children.r = b;
39    return e;
41    
42 Exp DIV(Exp a, Exp b)
43 {  Exp e = new exp; e->tag = Div; e->u.children.l = a; e->u.children.r = b;
44    return e;
46    
47 datatype Exp :: view
48     = match (this ? this->tag : 0)
49       view 0     => NONE
50     | view Int   => INT (int = this->u.number) 
51     | view Ident => ID (const char * = this->u.ident) 
52     | view Add   => ADD (Exp = this->u.children.l, Exp = this->u.children.r)
53     | view Sub   => SUB (Exp = this->u.children.l, Exp = this->u.children.r)
54     | view Mul   => MUL (Exp = this->u.children.l, Exp = this->u.children.r)
55     | view Div   => DIV (Exp = this->u.children.l, Exp = this->u.children.r)
56     ;
58 ostream& operator << (ostream& s, const Exp& e)
59 {  match (e)
60    {  NONE:      { return s << "NONE"; }
61    |  INT i:     { return s << i; }
62    |  ID x:      { return s << x; }
63    |  ADD (x,y): { return s << '(' << x << " + " << y << ')'; }
64    |  SUB (x,y): { return s << '(' << x << " - " << y << ')'; }
65    |  MUL (x,y): { return s << '(' << x << " * " << y << ')'; }
66    |  DIV (x,y): { return s << '(' << x << " / " << y << ')'; }
67    }
70 int eval(const Exp& e)
71 {  match (e) 
72    {  NONE:      { return 0; }
73    |  INT i:     { return i; }
74    |  ID x:      { return 0; }
75    |  ADD (x,y): { return eval(x) + eval(y); }
76    |  SUB (x,y): { return eval(x) - eval(y); }
77    |  MUL (x,y): { return eval(x) * eval(y); }
78    |  DIV (x,INT 0): { cerr << "Division by zero\n"; return 0; }
79    |  DIV (x,y): { return eval(x) / eval(y); }
80    }
83 void simplify(Exp& e)
85    rewrite (e) type (Exp)
86    {  ADD(INT i, INT j): INT(i+j)
87    |  SUB(INT i, INT j): INT(i-j)
88    |  MUL(INT i, INT j): INT(i*j)
89    |  DIV(INT i, INT j): INT(i/j)
90    }
93 int main()
94 {  Exp e = ADD(MUL(INT(5),INT(2)),DIV(INT(30),INT(6)));
95    cout << "Expression = " << e << endl;
96    cout << "Eval(" << e << ") = " << eval(e) << endl;
97    simplify(e);
98    cout << "Simplified = " << e << endl;
99    assert(eval(e) == 15);
100    return 0;