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); }
//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) { InABinopExp(node); if (node.GetRight() != null) { node.GetRight().Apply(this); } if (node.GetBinop() != null) { node.GetBinop().Apply(this); } if (node.GetLeft() != null) { node.GetLeft().Apply(this); } OutABinopExp(node); }
public override void OutABinopExp(ABinopExp node) { PBinop binop = node.GetBinop(); PExp left = node.GetLeft(); PType leftType = data.ExpTypes[left]; string leftTypeString = Util.TypeToString(leftType); PExp right = node.GetRight(); PType rightType = data.ExpTypes[right]; string rightTypeString = Util.TypeToString(rightType); bool wasDefined = false; Token token = null; while (true) { if (binop is APlusBinop) { token = ((APlusBinop) binop).GetToken(); //Check that types are okay for + if (!new[] {"int", "fixed", "string", "text", "byte", "point"}.Any(c => c == leftTypeString)) { errors.Add(new ErrorCollection.Error(token, currentSourceFile, LocRM.GetString("ErrorText103") + leftTypeString)); throw new ParserException(null, null); } if (!new[] {"int", "fixed", "string", "text", "byte", "point"}.Any(c => c == rightTypeString)) { errors.Add(new ErrorCollection.Error(token, currentSourceFile, LocRM.GetString("ErrorText103") + rightTypeString)); throw new ParserException(null, null); } //If you are using string or text, both sides must be same type if ((leftTypeString == "string" && rightTypeString != "string") || (leftTypeString == "text" && rightTypeString != "text") || (leftTypeString == "point" && rightTypeString != "point") || (rightTypeString == "string" && leftTypeString != "string") || (rightTypeString == "text" && leftTypeString != "text") || (rightTypeString == "point" && leftTypeString != "point")) { if (ImplicitAssignable(leftType, rightType)) { ANamedType namedTo = (ANamedType) rightType; ACastExp cast = new ACastExp(new TLParen("("), new ANamedType( new TIdentifier(((AAName) namedTo.GetName()).AsString()), null), node.GetLeft()); node.SetLeft(cast); OutACastExp(cast); leftType = rightType; } else if (ImplicitAssignable(rightType, leftType)) { ANamedType namedTo = (ANamedType) leftType; ACastExp cast = new ACastExp(new TLParen("("), new ANamedType( new TIdentifier(((AAName) namedTo.GetName()).AsString()), null), node.GetRight()); node.SetRight(cast); OutACastExp(cast); rightType = leftType; } else { //Not valid break; } } wasDefined = true; PType type = leftType; if (rightTypeString == "fixed") type = rightType; data.ExpTypes[node] = type; } else if (binop is AMinusBinop || binop is ATimesBinop || binop is ADivideBinop || binop is AModuloBinop) { token = null; if (binop is AMinusBinop) token = ((AMinusBinop) binop).GetToken(); else if (binop is ATimesBinop) token = ((ATimesBinop) binop).GetToken(); else if (binop is ADivideBinop) token = ((ADivideBinop) binop).GetToken(); else if (binop is AModuloBinop) token = ((AModuloBinop) binop).GetToken(); //Check that types are okay for whatever if (!new[] {"int", "fixed", "byte", "point"}.Any(c => c == leftTypeString)) { //Not valid break; } if (!new[] {"int", "fixed", "byte", "point"}.Any(c => c == rightTypeString)) { //Not valid break; } if ((leftTypeString == "point" || rightTypeString == "point") && !(leftTypeString == "point" && rightTypeString == "point" && binop is AMinusBinop)) { //Not valid break; } wasDefined = true; PType type = leftType; if (rightTypeString == "fixed") type = rightType; if (rightTypeString == "int" && leftTypeString == "byte") type = rightType; data.ExpTypes[node] = type; } else if (binop is AEqBinop || binop is ANeBinop || binop is ALtBinop || binop is ALeBinop || binop is AGtBinop || binop is AGeBinop) { token = null; if (binop is AEqBinop) token = ((AEqBinop) binop).GetToken(); else if (binop is ANeBinop) token = ((ANeBinop) binop).GetToken(); else if (binop is ALtBinop) token = ((ALtBinop) binop).GetToken(); else if (binop is ALeBinop) token = ((ALeBinop) binop).GetToken(); else if (binop is AGtBinop) token = ((AGtBinop) binop).GetToken(); else if (binop is AGeBinop) token = ((AGeBinop) binop).GetToken(); //Unless types are int and fixed, they must be the same type, or null and a nullable type if (leftTypeString == "void" || rightTypeString == "void" || !( GalaxyKeywords.NullablePrimitives.words.Any(s => s == leftTypeString) && rightTypeString == "null" || leftTypeString == "null" && GalaxyKeywords.NullablePrimitives.words.Any(s => s == rightTypeString) || (leftTypeString == "int" || leftTypeString == "fixed" || leftTypeString == "byte") && (rightTypeString == "int" || rightTypeString == "fixed" || rightTypeString == "byte") || leftTypeString == rightTypeString && !(IsDynamic(leftType) || IsDynamic(rightType)) || (binop is AEqBinop || binop is ANeBinop) && ( leftTypeString == rightTypeString || leftTypeString == "null" && IsDynamic(rightType) || IsDynamic(leftType) && rightTypeString == "null" || Util.TypesEqual(leftType, rightType, data) ) || leftType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) leftType) && (rightTypeString == "null" || rightType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) rightType)) || rightType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) rightType) && leftTypeString == "null" ) ) { //Not valid break; } wasDefined = true; data.ExpTypes[node] = new ANamedType(new TIdentifier("bool"), null); } else if (binop is AAndBinop || binop is AOrBinop || binop is AXorBinop || binop is ALBitShiftBinop || binop is ARBitShiftBinop) { token = null; if (binop is AAndBinop) token = ((AAndBinop) binop).GetToken(); else if (binop is AOrBinop) token = ((AOrBinop) binop).GetToken(); else if (binop is AXorBinop) token = ((AXorBinop) binop).GetToken(); else if (binop is ALBitShiftBinop) token = ((ALBitShiftBinop) binop).GetToken(); else if (binop is ARBitShiftBinop) token = ((ARBitShiftBinop) binop).GetToken(); if ( !((leftTypeString == "int" || leftTypeString == "byte") && (rightTypeString == "int" || rightTypeString == "byte") && (binop is ALBitShiftBinop || binop is ARBitShiftBinop || leftTypeString == rightTypeString))) { if (rightTypeString == "int" && leftTypeString == "byte" && left is AIntConstExp) { data.ExpTypes[left] = leftType = new ANamedType(new TIdentifier("int"), null); leftTypeString = "int"; } else if (leftTypeString == "int" && rightTypeString == "byte" && right is AIntConstExp) { data.ExpTypes[right] = rightType = new ANamedType(new TIdentifier("int"), null); rightTypeString = "int"; } else { //Not valid break; } } wasDefined = true; data.ExpTypes[node] = leftType; if (rightTypeString == "int") data.ExpTypes[node] = rightType; } else if (binop is ALazyAndBinop || binop is ALazyOrBinop) { token = null; if (binop is ALazyAndBinop) token = ((ALazyAndBinop) binop).GetToken(); else if (binop is ALazyOrBinop) token = ((ALazyOrBinop) binop).GetToken(); if (leftTypeString != "bool" || rightTypeString != "bool") { errors.Add(new ErrorCollection.Error(token, currentSourceFile, token.Text + LocRM.GetString("ErrorText104") + token.Text + " bool). Got (" + leftTypeString + " " + token.Text + " " + rightTypeString + ")")); throw new ParserException(null, null); } wasDefined = true; data.ExpTypes[node] = leftType; } else throw new Exception("Unexpected binop (This should never happen)"); break; } List<AMethodDecl> possibleOperators = new List<AMethodDecl>(); List<IList> visibleDecls = Util.GetVisibleDecls(node, true); List<string> currentNamespace = Util.GetFullNamespace(node); AASourceFile currentFile = Util.GetAncestor<AASourceFile>(node); foreach (IList declList in visibleDecls) { bool sameNS = false; bool sameFile = false; if (declList.Count > 0) { sameNS = Util.NamespacesEquals(currentNamespace, Util.GetFullNamespace((PDecl) declList[0])); sameFile = currentFile == Util.GetAncestor<AASourceFile>((PDecl) declList[0]); } foreach (PDecl decl in declList) { if (decl is AMethodDecl) { AMethodDecl method = (AMethodDecl) decl; if (method.GetName().Text == token.Text) { if (method.GetVisibilityModifier() is APrivateVisibilityModifier && !sameNS) continue; if (method.GetStatic() != null && !sameFile) continue; //Check that parameters are assignable bool add = true; bool matchImplicit = false; List<PType> argTypes = new List<PType>(){leftType, rightType}; for (int i = 0; i < argTypes.Count; i++) { PType argType = argTypes[i]; AALocalDecl formal = (AALocalDecl)method.GetFormals()[i]; PType formalType = formal.GetType(); if (formal.GetOut() != null && !Assignable(formalType, argType) || formal.GetRef() != null && !(Assignable(argType, formalType) && Assignable(formalType, argType)) || formal.GetOut() == null && formal.GetRef() == null && !Assignable(argType, formalType)) { add = false; if (formal.GetOut() == null && formal.GetRef() == null && ImplicitAssignable(argType, formalType)) { matchImplicit = true; } else { matchImplicit = false; break; } } } if (!add && !matchImplicit) continue; if (add) possibleOperators.Add(method); } } } } if (possibleOperators.Count == 0 && !wasDefined) { errors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText105") + leftTypeString + " " + token.Text + " " + rightTypeString + ")")); throw new ParserException(token, "TypeChecking.OutABinopExp"); } if (possibleOperators.Count + (wasDefined ? 1 : 0) > 1) { List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>(); foreach (AMethodDecl method in possibleOperators) { subErrors.Add(new ErrorCollection.Error(method.GetName(), LocRM.GetString("ErrorText106"))); } if (wasDefined) subErrors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText107") + token.Text)); errors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText108") + leftTypeString + " " + token.Text + " " + rightTypeString + LocRM.GetString("ErrorText109"), false, subErrors.ToArray())); throw new ParserException(token, "TypeChecking.OutABinopExp"); } if (wasDefined) return; AMethodDecl op = possibleOperators[0]; ASimpleInvokeExp replacer = new ASimpleInvokeExp(new TIdentifier(op.GetName().Text), new ArrayList(){node.GetLeft(), node.GetRight()}); node.ReplaceBy(replacer); data.SimpleMethodLinks[replacer] = op; data.ExpTypes[replacer] = op.GetReturnType(); //base.OutABinopExp(node); }
public override void CaseABinopExp(ABinopExp node) { if (!foldIntegerConstants) { base.CaseABinopExp(node); return; } CheckValidConstExp(node.GetLeft()); CheckValidConstExp(node.GetRight()); node.GetLeft().Apply(this); int left = integerConstant; node.GetBinop().Apply(this); node.GetRight().Apply(this); int right = integerConstant; if (node.GetBinop() is APlusBinop) integerConstant = left + right; else if (node.GetBinop() is AMinusBinop) integerConstant = left - right; else if (node.GetBinop() is ATimesBinop) integerConstant = left * right; else if (node.GetBinop() is ADivideBinop) { if (right == 0) { errors.Add(new ErrorCollection.Error(((ADivideBinop)node.GetBinop()).GetToken(), currentSourceFile, LocRM.GetString("ErrorText58"), false), true); throw new ParserException(null, "EnviromentChecking.CaseABinopExp"); } integerConstant = left / right; } else if (node.GetBinop() is AModuloBinop) { if (right == 0) { errors.Add(new ErrorCollection.Error(((AModuloBinop)node.GetBinop()).GetToken(), currentSourceFile, LocRM.GetString("ErrorText58"), false), true); throw new ParserException(null, "EnviromentChecking.CaseABinopExp"); } integerConstant = left % right; } else if (node.GetBinop() is AAndBinop) integerConstant = left & right; else if (node.GetBinop() is AOrBinop) integerConstant = left | right; else if (node.GetBinop() is AXorBinop) integerConstant = left ^ right; else if (node.GetBinop() is ALBitShiftBinop) integerConstant = left << right; else if (node.GetBinop() is ARBitShiftBinop) integerConstant = left >> right; }
public override void CaseABinopExp(ABinopExp node) { if (node.GetBinop() is AEqBinop && node.GetRight() is ANullExp && data.ExpTypes[node.GetLeft()] is APointerType) { //We have a null check APointerType pointerType = (APointerType)data.ExpTypes[node.GetLeft()]; AMethodDecl nullCheckMethod = CreateNullCheckMethod(node, pointerType.GetType(), data); ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("IsNull"), new ArrayList(){node.GetLeft()}); node.ReplaceBy(invoke); data.ExpTypes[invoke] = new ANamedType(new TIdentifier("bool"), null); data.SimpleMethodLinks[invoke] = nullCheckMethod; CaseASimpleInvokeExp(invoke); return; } base.CaseABinopExp(node); }
public override void OutABinopExp(ABinopExp node) { if (node.GetBinop() is AEqBinop || node.GetBinop() is ANeBinop) { if (node.GetLeft() is ANullExp || node.GetRight() is ANullExp) { if (node.GetLeft() is ANullExp) { //Swap left and right PExp temp = node.GetLeft(); node.SetLeft(node.GetRight()); node.SetRight(temp); } PExp exp = node.GetLeft(); PType type = data.ExpTypes[exp]; if (type is APointerType) { if (node.GetBinop() is ANeBinop) { //Convert a != null to !(a == null) AUnopExp unop = new AUnopExp(new AComplementUnop(new TComplement("!")), null); node.ReplaceBy(unop); unop.SetExp(node); node.SetBinop(new AEqBinop(new TEq("=="))); data.ExpTypes[unop] = new ANamedType(new TIdentifier("bool"), null); } if (Util.IsIntPointer(node, ((APointerType)type).GetType(), data)) { bool add = true; foreach (PType pType in TypesWithIdentifierArray) { if (Util.TypesEqual(((APointerType)type).GetType(), pType, data)) { add = false; break; } } if (add) TypesWithIdentifierArray.Add(((APointerType)type).GetType()); } } } } }