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)
56 | view 10 => CALL { func : Exp = this->u.children.l,
57 argument : Exp = this->u.children.r}
60 std::ostream& operator << (std::ostream& s, const Exp& e)
62 { NONE: { return s << "NONE"; }
63 | INT i: { return s << i; }
64 | ID x: { return s << x; }
65 | ADD (x,y): { return s << '(' << x << " + " << y << ')'; }
66 | SUB (x,y): { return s << '(' << x << " - " << y << ')'; }
67 | MUL (x,y): { return s << '(' << x << " * " << y << ')'; }
68 | DIV (x,y): { return s << '(' << x << " / " << y << ')'; }
72 int eval(const Exp& e)
75 | INT i: { return i; }
77 | ADD (x,y): { return eval(x) + eval(y); }
78 | SUB (x,y): { return eval(x) - eval(y); }
79 | MUL (x,y): { return eval(x) * eval(y); }
80 | DIV (x,INT 0) | x != NONE: { cerr << "Division by zero\n"; return 0; }
81 | DIV (x,y): { return eval(x) / eval(y); }
87 rewrite (e) type (Exp)
88 { ADD(INT i, INT j): INT(i+j)
89 | SUB(INT i, INT j): INT(i-j)
90 | MUL(INT i, INT j): INT(i*j)
91 | DIV(INT i, INT j): INT(i/j)
96 { Exp e = ADD(MUL(INT(5),INT(2)),DIV(INT(30),INT(6)));
97 cout << "Expression = " << e << endl;
98 cout << "Eval(" << e << ") = " << eval(e) << endl;
100 cout << "Simplified = " << e << endl;
101 assert(eval(e) == 15);
105 Exp e = CALL'{ func = INT(1), argument = INT(2) };