/* AST ::= BoolConstant | IntConstant | NullConstant | Variable | PrimFun | UnOpApp | BinOpApp | App | Map | If | Let */ /* AST class definitions */ /** The AST type which supports a visitor interface */ interface AST { public ResType accept(ASTVisitor v); } /** The visitor interface for processing ASTs. * AST ::= BoolConstant | IntConstant | NullConstant | Variable | PrimFun | UnOpApp | BinOpApp | App | Map | If | Let */ interface ASTVisitor { ResType forBoolConstant(BoolConstant b); ResType forIntConstant(IntConstant i); ResType forNullConstant(NullConstant n); ResType forVariable(Variable v); ResType forPrimFun(PrimFun f); ResType forUnOpApp(UnOpApp u); ResType forBinOpApp(BinOpApp b); ResType forApp(App a); ResType forMap(Map m); ResType forIf(If i); ResType forLet(Let l); } /** An important SubType of the AST Type but it does not have its own visitor interface. Visited as part of AST type. * Term ::= Constant | PrimFun | Variable */ interface Term extends AST {} /** The subtype of Term consisting of atomic constants. * Constant ::= IntConstant | BoolConstant | NullConstant */ interface Constant extends Term {} /** Class representing an application of a unary operator. */ class UnOpApp implements AST { private UnOp rator; private AST arg; UnOpApp(UnOp r, AST a) { rator = r; arg = a; } public UnOp rator() { return rator; } public AST arg() { return arg; } public ResType accept(ASTVisitor v) { return v.forUnOpApp(this); } public String toString() { return rator + " " + arg; } } /** Class representing an application of a binary operator. */ class BinOpApp implements AST { private BinOp rator; private AST arg1, arg2; BinOpApp(BinOp r, AST a1, AST a2) { rator = r; arg1 = a1; arg2 = a2; } public BinOp rator() { return rator; } public AST arg1() { return arg1; } public AST arg2() { return arg2; } public ResType accept(ASTVisitor v) { return v.forBinOpApp(this); } public String toString() { return "(" + arg1 + " " + rator + " " + arg2 + ")"; } } /** Class representing a Map (Jam syntax for a lambda-expression). */ class Map implements AST { private Variable[] vars; private AST body; Map(Variable[] v, AST b) { vars = v; body = b; } public Variable[] vars() { return vars; } public AST body() { return body; } public ResType accept(ASTVisitor v) { return v.forMap(this); } public String toString() { return "map " + ToString.toString(vars,",") + " to " + body ; } } /** Class representing a function application. */ class App implements AST { private AST rator; private AST[] args; App(AST r, AST[] a) { rator = r; args = a; } public AST rator() { return rator; } public AST[] args() { return args; } public ResType accept(ASTVisitor v) { return v.forApp(this); } public String toString() { if ((rator instanceof PrimFun) || (rator instanceof Variable)) return rator + "(" + ToString.toString(args,", ") + ")"; else return "(" + rator + ")(" + ToString.toString(args,", ") + ")"; } } /** Class representing an if expression. */ class If implements AST { private AST test, conseq, alt; If(AST t, AST c, AST a) { test = t; conseq = c; alt = a; } public AST test() { return test; } public AST conseq() { return conseq; } public AST alt() { return alt; } public ResType accept(ASTVisitor v) { return v.forIf(this); } public String toString() { return "if " + test + " then " + conseq + " else " + alt ; } } /** Class representing a let expression. */ class Let implements AST { private Def[] defs; private AST body; Let(Def[] d, AST b) { defs = d; body = b; } public ResType accept(ASTVisitor v) { return v.forLet(this); } public Def[] defs() { return defs; } public AST body() { return body; } /** Returns the vars that are locally defined in this Let. */ public Variable[] vars() { int n = defs.length; Variable[] vars = new Variable[n]; for(int i = 0; i < n; i++) { vars[i] = defs[i].lhs(); } return vars; } /** Returns the exps that appear on the rhs of defs in this Let. */ public AST[] exps() { int n = defs.length; AST[] exps = new AST[n]; for(int i = 0; i < n; i++) { exps[i] = defs[i].rhs(); } return exps; } public String toString() { return "let " + ToString.toString(defs," ") + " in " + body; } } /** Class representing a unary operator within a UnOppApp. UnOp is an AST component type but it is NOT a subtype. It * has its own visitor interface. * UnOp ::= UnOpPlus | UnOpMinus | OpTilde */ abstract class UnOp { String name; public UnOp(String s) { name = s; } public String toString() { return name; } public abstract ResType accept(UnOpVisitor v); } /** Visitor for the UnOp union type. */ interface UnOpVisitor { ResType forUnOpPlus(UnOpPlus op); ResType forUnOpMinus(UnOpMinus op); ResType forOpTilde(OpTilde op); // ResType forOpBang(OpBang op); // Supports ref cell extension to Jam // ResType forOpRef(OpRef op); // Supports ref cell extension to Jam } /** Class representing + as a unary operator. */ class UnOpPlus extends UnOp { public static final UnOpPlus ONLY = new UnOpPlus(); private UnOpPlus() { super("+"); } public ResType accept(UnOpVisitor v) { return v.forUnOpPlus(this); } } /** Class representing - as a unary operator. */ class UnOpMinus extends UnOp { public static final UnOpMinus ONLY = new UnOpMinus(); private UnOpMinus() { super("-"); } public ResType accept(UnOpVisitor v) { return v.forUnOpMinus(this); } } /** Class representing ~ as a unary operator. */ class OpTilde extends UnOp { public static final OpTilde ONLY = new OpTilde(); private OpTilde() { super("~"); } public ResType accept(UnOpVisitor v) { return v.forOpTilde(this); } } ///* Supports ref cell extension to Jam */ ///** Class representing ! as unary operator. */ //class OpBang extends UnOp { // public static final OpBang ONLY = new OpBang(); // private OpBang() { super("!"); } // public ResType accept(UnOpVisitor v) { // return v.forOpBang(this); // } //} ///** Class representing ref as unary operator. */ //class OpRef extends UnOp { // public static final OpRef ONLY = new OpRef(); // private OpRef() { super("ref"); } // public ResType accept(UnOpVisitor v) { // return v.forOpRef(this); // } //} /** Class representing the binary operator within a BinOppApp. BinOp is an AST component type but it is NOT a subtype. * It has its own visitor interface. * BinOp ::= BinOpPlus | BinOpMinus | OpTimes | OpDivide | OpEquals | OpNotEquals | OpLessThan | OpGreaterThan | * OpLessThanOrEquals OpGreaterThanOrEquals | OpAnd | OpOr */ abstract class BinOp { String name; public BinOp(String s) { name = s; } public String toString() { return name; } public abstract ResType accept(BinOpVisitor v); } /** Visitor for the BinOp union type. */ interface BinOpVisitor { ResType forBinOpPlus(BinOpPlus op); ResType forBinOpMinus(BinOpMinus op); ResType forOpTimes(OpTimes op); ResType forOpDivide(OpDivide op); ResType forOpEquals(OpEquals op); ResType forOpNotEquals(OpNotEquals op); ResType forOpLessThan(OpLessThan op); ResType forOpGreaterThan(OpGreaterThan op); ResType forOpLessThanEquals(OpLessThanEquals op); ResType forOpGreaterThanEquals(OpGreaterThanEquals op); ResType forOpAnd(OpAnd op); ResType forOpOr(OpOr op); // ResType forOpGets(OpGets op); // Supports the ref cell extension to Jam } /** Class representing + as a binary operator. */ class BinOpPlus extends BinOp { public static final BinOpPlus ONLY = new BinOpPlus(); private BinOpPlus() { super("+"); } public ResType accept(BinOpVisitor v) { return v.forBinOpPlus(this); } } /** Class representing - as a binary operator. */ class BinOpMinus extends BinOp { public static final BinOpMinus ONLY = new BinOpMinus(); private BinOpMinus() { super("-"); } public ResType accept(BinOpVisitor v) { return v.forBinOpMinus(this); } } /** Class representing * as a binary operator. */ class OpTimes extends BinOp { public static final OpTimes ONLY = new OpTimes(); private OpTimes() { super("*"); } public ResType accept(BinOpVisitor v) { return v.forOpTimes(this); } } /** Class representing / as a binary operator. */ class OpDivide extends BinOp { public static final OpDivide ONLY = new OpDivide(); private OpDivide() { super("/"); } public ResType accept(BinOpVisitor v) { return v.forOpDivide(this); } } /** Class representing = as a binary operator. */ class OpEquals extends BinOp { public static final OpEquals ONLY = new OpEquals(); private OpEquals() { super("="); } public ResType accept(BinOpVisitor v) { return v.forOpEquals(this); } } /** Class representing != as a binary operator. */ class OpNotEquals extends BinOp { public static final OpNotEquals ONLY = new OpNotEquals(); private OpNotEquals() { super("!="); } public ResType accept(BinOpVisitor v) { return v.forOpNotEquals(this); } } /** Class representing < as a binary operator. */ class OpLessThan extends BinOp { public static final OpLessThan ONLY = new OpLessThan(); private OpLessThan() { super("<"); } public ResType accept(BinOpVisitor v) { return v.forOpLessThan(this); } } /** Class representing > as a binary operator. */ class OpGreaterThan extends BinOp { public static final OpGreaterThan ONLY = new OpGreaterThan(); private OpGreaterThan() { super(">"); } public ResType accept(BinOpVisitor v) { return v.forOpGreaterThan(this); } } /** Class representing <= as a binary operator. */ class OpLessThanEquals extends BinOp { public static final OpLessThanEquals ONLY = new OpLessThanEquals(); private OpLessThanEquals() { super("<="); } public ResType accept(BinOpVisitor v) { return v.forOpLessThanEquals(this); } } /** Class representing >= as a binary operator. */ class OpGreaterThanEquals extends BinOp { public static final OpGreaterThanEquals ONLY = new OpGreaterThanEquals(); private OpGreaterThanEquals() { super(">="); } public ResType accept(BinOpVisitor v) { return v.forOpGreaterThanEquals(this); } } /** Class representing & as a binary operator. */ class OpAnd extends BinOp { public static final OpAnd ONLY = new OpAnd(); private OpAnd() { super("&"); } public ResType accept(BinOpVisitor v) { return v.forOpAnd(this); } } /** Class representing | as a binary operator. */ class OpOr extends BinOp { public static final OpOr ONLY = new OpOr(); private OpOr() { super("|"); } public ResType accept(BinOpVisitor v) { return v.forOpOr(this); } } ///* Supports the ref cell extension to Jam */ ///** Class representing <- as binary operator. */ //class OpGets extends BinOp { // public static final OpGets ONLY = new OpGets(); // private OpGets() { super("<-"); } // public ResType accept(BinOpVisitor v) { // return v.forOpGets(this); // } //} /** Class representing a definition embedded inside a Let. It can appear as a component of an AST but is NOT as AST. */ class Def { private Variable lhs; private AST rhs; Def(Variable l, AST r) { lhs = l; rhs = r; } public Variable lhs() { return lhs; } public AST rhs() { return rhs; } public String toString() { return lhs + " := " + rhs + ";"; } }