/********************************************** * AOSD 10 Submission Files * * asm.beh : * * Contains all the Exp handcoded methods * * * *********************************************/ include "asm.beh"; Exp{{ public abstract int eval(Env ev); public int eval(){ return eval(Env.empty); } public abstract List compile(List env); public abstract Exp simplify(); public abstract int maxEnv(); public static abstract class Vis{ public abstract X visit(Num n); public abstract X visit(Var v); public abstract X visit(Bin b); public abstract X visit(Def d); public abstract X visit(Ifz i); } public abstract X accept(Vis v); public boolean isNum(){ return false; } public boolean isZero(){ return false; } static class Zero extends Num{ Zero(){ super(0); } public boolean isZero(){ return true; } } }} Oper{{ public abstract int eval(int l, int r); public abstract List compile(List env); public static abstract class Vis{ public abstract X visit(Sub s); } public abstract X accept(Vis v); public boolean isSub(){ return false; } }} Num {{ public int eval(Env ev){ return val; } public List compile(List env){ return List.create(new Push(val)); } public X accept(Vis v){ return v.visit(this); } public boolean isNum(){ return true; } public Exp simplify(){ return val == 0?new Zero():this; } public int maxEnv(){ return 0; } }} Var {{ public int eval(Env ev){ return ev.apply(id); } public List compile(List env){ return List.create(new Load(env.index(id))); } public X accept(Vis v){ return v.visit(this); } public Exp simplify(){ return new Var(id); } public int maxEnv(){ return 0; } }} Sub {{ public int eval(int l, int r){ return l-r; } public List compile(List env){ return List.create(new Minus()); } public X accept(Vis v){ return v.visit(this); } public boolean isSub(){ return true; } }} Bin {{ public int eval(Env ev){ return op.eval(left.eval(ev), right.eval(ev)); } public List compile(List env){ return right.compile(env) .append(left.compile(env)) .append(op.compile(env)); } public X accept(Vis v){ return v.visit(this); } public Exp simplify(){ Exp l = left.simplify(), r = right.simplify(); if(op.isSub()){ if(left.isNum()){ if(right.isNum()){ if(right.isZero()){ return left; }else{ return new Num(((Num)left).val-((Num)right).val).simplify(); } } }else{ if(right.isZero()){ return left; } } } return new Bin(op,l,r); } public int maxEnv(){ return Math.max(left.maxEnv(),right.maxEnv()); } }} Def {{ public int eval(Env ev){ return body.eval(ev.extend(id, e.eval(ev))); } public List compile(List env){ return e.compile(env) .append(new Define()) .append(body.compile(env.push(id))) .append(new Undef()); } public X accept(Vis v){ return v.visit(this); } public Exp simplify(){ Exp ee = e.simplify(), b = body.simplify(); if(b.isNum())return b; return new Def(id,ee,b); } public int maxEnv(){ return Math.max(e.maxEnv(),1+body.maxEnv()); } }} Ifz {{ public int eval(Env ev){ return cnd.eval(ev)==0?thn.eval(ev):els.eval(ev); } static int lnum = 0; synchronized ident fresh(String s){ return new ident(s+"_"+lnum++); } public List compile(List env){ ident le = fresh("else"), ld = fresh("done"); return cnd.compile(env) .append(new IfNZ(le)) .append(thn.compile(env)) .append(new Jmp(ld)) .append(new Label(le)).append(els.compile(env)) .append(new Label(ld)); } public X accept(Vis v){ return v.visit(this); } public Exp simplify(){ Exp c = cnd.simplify(), t = thn.simplify(), e = els.simplify(); if(c.isNum()){ if(c.isZero())return t; else return e; } return new Ifz(c,t,e); } public int maxEnv(){ return Math.max(cnd.maxEnv(), Math.max(thn.maxEnv(), els.maxEnv())); } }} // Environments Env{{ static Env empty = new EmptyEnv(); int apply(ident id){ throw error.nodef(id); } Env extend(ident id, int v){ return new ExtEnv(id,v,this); } Env unextend(){ throw new RuntimeException("Can\'t unextend the empty env"); } }} Extenv{{ int apply(ident i){ return (id.equals(i))? v : rest.apply(i); } Env unextend(){ return rest; } }} error{{ public error(String s){ super(s); } static error nodef(ident id){ return new error("Def not found :"+id); } }}