public override void DefaultIn(Node node) { if (node is PExp) { PExp exp = (PExp)node; if (finalTrans.data.ExpTypes[exp] is ANamedType) { ANamedType type = (ANamedType)finalTrans.data.ExpTypes[exp]; if (finalTrans.data.StructTypeLinks.ContainsKey(type)) { AStructDecl strDecl = finalTrans.data.StructTypeLinks[type]; if (strDecl.GetLocals().Cast <PLocalDecl>().Select(decl => decl is AALocalDecl).Count() == 0) { if (node.Parent() is AAssignmentExp) { node = node.Parent().Parent(); } MoveMethodDeclsOut mover = new MoveMethodDeclsOut("removedStructVar", finalTrans.data); node.Apply(mover); foreach (PStm pStm in mover.NewStatements) { pStm.Apply(this); } node.Parent().RemoveChild(node); if (node.Parent() is ABinopExp) { ABinopExp parent = (ABinopExp)node.Parent(); ABooleanConstExp replacer; if (parent.GetBinop() is ANeBinop || parent.GetBinop() is AGtBinop || parent.GetBinop() is ALtBinop) { replacer = new ABooleanConstExp(new AFalseBool()); } else { replacer = new ABooleanConstExp(new ATrueBool()); } finalTrans.data.ExpTypes[replacer] = new ANamedType(new TIdentifier("bool"), null); parent.ReplaceBy(replacer); } } } } } }
public override void OutABinopExp(ABinopExp node) { if (data.ExpTypes[node.GetLeft()] is ANamedType && data.StructTypeLinks.ContainsKey((ANamedType)data.ExpTypes[node.GetLeft()])) { AStructDecl str = data.StructTypeLinks[(ANamedType)data.ExpTypes[node.GetLeft()]]; PExp replacementExp = new ABooleanConstExp(new ATrueBool()); data.ExpTypes[replacementExp] = new ANamedType(new TIdentifier("bool"), null); foreach (AALocalDecl local in str.GetLocals().OfType <AALocalDecl>()) { AStructLvalue leftSide = new AStructLvalue(Util.MakeClone(node.GetLeft(), data), new ADotDotType(new TDot(".")), new TIdentifier(local.GetName().Text)); ALvalueExp leftSideExp = new ALvalueExp(leftSide); AStructLvalue rightSide = new AStructLvalue(Util.MakeClone(node.GetRight(), data), new ADotDotType(new TDot(".")), new TIdentifier(local.GetName().Text)); ALvalueExp rightSideExp = new ALvalueExp(rightSide); data.StructFieldLinks[leftSide] = data.StructFieldLinks[rightSide] = local; data.LvalueTypes[leftSide] = data.ExpTypes[leftSideExp] = data.LvalueTypes[rightSide] = data.ExpTypes[rightSideExp] = local.GetType(); ABinopExp binop = new ABinopExp(leftSideExp, (PBinop)node.GetBinop().Clone(), rightSideExp); data.ExpTypes[binop] = data.ExpTypes[node]; if (replacementExp is ABooleanConstExp) { replacementExp = binop; } else { replacementExp = new ABinopExp(replacementExp, new ALazyAndBinop(new TAndAnd("&&")), binop); data.ExpTypes[replacementExp] = new ANamedType(new TIdentifier("bool"), null); } } node.ReplaceBy(replacementExp); replacementExp.Apply(this); } base.OutABinopExp(node); }
//Join string + string to string public override void CaseABinopExp(ABinopExp node) { if (node.GetBinop() is APlusBinop) { PType type = data.ExpTypes[node]; if (type is ANamedType && ((ANamedType)type).IsPrimitive("string")) { PExp other = null; if (node.GetLeft() is ANullExp) { other = node.GetRight(); } if (node.GetRight() is ANullExp) { other = node.GetLeft(); } if (other != null) { node.ReplaceBy(other); other.Apply(this); return; } } //Case (string + string) if (node.GetLeft() is AStringConstExp && node.GetRight() is AStringConstExp) { AStringConstExp left = (AStringConstExp)node.GetLeft(); AStringConstExp right = (AStringConstExp)node.GetRight(); if (!IsJoinAllowed(left.GetStringLiteral().Text, right.GetStringLiteral().Text)) { base.CaseABinopExp(node); return; } left.GetStringLiteral().Text = left.GetStringLiteral().Text.Substring(0, left.GetStringLiteral().Text. Length - 1); left.GetStringLiteral().Text += right.GetStringLiteral().Text.Substring(1); node.ReplaceBy(left); CaseAStringConstExp(left); return; } //Case (<exp> + string) + string if (node.GetLeft() is ABinopExp && node.GetRight() is AStringConstExp) { ABinopExp leftBinop = (ABinopExp)node.GetLeft(); if (leftBinop.GetBinop() is APlusBinop && leftBinop.GetRight() is AStringConstExp) { AStringConstExp left = (AStringConstExp)leftBinop.GetRight(); AStringConstExp right = (AStringConstExp)node.GetRight(); if (!IsJoinAllowed(left.GetStringLiteral().Text, right.GetStringLiteral().Text)) { base.CaseABinopExp(node); return; } left.GetStringLiteral().Text = left.GetStringLiteral().Text.Substring(0, left.GetStringLiteral(). Text. Length - 1); left.GetStringLiteral().Text += right.GetStringLiteral().Text.Substring(1); node.ReplaceBy(leftBinop); CaseABinopExp(leftBinop); return; } } //Case string + (string + <exp>) //Case (<exp> + string) + (string + <exp>) } //Case (int + int) /*if (node.GetLeft() is AIntConstExp && node.GetRight() is AIntConstExp) * { * AIntConstExp left = (AIntConstExp) node.GetLeft(); * AIntConstExp right = (AIntConstExp) node.GetRight(); * * int a = int.Parse(left.GetIntegerLiteral().Text); * int b = int.Parse(right.GetIntegerLiteral().Text); * * if (node.GetBinop() is APlusBinop) * { * a += b; * } * else if (node.GetBinop() is AMinusBinop) * { * a -= b; * } * else if (node.GetBinop() is ATimesBinop) * { * a *= b; * } * else if (node.GetBinop() is ADivideBinop) * { * if (b == 0) * { * base.CaseABinopExp(node); * return; * } * a /= b; * } * else * { * base.CaseABinopExp(node); * return; * } * * left.GetIntegerLiteral().Text = a.ToString(); * node.ReplaceBy(left); * left.Apply(this); * return; * } * //Case (<exp> + int) + int * if (node.GetLeft() is ABinopExp && node.GetRight() is AIntConstExp && (node.GetBinop() is APlusBinop || node.GetBinop() is AMinusBinop)) * { * ABinopExp leftBinop = (ABinopExp) node.GetLeft(); * PType leftType = data.ExpTypes[leftBinop]; * if (leftBinop.GetRight() is AIntConstExp && leftType is ANamedType && ((ANamedType) leftType).GetName().Text == "int" && * (leftBinop.GetBinop() is APlusBinop || leftBinop.GetBinop() is AMinusBinop)) * { * AIntConstExp left = (AIntConstExp)leftBinop.GetRight(); * AIntConstExp right = (AIntConstExp)node.GetRight(); * int a = int.Parse(left.GetIntegerLiteral().Text); * int b = int.Parse(right.GetIntegerLiteral().Text); * * if (node.GetBinop() is APlusBinop) * { * if (leftBinop.GetBinop() is APlusBinop) * { * //(<exp> + int) + int * int c = a + b; * //Test for overflow * if (a > 0 && b > 0 && (c < a || c < b) || * a < 0 && b < 0 && (c > a || c > b)) * { * //Don't add them * base.CaseABinopExp(node); * return; * } * if (c < 0) * { * //Change binop to <exp> - c * if (c != int.MinValue) * { * c = -c; * leftBinop.SetBinop(new AMinusBinop(new TMinus("-"))); * } * } * //Replace node with leftbinop * left.GetIntegerLiteral().Text = c.ToString(); * node.ReplaceBy(leftBinop); * leftBinop.Apply(this); * return; * } * else * { * //(<exp> - int) + int * int c = b - a; * //Test for overflow * if (a < 0 && b > 0 && (c < a || c < b) || * a > 0 && b < 0 && (c > a || c > b)) * { * //Don't add them * base.CaseABinopExp(node); * return; * } * if (c > 0 || c == int.MinValue) * { * //Change binop to <exp> + c * leftBinop.SetBinop(new APlusBinop(new TPlus("+"))); * * } * else * c = -c; * //Replace node with leftbinop * left.GetIntegerLiteral().Text = c.ToString(); * node.ReplaceBy(leftBinop); * leftBinop.Apply(this); * return; * } * } * else * { * if (leftBinop.GetBinop() is APlusBinop) * { * //(<exp> + int) - int * //ALso need to consider <exp> in the other position, and int on the other side of the binop * //Make a more general algorithm * } * else * { * * } * } * } * }*/ base.CaseABinopExp(node); }
public override void CaseABinopExp(ABinopExp node) { bool pushed = false; if (!(node.Parent() is ABinopExp)) { PushStack(); pushed = true; } try { bool isIntegerType = data.ExpTypes[node] is ANamedType && (((ANamedType)data.ExpTypes[node]).IsPrimitive("int") || ((ANamedType)data.ExpTypes[node]).IsPrimitive("byte")); if (isIntegerType) { if (node.GetBinop() is APlusBinop || node.GetBinop() is AMinusBinop) { node.GetLeft().Apply(this); if (!Util.HasAncestor <AAProgram>(node)) { return; } if (node.GetBinop() is AMinusBinop) { isNegativeRightSide = !isNegativeRightSide; } node.GetRight().Apply(this); if (node.GetBinop() is AMinusBinop) { isNegativeRightSide = !isNegativeRightSide; } if (!Util.HasAncestor <AAProgram>(node)) { return; } for (int i = 0; i < intConsts.Count; i++) { for (int j = i + 1; j < intConsts.Count; j++) { Pair <AIntConstExp, bool> const1 = intConsts[i]; Pair <AIntConstExp, bool> const2 = intConsts[j]; ABinopExp pBinop1 = (ABinopExp)const1.Car.Parent(); ABinopExp pBinop2 = (ABinopExp)const2.Car.Parent(); int a = int.Parse(const1.Car.GetIntegerLiteral().Text); int b = int.Parse(const2.Car.GetIntegerLiteral().Text); int c; if (const1.Cdr != const2.Cdr) { c = a - b; } else { c = a + b; } //Eliminate stuff like <exp> + -1 if (c < 0 && pBinop1.GetRight() == const1.Car) { c = -c; if (pBinop1.GetBinop() is AMinusBinop) { pBinop1.SetBinop(new APlusBinop(new TPlus("+"))); } else { pBinop1.SetBinop(new AMinusBinop(new TMinus("-"))); } const1.Cdr = !const1.Cdr; } const1.Car.GetIntegerLiteral().Text = c.ToString(); //Remove binop2 if (pBinop2.GetLeft() == const2.Car) { if (pBinop2.GetBinop() is AMinusBinop) { if (pBinop2.GetRight() is AIntConstExp) { AIntConstExp const3 = (AIntConstExp)pBinop2.GetRight(); const3.GetIntegerLiteral().Text = (-int.Parse(const3.GetIntegerLiteral().Text)).ToString(); pBinop2.ReplaceBy(const3); intConsts.Add(new Pair <AIntConstExp, bool>(const3, isNegativeRightSide)); } else { AUnopExp unop = new AUnopExp(new ANegateUnop(new TMinus("-")), pBinop2.GetRight()); data.ExpTypes[unop] = new ANamedType(new TIdentifier("int"), null); pBinop2.ReplaceBy(unop); } } else { pBinop2.ReplaceBy(pBinop2.GetRight()); } } else { pBinop2.ReplaceBy(pBinop2.GetLeft()); } intConsts.RemoveAt(j); j--; } } return; } } { PushStack(); node.GetLeft().Apply(this); PopStack(); PushStack(); node.GetRight().Apply(this); PopStack(); } if (isIntegerType && (node.GetBinop() is ATimesBinop || node.GetBinop() is ADivideBinop) && node.GetLeft() is AIntConstExp && node.GetRight() is AIntConstExp) { AIntConstExp const1 = (AIntConstExp)node.GetLeft(); AIntConstExp const2 = (AIntConstExp)node.GetRight(); int a = int.Parse(const1.GetIntegerLiteral().Text); int b = int.Parse(const2.GetIntegerLiteral().Text); int c; if (node.GetBinop() is ATimesBinop || b != 0) { if (node.GetBinop() is ATimesBinop) { c = a * b; } else { c = a / b; } const1.GetIntegerLiteral().Text = c.ToString(); node.ReplaceBy(const1); const1.Apply(this); return; } } if (node.GetBinop() is AEqBinop || node.GetBinop() is ANeBinop) { if (node.GetLeft() is ABooleanConstExp && node.GetRight() is ABooleanConstExp) { bool b1 = ((ABooleanConstExp)node.GetLeft()).GetBool() is ATrueBool; bool b2 = ((ABooleanConstExp)node.GetRight()).GetBool() is ATrueBool; bool b3 = false; if (node.GetBinop() is AEqBinop) { b3 = b1 == b2; } else if (node.GetBinop() is ANeBinop) { b3 = b1 != b2; } ((ABooleanConstExp)node.GetLeft()).SetBool(b3 ? (PBool) new ATrueBool() : new AFalseBool()); node.ReplaceBy(node.GetLeft()); return; } else if (node.GetLeft() is AIntConstExp && node.GetRight() is AIntConstExp) { AIntConstExp const1 = (AIntConstExp)node.GetLeft(); AIntConstExp const2 = (AIntConstExp)node.GetRight(); int a = int.Parse(const1.GetIntegerLiteral().Text); int b = int.Parse(const2.GetIntegerLiteral().Text); bool c = false; if (node.GetBinop() is AEqBinop) { c = a == b; } else if (node.GetBinop() is ANeBinop) { c = a != b; } ABooleanConstExp booleanExp = new ABooleanConstExp(c ? (PBool) new ATrueBool() : new AFalseBool()); data.ExpTypes[booleanExp] = new ANamedType(new TIdentifier("bool"), null); node.ReplaceBy(booleanExp); return; } else if (node.GetLeft() is ANullExp && node.GetRight() is ANullExp) { ABooleanConstExp booleanExp = new ABooleanConstExp(node.GetBinop() is AEqBinop ? (PBool) new ATrueBool() : new AFalseBool()); data.ExpTypes[booleanExp] = new ANamedType(new TIdentifier("bool"), null); node.ReplaceBy(booleanExp); return; } else if (node.GetLeft() is AStringConstExp && node.GetRight() is AStringConstExp) { AStringConstExp const1 = (AStringConstExp)node.GetLeft(); AStringConstExp const2 = (AStringConstExp)node.GetRight(); string a = const1.GetStringLiteral().Text; string b = const2.GetStringLiteral().Text; bool c = false; if (node.GetBinop() is AEqBinop) { c = a == b; } else if (node.GetBinop() is ANeBinop) { c = a != b; } ABooleanConstExp booleanExp = new ABooleanConstExp(c ? (PBool) new ATrueBool() : new AFalseBool()); data.ExpTypes[booleanExp] = new ANamedType(new TIdentifier("bool"), null); node.ReplaceBy(booleanExp); return; } } if ((node.GetLeft() is ABooleanConstExp || node.GetRight() is ABooleanConstExp) && (node.GetBinop() is ALazyAndBinop || node.GetBinop() is ALazyOrBinop)) { ABooleanConstExp boolExp; PExp other; if (node.GetLeft() is ABooleanConstExp) { boolExp = (ABooleanConstExp)node.GetLeft(); other = node.GetRight(); } else { boolExp = (ABooleanConstExp)node.GetRight(); other = node.GetLeft(); } if (node.GetBinop() is ALazyAndBinop) { if (boolExp.GetBool() is ATrueBool) { //true && <exp> node.ReplaceBy(other); } else { //false && <exp> node.ReplaceBy(boolExp); } } else { if (boolExp.GetBool() is ATrueBool) { //true || <exp> node.ReplaceBy(boolExp); } else { //false || <exp> node.ReplaceBy(other); } } return; } } finally { if (pushed) { PopStack(); } } }
private int FoldInt(PExp exp, ref bool valid) { if (!valid) { return(-1); } if (exp is AIntConstExp) { return(int.Parse(((AIntConstExp)exp).GetIntegerLiteral().Text)); } if (exp is ABinopExp) { ABinopExp aExp = (ABinopExp)exp; int left = FoldInt(aExp.GetLeft(), ref valid); int right = FoldInt(aExp.GetLeft(), ref valid); if (!valid) { return(-1); } PBinop binop = aExp.GetBinop(); if (binop is APlusBinop) { return(left + right); } if (binop is AMinusBinop) { return(left - right); } if (binop is ATimesBinop) { return(left * right); } if ((binop is AModuloBinop || binop is ADivideBinop) && right == 0) { Token token = binop is AModuloBinop ? (Token)((AModuloBinop)binop).GetToken() : ((ADivideBinop)binop).GetToken(); errors.Add(new ErrorCollection.Error(token, "Zero division during constant folding.")); throw new ParserException(null, null); } if (binop is AModuloBinop) { return(left % right); } if (binop is ADivideBinop) { return(left / right); } if (binop is AAndBinop) { return(left & right); } if (binop is AOrBinop) { return(left | right); } if (binop is AXorBinop) { return(left ^ right); } if (binop is ALBitShiftBinop) { return(left << right); } if (binop is ARBitShiftBinop) { return(left >> right); } } if (exp is ALvalueExp) { return(FoldInt(((ALvalueExp)exp).GetLvalue(), ref valid)); } valid = false; return(-1); }
public override void CaseABinopExp(ABinopExp node) { if (folding) { node.GetLeft().Apply(this); int left = value; node.GetRight().Apply(this); int right = value; if (node.GetBinop() is APlusBinop) { value = left + right; } else if (node.GetBinop() is AMinusBinop) { value = left - right; } else if (node.GetBinop() is ATimesBinop) { value = left * right; } else if (node.GetBinop() is ADivideBinop) { if (right == 0) { errors.Add(new ErrorCollection.Error(((ADivideBinop)node.GetBinop()).GetToken(), LocRM.GetString("ErrorText58")), true); throw new ParserException(null, "SetArrayIndexes.CaseABinopExp"); } value = left / right; } else if (node.GetBinop() is AModuloBinop) { if (right == 0) { errors.Add(new ErrorCollection.Error(((AModuloBinop)node.GetBinop()).GetToken(), LocRM.GetString("ErrorText58")), true); throw new ParserException(null, "EnviromentChecking.CaseABinopExp"); } value = left % right; } else if (node.GetBinop() is AAndBinop) { value = left & right; } else if (node.GetBinop() is AOrBinop) { value = left | right; } else if (node.GetBinop() is AXorBinop) { value = left ^ right; } else if (node.GetBinop() is ALBitShiftBinop) { value = left << right; } else if (node.GetBinop() is ARBitShiftBinop) { value = left >> right; } } else { base.CaseABinopExp(node); } }
public static bool ReturnsTheSame(PExp left, PExp right, SharedData data) { if (left.GetType() != right.GetType()) { return(false); } if (left is ABinopExp) { ABinopExp aLeft = (ABinopExp)left; ABinopExp aRight = (ABinopExp)right; if (aLeft.GetBinop().GetType() != aRight.GetBinop().GetType()) { return(false); } return(ReturnsTheSame(aLeft.GetLeft(), aRight.GetLeft(), data) && ReturnsTheSame(aLeft.GetRight(), aRight.GetRight(), data)); } if (left is AUnopExp) { AUnopExp aLeft = (AUnopExp)left; AUnopExp aRight = (AUnopExp)right; if (aLeft.GetUnop().GetType() != aRight.GetUnop().GetType()) { return(false); } return(ReturnsTheSame(aLeft.GetExp(), aRight.GetExp(), data)); } if (left is AIntConstExp) { AIntConstExp aLeft = (AIntConstExp)left; AIntConstExp aRight = (AIntConstExp)right; return(int.Parse(aLeft.GetIntegerLiteral().Text) == int.Parse(aRight.GetIntegerLiteral().Text)); } if (left is AFixedConstExp) { AFixedConstExp aLeft = (AFixedConstExp)left; AFixedConstExp aRight = (AFixedConstExp)right; return(aLeft.GetFixedLiteral().Text == aRight.GetFixedLiteral().Text); } if (left is AStringConstExp) { AStringConstExp aLeft = (AStringConstExp)left; AStringConstExp aRight = (AStringConstExp)right; return(aLeft.GetStringLiteral().Text == aRight.GetStringLiteral().Text); } if (left is ACharConstExp) { ACharConstExp aLeft = (ACharConstExp)left; ACharConstExp aRight = (ACharConstExp)right; return(aLeft.GetCharLiteral().Text == aRight.GetCharLiteral().Text); } if (left is ABooleanConstExp) { ABooleanConstExp aLeft = (ABooleanConstExp)left; ABooleanConstExp aRight = (ABooleanConstExp)right; return(aLeft.GetBool().GetType() == aRight.GetBool().GetType()); } if (left is ASimpleInvokeExp) { //A method might not return the same thing each time it is called return(false); } if (left is ALvalueExp) { ALvalueExp aLeft = (ALvalueExp)left; ALvalueExp aRight = (ALvalueExp)right; return(ReturnsTheSame(aLeft.GetLvalue(), aRight.GetLvalue(), data)); } if (left is AParenExp) { AParenExp aLeft = (AParenExp)left; AParenExp aRight = (AParenExp)right; return(ReturnsTheSame(aLeft.GetExp(), aRight.GetExp(), data)); } throw new Exception("Util.ReturnsTheSame. Unexpected type, got " + left.GetType()); }