#include <stdlib.h>
#include <stdio.h>

enum ExprTag { Neg, Int, Plus, Times };
struct Expr {
  enum ExprTag tag;
  union {
    int i;
    struct Expr * uni;
    struct { struct Expr * l; struct Expr * r; } bin;
  } u;
};

int eval(struct Expr * e) {
  if (e->tag == Int) {
    return e->u.i;
  }
  else if (e->tag == Neg) {
    return - eval(e->u.uni);
  }
  else if (e->tag == Plus) {
    return eval(e->u.bin.l) + eval(e->u.bin.r);
  }
  else {
    return eval(e->u.bin.l) * eval(e->u.bin.r);
  }
}

struct Expr * mkInt(int i) {
  struct Expr * e = (struct Expr *) malloc(sizeof(struct Expr));
  //e->tag = Int;
  e->u.i = i;
  return e;
}

struct Expr * mkNeg(struct Expr * c) {
  struct Expr * e = (struct Expr *) malloc(sizeof(struct Expr));
  //e->tag = Neg;
  e->u.uni = c;
  return e;
}

struct Expr * mkBin(enum ExprTag tag, struct Expr * l, struct Expr * r) {
  struct Expr * e = (struct Expr *) malloc(sizeof(struct Expr));
  //e->tag = tag;
  e->u.bin.l = l;
  e->u.bin.r = r;
  return e;
}

int main() {
  struct Expr * ex = mkBin(Plus, mkInt(2), mkNeg(mkInt(3)));
  printf("result = %d\n", eval(ex));
  return 0;
}

