One simple possibility is

import std.stdio;
struct Expr{
    enum Tag { val, plus, minus }
    union{int i;struct{Expr* a, b;}}
    Tag tag;
}
Expr val(int i){ Expr e;e.tag=Expr.Tag.val;e.i=i;return e;}
Expr plus(Expr* a, Expr* b){Expr e;e.tag=Expr.Tag.plus; e.a=a; e.b=b;return e;} Expr minus(Expr* a, Expr* b){Expr e;e.tag=Expr.Tag.minus; e.a=a; e.b=b;return e;}

int eval(scope Expr* e){
    final switch(e.tag) with(Expr.Tag){
        case val:   return e.i;
        case plus:  return eval(e.a) + eval(e.b);
        case minus: return eval(e.a) - eval(e.b);
    }
}
void main(){
    auto five = val(5), three = val(3), one = val(1);
    auto add  = plus(&three, &one);
    auto sub  = minus(&five, &add);
    auto x    = eval(&sub);
    writeln("val: ",x);
}

It would of course be better if D supported ADTs.

Reply via email to