CanonizedExp CanonNoTopCall(TreeExp e) { CanonizedExp ce = CanonExpression(e); if (ce.Exp is ExpCall) { TreeExp call = ce.Exp; TreeExp t = new ExpTemp(new Temp()); List <TreeStm> stms = new List <TreeStm>(ce.Body); stms.Add(new StmMove(t, call)); ce = new CanonizedExp(stms, t); } return(ce); }
private static CanonizedExp Compose(CanonizedExp c, List <TreeStm> stms) { if (!stms.Any()) { return(c); } List <TreeStm> newstms = new List <TreeStm>(); newstms.AddRange(c.Body); if (Commute(stms, c.Exp)) { newstms.AddRange(stms); return(new CanonizedExp(newstms, c.Exp)); } else { TreeExp t = new ExpTemp(new Temp()); newstms.Add(new StmMove(t, c.Exp)); newstms.AddRange(stms); return(new CanonizedExp(newstms, t)); } }
private TreeExp BuildExpression(Expression expression) { switch (expression) { case Identifier id: { // TODO instance stuff if (env.ContainsKey(id.Name)) { return(new ExpTemp(env[id.Name])); } else if (parEnv.ContainsKey(id.Name)) { return(new ExpParam(parEnv[id.Name].Number)); } else if (instanceVariables.ContainsKey(id.Name)) { int index = -1; for (int i = 0; i < vshit.RawClass[currentClass].Length; i++) { if (vshit.RawClass[currentClass][i] == id.Name) { index = i; } } if (index < 0) { throw new Exception("Instance Variable not found"); } return(new ExpMem(new ExpBinOp(ExpBinOp.Op.PLUS, new ExpParam(0), new ExpBinOp(ExpBinOp.Op.MUL, new ExpConst(index), new ExpConst(WORDSIZE))))); } else { throw new Exception("Could not find id in environment"); } } case And and: { Label labelT = new Label(); Label labelF = new Label(); Label exit = new Label(); ExpTemp leftT = new ExpTemp(new Temp()); ExpTemp rightT = new ExpTemp(new Temp()); return(new ExpESeq(new StmSeq(new List <TreeStm>() { new StmCJump(StmCJump.Relation.EQ, BuildExpression(and.Left), new ExpConst(1), labelT, labelF), new StmLabel(labelT), new StmMove(rightT, BuildExpression(and.Right)), new StmMove(leftT, new ExpConst(1)), new StmJump(new ExpName(exit), new List <Label> { exit }), new StmLabel(labelF), new StmMove(rightT, new ExpConst(0)), new StmMove(leftT, new ExpConst(0)), new StmLabel(exit) }), new ExpBinOp(ExpBinOp.Op.AND, leftT, rightT))); } case Plus plus: { return(new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(plus.Left), BuildExpression(plus.Right))); } case Minus minus: { return(new ExpBinOp(ExpBinOp.Op.MINUS, BuildExpression(minus.Left), BuildExpression(minus.Right))); } case Times times: { return(new ExpBinOp(ExpBinOp.Op.MUL, BuildExpression(times.Left), BuildExpression(times.Right))); } case Division division: { return(new ExpBinOp(ExpBinOp.Op.DIV, BuildExpression(division.Left), BuildExpression(division.Right))); } case LessThan lt: { Label ltrue = new Label(); Label lfalse = new Label(); Temp temp = new Temp(); return(new ExpESeq(new StmSeq(new List <TreeStm>() { new StmMove(new ExpTemp(temp), new ExpConst(0)), new StmCJump(StmCJump.Relation.LT, BuildExpression(lt.Left), BuildExpression(lt.Right), ltrue, lfalse), new StmLabel(ltrue), new StmMove(new ExpTemp(temp), new ExpConst(1)), new StmLabel(lfalse) }), new ExpTemp(temp))); } case GreaterThan gt: { throw new Exception("Not implemented"); // i dont care TODO } case ArrayAccess arrAcc: { ExpMem lengthMem = new ExpMem(BuildExpression(arrAcc.Index)); Label ltrue1 = new Label(); Label lfalse1 = new Label(); Label labelExit1 = new Label(); ExpTemp test1 = new ExpTemp(new Temp()); Label ltrue2 = new Label(); Label lfalse2 = new Label(); Label labelExit2 = new Label(); ExpTemp test2 = new ExpTemp(new Temp()); Label allTrue = new Label(); Label allFalse = new Label(); ExpTemp allTest = new ExpTemp(new Temp()); ExpConst trueConst = new ExpConst(1); ExpConst falseConst = new ExpConst(0); ExpTemp result = new ExpTemp(new Temp()); ExpCall error = new ExpCall(new ExpName(RAISE), new List <TreeExp>() { new ExpConst(1) }); ExpMem positiveResult = new ExpMem(new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(arrAcc.Index), new ExpBinOp(ExpBinOp.Op.MUL, new ExpConst(WORDSIZE), new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(arrAcc.Val), new ExpConst(1))))); Label labelExit = new Label(); // TODO überprüfen, ob sich der wert in den Arraygrenzen befindet sonst L_Raise callen return(new ExpESeq(new StmSeq(new List <TreeStm>() { new StmCJump(StmCJump.Relation.EQ, new ExpBinOp(ExpBinOp.Op.AND, new ExpESeq(new StmSeq(new List <TreeStm>() { new StmCJump(StmCJump.Relation.LT, BuildExpression(arrAcc.Val), lengthMem, ltrue1, lfalse1), new StmLabel(ltrue1), new StmMove(test1, trueConst), new StmJump(new ExpName(labelExit1), new List <Label>() { labelExit1 }), new StmLabel(lfalse1), new StmMove(test1, falseConst), new StmLabel(labelExit1) }), test1), new ExpESeq(new StmSeq(new List <TreeStm>() { new StmCJump(StmCJump.Relation.GE, BuildExpression(arrAcc.Val), falseConst, ltrue2, lfalse2), new StmLabel(ltrue2), new StmMove(test2, trueConst), new StmJump(new ExpName(labelExit2), new List <Label>() { labelExit2 }), new StmLabel(lfalse2), new StmMove(test2, falseConst), new StmLabel(labelExit2) }), test2) ), new ExpConst(1), allTrue, allFalse), new StmLabel(allTrue), new StmMove(result, positiveResult), new StmJump(new ExpName(labelExit), new List <Label>() { labelExit }), new StmLabel(allFalse), new StmMove(result, error), new StmLabel(labelExit) }), result)); //return new ExpMem(new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(arrAcc.Index), new ExpBinOp(ExpBinOp.Op.MUL, new ExpConst(WORDSIZE), new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(arrAcc.Val), new ExpConst(1))))); } case ArrayLength arrlength: { return(new ExpMem(BuildExpression(arrlength.Exp))); } case MethodCall call: { List <TreeExp> parameters = new List <TreeExp>(); if (call.Exp is This) { parameters.Add(new ExpParam(0)); } else { parameters.Add(BuildExpression(call.Exp)); } foreach (var parameter in call.Parameters) { parameters.Add(BuildExpression(parameter)); } return(new ExpCall(new ExpName(new Label(call.EnhancedName)), parameters)); } case Read read: { //TODO throw new Exception("Not implemented"); } case IntegerLit integerLit: { return(new ExpConst(integerLit.Val)); } case BooleanLit booleanLit: { int val; val = booleanLit.Val ? 1 : 0; return(new ExpConst(val)); } case This t: { return(new ExpParam(0)); } case ArrayInstantiation arrayInst: { Temp temptemp = new Temp(); return(new ExpESeq(new StmSeq(new List <TreeStm> { new StmMove(new ExpTemp(temptemp), new ExpCall(new ExpName(HALLOC), new List <TreeExp> { new ExpBinOp(ExpBinOp.Op.MUL, new ExpBinOp(ExpBinOp.Op.PLUS, BuildExpression(arrayInst.Length), new ExpConst(1)), new ExpConst(WORDSIZE)) })), new StmMove(new ExpMem(new ExpTemp(temptemp)), BuildExpression(arrayInst.Length)) }), new ExpTemp(temptemp))); } case ObjectInstantiation objInst: { return(new ExpCall(new ExpName(HALLOC), new List <TreeExp> { new ExpConst((vshit.RawClass[objInst.ObjectId].Length) * WORDSIZE) })); } case Not not: { return(new ExpBinOp(ExpBinOp.Op.MINUS, new ExpConst(1), BuildExpression(not.Exp))); } case Parent par: { return(BuildExpression(par.Exp)); } default: { throw new Exception("Your expression is weird."); } } }