gcc config
[prop.git] / prop-src / T3.pcc
blobaa99babef26492bbc353cb0557c653b8ef211598
1 //
2 //  Test the view mechanism
3 //
5 #include <assert.h>
6 #include <iostream>
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     | view 10    => CALL { func : Exp = this->u.children.l,
57                            argument : Exp = this->u.children.r}
58     ;
60 std::ostream& operator << (std::ostream& s, const Exp& e)
61 {  match (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 << ')'; }
69    }
72 int eval(const Exp& e)
73 {  match (e) 
74    {  NONE:      { return 0; }
75    |  INT i:     { return i; }
76    |  ID x:      { return 0; }
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); }
82    }
85 void simplify(Exp& e)
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)
92    }
95 int main()
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;
99    simplify(e);
100    cout << "Simplified = " << e << endl;
101    assert(eval(e) == 15);
102    return 0;
105 Exp e = CALL'{ func = INT(1), argument = INT(2) };