2 // Test the view mechanism
8 enum exp_tag { Int = 1, Ident, Add, Sub, Mul, Div };
15 struct { struct exp * l, * r; } children;
19 typedef struct exp * Exp;
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; }
28 { Exp e = new exp; e->tag = Add; e->u.children.l = a; e->u.children.r = b;
33 { Exp e = new exp; e->tag = Sub; e->u.children.l = a; e->u.children.r = b;
38 { Exp e = new exp; e->tag = Mul; e->u.children.l = a; e->u.children.r = b;
43 { Exp e = new exp; e->tag = Div; e->u.children.l = a; e->u.children.r = b;
48 = match (this ? this->tag : 0)
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)
58 ostream& operator << (ostream& s, const Exp& 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 << ')'; }
70 int eval(const Exp& e)
73 | INT i: { return i; }
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); }
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)
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;
98 cout << "Simplified = " << e << endl;
99 assert(eval(e) == 15);