more typename fixes
[prop.git] / tests / prop5.pcc
blob6c948f11f27e70cc79dc788b7047f8195d2294e0
1 //
2 //  Test the view mechanism
3 //
5 #include <assert.h>
6 #include <iostream.h>
8 class Expression
10 public:
11    enum Variant { Int, Ident, Add, Sub, Mul, Div };
12    virtual Variant get_variant() const = 0;
13    virtual int  number() const;
14    virtual const char * ident() const;
15    virtual const Expression * child(int) const;
16    virtual Expression *& child(int);
19 typedef Expression * Exp;
21 int Expression::number() const 
22 { cerr << "unimplement Expression::number()\n"; exit(1); return 0; }
24 const char * Expression::ident() const 
25 { cerr << "unimplement Expression::ident()\n"; exit(1); return 0; }
27 const Expression * Expression::child(int) const 
28 { cerr << "unimplement Expression::child(int) const\n"; exit(1); return 0; }
30 Expression *& Expression::child(int) 
31 { cerr << "unimplement Expression::child(int)\n"; exit(1); 
32   static Expression * t = 0;
33   return t; 
36 class Number : public Expression {
37    int the_number;
38 public:
39    Number(int n) : the_number(n) {}
40    Variant get_variant() const { return Int; }
41    int number() const { return the_number; }
42    friend Expression * INT(int i) { return new Number(i); }
45 class Identifier : public Expression {
46    const char * the_ident;
47 public:
48    Identifier(const char * ident) : the_ident(ident) {}
49    Variant get_variant() const { return Ident; }
50    const char * ident() const { return the_ident; }
51    friend Expression * ID(const char * id) { return new Identifier(id); }
54 class Operator : public Expression {
55    char  op;
56    Expression * children[2];
57 public:
58    Operator(char o, const Expression* a, const Expression* b) : op(o) 
59       { children[0] = (Expression*)a; children[1] = (Expression*)b; }
60    Variant get_variant() const
61    {  switch (op)
62       { case '+':  return Add;
63         case '-':  return Sub;
64         case '*':  return Mul;
65         case '/':  return Div;
66         default:   return Add;
67       }
68    }
69    Expression *& child(int i) { return children[i]; }
70    const Expression * child(int i) const { return children[i]; }
72    friend Expression * ADD(const Expression * a, const Expression * b)
73    {  return new Operator('+',a,b); }
74    friend Expression * SUB(const Expression * a, const Expression * b)
75    {  return new Operator('-',a,b); }
76    friend Expression * MUL(const Expression * a, const Expression * b)
77    {  return new Operator('*',a,b); }
78    friend Expression * DIV(const Expression * a, const Expression * b)
79    {  return new Operator('/',a,b); }
82 datatype Exp :: view
83    = match (this->get_variant())
84      view Expression::Int   => INT (int = this->number()) 
85    | view Expression::Ident => ID (const char * = this->ident()) 
86    | view Expression::Add   => ADD (Exp = this->child(0), Exp = this->child(1))
87    | view Expression::Sub   => SUB (Exp = this->child(0), Exp = this->child(1))
88    | view Expression::Mul   => MUL (Exp = this->child(0), Exp = this->child(1))
89    | view Expression::Div   => DIV (Exp = this->child(0), Exp = this->child(1))
90    ;
92 ostream& operator << (ostream& s, Exp e)
93 {  match (e)
94    {  INT i:     { return s << i; }
95    |  ID x:      { return s << x; }
96    |  ADD (x,y): { return s << '(' << x << " + " << y << ')'; }
97    |  SUB (x,y): { return s << '(' << x << " - " << y << ')'; }
98    |  MUL (x,y): { return s << '(' << x << " * " << y << ')'; }
99    |  DIV (x,y): { return s << '(' << x << " / " << y << ')'; }
100    }
103 int eval(Exp e)
104 {  match (e) 
105    {  INT i:     { return i; }
106    |  ID x:      { return 0; }
107    |  ADD (x,y): { return eval(x) + eval(y); }
108    |  SUB (x,y): { return eval(x) - eval(y); }
109    |  MUL (x,y): { return eval(x) * eval(y); }
110    |  DIV (x,INT 0): { cerr << "Division by zero\n"; return 0; }
111    |  DIV (x,y): { return eval(x) / eval(y); }
112    }
115 void simplify(Exp& e)
118    rewrite (e) type (Exp)
119    {
120       ADD(INT i, INT j): INT(i+j)
121    |  SUB(INT i, INT j): INT(i-j)
122    |  MUL(INT i, INT j): INT(i*j)
123    |  DIV(INT i, INT j): INT(i/j)
124    }
127 int main()
128 {  Exp e = ADD(MUL(INT(5),INT(2)),DIV(INT(30),INT(6)));
129    cout << "Expression = " << e << endl;
130    cout << "Eval(" << e << ") = " << eval(e) << endl;
131    simplify(e);
132    cout << "Simplified = " << e << endl;
133    assert(eval(e) == 15);
134    return 0;