// cexp3ast.ast
// simple expression AST

verbatim {
  inline string toString(Exp const *e) {
    return stringc << (void*)e;
  }
}

class Exp {
  // reference count
  private int refCt;
  public void incRefCt();
  public void decRefCt();      // deletes when it hits 0
  
  // whoever creates this object initially is its first owner,
  // hence the refct starts at 1
  ctor { refCt=0; incRefCt(); };

  // number of nodes in this subtree, including myself
  public(func) virtual int numNodes() const = 0;

  // evaluate the arithmetic value of the subtree
  public(func) virtual int eval() const = 0;

  // merge alternative interpretations
  public static Exp *mergeAlts(Exp *p1, Exp *p2);

  // expression containing simply a literal integer
  -> E_int(int i) {
    public int numNodes() const
      { return 1; };
    public int eval() const
      { return i; };
  }

  // 'op' can be either '+' or '*' 
  // the explicit pointer notation means "serf"
  -> E_op(char op, Exp *left, Exp *right) {
    dtor {
      left->decRefCt();
      right->decRefCt();
    };
    public int numNodes() const
      { return 1 + left->numNodes() + right->numNodes(); };
    public int eval() const {
      int L = left->eval();
      int R = right->eval();
      return op=='+'? L+R : L*R;
    };
  }
}
