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 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)
 {
     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);
 }
            private void MakeAssignmentRightDynamic(PLvalue leftSide, PExp rightSide, PType type, AABlock block, ref int index)
            {
                if (Util.IsBulkCopy(type))
                {
                    if (type is ANamedType)
                    {
                        ANamedType aType = (ANamedType)type;
                        AStructDecl structDecl = data.StructTypeLinks[aType];
                        foreach (AALocalDecl localDecl in structDecl.GetLocals())
                        {
                            AStructLvalue newleftSide = new AStructLvalue(new ALvalueExp(leftSide),
                                                                          new ADotDotType(new TDot(".")),
                                                                          new TIdentifier(localDecl.GetName().Text));

                            ABinopExp newrightSide = new ABinopExp(rightSide, new APlusBinop(new TPlus("+")),
                                                     new AStringConstExp(
                                                         new TStringLiteral("\"." + localDecl.GetName().Text + "\"")));

                             data.ExpTypes[newrightSide] =
                                data.ExpTypes[newrightSide.GetRight()] =
                                new ANamedType(new TIdentifier("string"), null);

                            data.ExpTypes[newleftSide.GetReceiver()] = type;
                            data.LvalueTypes[newleftSide] = localDecl.GetType();

                            data.StructFieldLinks[newleftSide] = localDecl;

                            MakeAssignmentRightDynamic(newleftSide, newrightSide, localDecl.GetType(), block, ref index);
                        }
                    }
                    else
                    {//Is array type. Can Only be a constant array type
                        AArrayTempType aType = (AArrayTempType)type;
                        for (int i = 0; i < int.Parse(aType.GetIntDim().Text); i++)
                        {
                            AArrayLvalue newleftSide = new AArrayLvalue(new TLBracket("["), new ALvalueExp(leftSide), new AIntConstExp(new TIntegerLiteral(i.ToString())));

                            ABinopExp newrightSide = new ABinopExp(rightSide, new APlusBinop(new TPlus("+")),
                                                     new AStringConstExp(
                                                         new TStringLiteral("\"[" + i + "]\"")));
                            data.ExpTypes[newrightSide] =
                                data.ExpTypes[newrightSide.GetRight()] =
                                new ANamedType(new TIdentifier("string"), null);

                            data.ExpTypes[newleftSide.GetBase()] = type;
                            data.ExpTypes[newleftSide.GetIndex()] = new ANamedType(new TIdentifier("int"), null);
                            data.LvalueTypes[newleftSide] = aType.GetType();

                            MakeAssignmentRightDynamic(newleftSide, newrightSide, aType.GetType(), block, ref index);

                        }

                    }
                }
                else
                {
                    ANamedType aType;// = type is APointerType ? new ANamedType(new TIdentifier("string"), null) : (ANamedType)type;
                    if (type is APointerType)
                    {
                        if (Util.IsIntPointer(type, ((APointerType)type).GetType(), data))
                            aType = new ANamedType(new TIdentifier("int"), null);
                        else
                            aType = new ANamedType(new TIdentifier("string"), null);
                    }
                    else
                    {
                        aType = (ANamedType) type;
                    }
                    string capitalType = Util.Capitalize(aType.AsIdentifierString());//Char.ToUpper(aType.GetName().Text[0]) + aType.GetName().Text.Substring(1);
                    leftSide = Util.MakeClone(leftSide, data);
                    rightSide = Util.MakeClone(rightSide, data);

                    ABooleanConstExp trueConst1 = new ABooleanConstExp(new ATrueBool());
                    //ABooleanConstExp trueConst2 = new ABooleanConstExp(new ATrueBool());
                    ASimpleInvokeExp innerInvoke = new ASimpleInvokeExp(new TIdentifier("DataTableGet" + capitalType), new ArrayList() { trueConst1, rightSide });
                    //ASimpleInvokeExp outerInvoke = new ASimpleInvokeExp(new TIdentifier("DataTableSet" + capitalType), new ArrayList() { trueConst2, leftSide, innerInvoke });
                    AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), leftSide, innerInvoke);
                    block.GetStatements().Insert(index, new AExpStm(new TSemicolon(";"), assignment));
                    index++;

                    data.ExpTypes[trueConst1] = new ANamedType(new TIdentifier("bool"), null);

                    data.ExpTypes[innerInvoke] = aType;
                    data.ExpTypes[assignment] = aType;

                    data.SimpleMethodLinks[innerInvoke] =
                        data.Libraries.Methods.First(m => m.GetName().Text == innerInvoke.GetName().Text);
                }
            }
        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 CaseAStructLvalue(AStructLvalue node)
 {
     hadPointer = false;
     base.CaseAStructLvalue(node);
     if (hadPointer)
     {
         //if (Util.GetAncestor<AAssignmentExp>(node) != null || Util.GetAncestor<APArrayLengthLvalue>(node) != null)
         {
             ABinopExp binopExp = new ABinopExp(nameExp, new APlusBinop(new TPlus("+")),
                                                new AStringConstExp(
                                                    new TStringLiteral("\"." + node.GetName().Text + "\"")));
             data.ExpTypes[binopExp] =
                 data.ExpTypes[binopExp.GetRight()] = new ANamedType(new TIdentifier("string"), null);
             nameExp = binopExp;
         }
         CheckDynamicLvalue(node);
     }
 }
            private static void AddRemoves(PExp exp, PType type, AABlock block, SharedData data)
            {
                if (Util.IsBulkCopy(type))
                {
                    if (type is ANamedType)
                    {
                        ANamedType aType = (ANamedType)type;
                        AStructDecl structDecl = data.StructTypeLinks[aType];
                        foreach (AALocalDecl localDecl in structDecl.GetLocals())
                        {
                            ABinopExp newExp = new ABinopExp(exp, new APlusBinop(new TPlus("+")),
                                                     new AStringConstExp(
                                                         new TStringLiteral("\"." + localDecl.GetName().Text + "\"")));
                            data.ExpTypes[newExp] =
                                data.ExpTypes[newExp.GetRight()] =
                                new ANamedType(new TIdentifier("string"), null);

                            AddRemoves(newExp, localDecl.GetType(), block, data);
                        }
                    }
                    else
                    {//Is array type. Can Only be a constant array type
                        AArrayTempType aType = (AArrayTempType)type;
                        for (int i = 0; i < int.Parse(aType.GetIntDim().Text); i++)
                        {
                            ABinopExp newExp = new ABinopExp(exp, new APlusBinop(new TPlus("+")),
                                                     new AStringConstExp(
                                                         new TStringLiteral("\"[" + i + "]\"")));
                            data.ExpTypes[newExp] =
                                data.ExpTypes[newExp.GetRight()] =
                                new ANamedType(new TIdentifier("string"), null);

                            AddRemoves(newExp, aType.GetType(), block, data);
                        }

                    }
                }
                else
                {
                    exp = Util.MakeClone(exp, data);

                    ABooleanConstExp trueConst1 = new ABooleanConstExp(new ATrueBool());
                    ASimpleInvokeExp removeInvoke = new ASimpleInvokeExp(new TIdentifier("DataTableValueRemove"), new ArrayList() { trueConst1, exp });
                    block.GetStatements().Add(new AExpStm(new TSemicolon(";"), removeInvoke));

                    data.ExpTypes[trueConst1] = new ANamedType(new TIdentifier("bool"), null);

                    data.ExpTypes[removeInvoke] = new AVoidType(new TVoid("void"));

                    data.SimpleMethodLinks[removeInvoke] =
                        data.Libraries.Methods.First(m => m.GetName().Text == removeInvoke.GetName().Text);
                }
            }
            public override void CaseADeleteStm(ADeleteStm node)
            {
                List<Node> visitMeNext = new List<Node>();
                APointerType pointer = (APointerType) data.ExpTypes[node.GetExp()];

                //Call deconstructor if it exists
                {
                    AMethodDecl deconstructor = null;
                    if (pointer.GetType() is ANamedType &&
                        data.StructTypeLinks.ContainsKey((ANamedType) pointer.GetType()))
                    {
                        AStructDecl str = data.StructTypeLinks[(ANamedType) pointer.GetType()];

                        deconstructor =
                            data.DeconstructorMap[data.StructDeconstructor[str]];

                    }
                    else //Look for enrichment deconstructor
                    {
                        foreach (AEnrichmentDecl enrichment in data.Enrichments)
                        {
                            if (Util.TypesEqual(pointer.GetType(), enrichment.GetType(), data))
                            {
                                foreach (PDecl decl in enrichment.GetDecl())
                                {
                                    if (decl is ADeconstructorDecl)
                                    {
                                        deconstructor = data.DeconstructorMap[(ADeconstructorDecl) decl];
                                        break;
                                    }
                                }
                                if (deconstructor != null)
                                    break;
                            }
                        }
                    }
                    if (deconstructor != null)
                    {
                        /*
                         * Convert delete <exp>; to
                         *
                         * var deleteVar = <exp>;
                         * Deconstructor(deleteVar);
                         * delete deleteVar;
                         */

                        AALocalDecl deleteVarDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null,
                                                                    null,
                                                                    new ANamedType(
                                                                        new TIdentifier(Util.IsIntPointer(node,
                                                                                                          pointer.
                                                                                                              GetType(),
                                                                                                          data)
                                                                                            ? "int"
                                                                                            : "string"), null),
                                                                    new TIdentifier("deleteVar"), node.GetExp());
                        ALocalLvalue deleteVarRef = new ALocalLvalue(new TIdentifier("deleteVar"));
                        ALvalueExp deleteVarRefExp = new ALvalueExp(deleteVarRef);
                        node.SetExp(deleteVarRefExp);

                        AABlock pBlock = (AABlock) node.Parent();
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node),
                                                      new ALocalDeclStm(new TSemicolon(";"), deleteVarDecl));

                        data.LocalLinks[deleteVarRef] = deleteVarDecl;
                        data.LvalueTypes[deleteVarRef] =
                            data.ExpTypes[deleteVarRefExp] = data.ExpTypes[deleteVarDecl.GetInit()];

                        deleteVarRef = new ALocalLvalue(new TIdentifier("deleteVar"));
                        deleteVarRefExp = new ALvalueExp(deleteVarRef);

                        ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier(deconstructor.GetName().Text),
                                                                       new ArrayList() {deleteVarRefExp});
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node),
                                                      new AExpStm(new TSemicolon(";"), invoke));

                        data.LocalLinks[deleteVarRef] = deleteVarDecl;
                        data.LvalueTypes[deleteVarRef] =
                            data.ExpTypes[deleteVarRefExp] = data.ExpTypes[deleteVarDecl.GetInit()];
                        data.SimpleMethodLinks[invoke] = deconstructor;
                        data.ExpTypes[invoke] = deconstructor.GetReturnType();
                        visitMeNext.Add(deleteVarDecl);

                    }
                }

                if (pointer.GetType() is AArrayTempType || pointer.GetType() is ADynamicArrayType)
                {
                    //If struct array, delete all struct data
                    PType baseType;
                    if (pointer.GetType() is AArrayTempType)
                        baseType = ((AArrayTempType) pointer.GetType()).GetType();
                    else
                        baseType = ((ADynamicArrayType)pointer.GetType()).GetType();

                    PExp pointerString = node.GetExp();
                    if (Util.IsBulkCopy(baseType))
                    {
                        node.GetExp().Apply(new MoveMethodDeclsOut("pointerVar", data));
                        pointerString = node.GetExp();
                        ANamedType aBaseType = (ANamedType) baseType;
                        /* Add the following
                         *
                         * string deleteMe = node.getExp(); <-- no
                         * int i = 0;
                         * while (i < array.length)
                         * {
                         *      DeleteStruct<name>(deleteMe + StringToInt(i));
                         *      i = i + 1;
                         * }
                         *
                         */
                        //string deleteMe = node.getExp();
                        /*AALocalDecl deleteMeVar = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                                  new ANamedType(new TIdentifier("string"), null),
                                                                  new TIdentifier("deleteMe"), node.GetExp());*/
                        //pointerString = deleteMeVar;
                        //int i = 0;
                        AALocalDecl iVar = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                           new ANamedType(new TIdentifier("int"), null),
                                                           new TIdentifier("i"),
                                                           new AIntConstExp(new TIntegerLiteral("0")));
                        //i < array.length
                        ASimpleInvokeExp lenghCall = new ASimpleInvokeExp(new TIdentifier("DataTableGetInt"), new ArrayList());
                        lenghCall.GetArgs().Add(new ABooleanConstExp(new ATrueBool()));
                        //ALocalLvalue deleteMeUse1 = new ALocalLvalue(new TIdentifier("deleteMeVar"));
                        ABinopExp arrayLengthString = new ABinopExp(Util.MakeClone(pointerString, data),
                                                                    new APlusBinop(new TPlus("+")),
                                                                    new AStringConstExp(
                                                                        new TStringLiteral("\"\\\\Length\"")));
                        lenghCall.GetArgs().Add(arrayLengthString);
                        ALocalLvalue iUse1 = new ALocalLvalue(new TIdentifier("i"));
                        ABinopExp cond = new ABinopExp(new ALvalueExp(iUse1), new ALtBinop(new TLt("<")), lenghCall);

                        //DeleteStruct<name>(deleteMe + StringToInt(i));
                        //ALocalLvalue deleteMeUse2 = new ALocalLvalue(new TIdentifier("deleteMeVar"));
                        ALocalLvalue iUse2 = new ALocalLvalue(new TIdentifier("i"));
                        ASimpleInvokeExp intToString = new ASimpleInvokeExp(new TIdentifier("IntToString"), new ArrayList());
                        intToString.GetArgs().Add(new ALvalueExp(iUse2));
                        ABinopExp binopExp1 = new ABinopExp(Util.MakeClone(pointerString, data), new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"[\"")));
                        ABinopExp binopExp2 = new ABinopExp(binopExp1, new APlusBinop(new TPlus("+")), intToString);
                        ABinopExp binopExp3 = new ABinopExp(binopExp2, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"]\"")));
                        ASimpleInvokeExp deleteStructInvoke = new ASimpleInvokeExp(new TIdentifier("DeleteStruct" + aBaseType.AsIdentifierString()), new ArrayList());
                        deleteStructInvoke.GetArgs().Add(binopExp3);
                        //i = i + 1;
                        ALocalLvalue iUse3 = new ALocalLvalue(new TIdentifier("i"));
                        ALocalLvalue iUse4 = new ALocalLvalue(new TIdentifier("i"));
                        ABinopExp binopExp = new ABinopExp(new ALvalueExp(iUse4), new APlusBinop(new TPlus("+")), new AIntConstExp(new TIntegerLiteral("1")));
                        AAssignmentExp assign = new AAssignmentExp(new TAssign("="), iUse3, binopExp);

                        //While (...){...}
                        AABlock innerWhile = new AABlock();
                        innerWhile.GetStatements().Add(new AExpStm(new TSemicolon(";"), deleteStructInvoke));
                        innerWhile.GetStatements().Add(new AExpStm(new TSemicolon(";"), assign));
                        AWhileStm whileStm = new AWhileStm(new TLParen("("), cond, new ABlockStm(new TLBrace("{"), innerWhile));

                        AABlock pBlock = (AABlock) node.Parent();
                        //pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node), new ALocalDeclStm(new TSemicolon(";"), deleteMeVar));
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node), new ALocalDeclStm(new TSemicolon(";"), iVar));
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node), whileStm);
                        //visitMeNext.Add(deleteMeVar);
                        visitMeNext.Add(whileStm);

                        data.ExpTypes[iVar.GetInit()] =
                            data.LvalueTypes[iUse1] =
                            data.LvalueTypes[iUse2] =
                            data.LvalueTypes[iUse3] =
                            data.LvalueTypes[iUse4] =
                            data.ExpTypes[cond.GetLeft()] =
                            data.ExpTypes[lenghCall] =
                            data.ExpTypes[(PExp) intToString.GetArgs()[0]] =
                            data.ExpTypes[binopExp.GetLeft()] =
                            data.ExpTypes[binopExp.GetRight()] =
                            data.ExpTypes[binopExp] =
                            data.ExpTypes[assign] = new ANamedType(new TIdentifier("int"), null);
                        data.ExpTypes[(PExp) lenghCall.GetArgs()[0]] =
                            data.ExpTypes[cond] = new ANamedType(new TIdentifier("bool"), null);
                        data.ExpTypes[lenghCall] =
                           // data.LvalueTypes[deleteMeUse1] =
                           // data.LvalueTypes[deleteMeUse2] =
                            data.ExpTypes[arrayLengthString.GetLeft()] =
                            data.ExpTypes[arrayLengthString.GetRight()] =
                            data.ExpTypes[arrayLengthString] =
                            data.ExpTypes[intToString] =
                            data.ExpTypes[binopExp1] =
                            data.ExpTypes[binopExp1.GetLeft()] =
                            data.ExpTypes[binopExp1.GetRight()] =
                            data.ExpTypes[binopExp2] =
                            data.ExpTypes[binopExp3] =
                            data.ExpTypes[binopExp3.GetRight()] =
                            data.ExpTypes[lenghCall] =
                            data.ExpTypes[lenghCall] =
                            data.ExpTypes[lenghCall] =
                            data.ExpTypes[lenghCall] = new ANamedType(new TIdentifier("string"), null);
                        data.ExpTypes[deleteStructInvoke] = new AVoidType(new TVoid("void"));

                        data.Locals[pBlock].Add(iVar);
                        //data.Locals[pBlock].Add(deleteMeVar);

                        data.LocalLinks[iUse1] =
                            data.LocalLinks[iUse2] =
                            data.LocalLinks[iUse3] =
                            data.LocalLinks[iUse4] = iVar;

                        //data.LocalLinks[deleteMeUse1] =
                        //    data.LocalLinks[deleteMeUse2] = deleteMeVar;

                        data.SimpleMethodLinks[lenghCall] =
                            data.Libraries.Methods.First(method => method.GetName().Text == lenghCall.GetName().Text);
                        data.SimpleMethodLinks[intToString] =
                            data.Libraries.Methods.First(method => method.GetName().Text == intToString.GetName().Text);

                        AStructDecl structDecl = data.StructTypeLinks[aBaseType];

                        if (!deleteStructMethod.ContainsKey(structDecl))
                            CreateDeleteStructMethod(node, structDecl, data);
                        data.SimpleMethodLinks[deleteStructInvoke] = deleteStructMethod[structDecl];
                    }

                    /*
                     * Convert delete <exp>
                     * to
                     * DeleteArray(<exp>);
                     *
                     */

                    ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("DeleteArray"), new ArrayList(){pointerString});
                    /*if (pointerString == null)
                    {
                        invoke.GetArgs().Add(node.GetExp());
                    }
                    else
                    {
                        ALocalLvalue local = new ALocalLvalue(new TIdentifier("pointerString"));
                        invoke.GetArgs().Add(new ALvalueExp(local));

                        data.LocalLinks[local] = pointerString;
                        data.LvalueTypes[local] =
                            data.ExpTypes[(PExp) invoke.GetArgs()[0]] = new ANamedType(new TIdentifier("string"), null);
                    }*/
                    data.ExpTypes[invoke] = new AVoidType(new TVoid("void"));
                    if (deleteArrayMethod == null)
                        CreateDeleteArrayMethod(node, data);
                    data.SimpleMethodLinks[invoke] = deleteArrayMethod;
                    visitMeNext.Add(invoke);

                    node.ReplaceBy(new AExpStm(new TSemicolon(";"), invoke));
                }
                else
                {
                    //Not array type
                    PExp pointerString = node.GetExp();
                    bool isIntPointer = Util.IsIntPointer(node, pointer.GetType(), data);
                    bool createdStructDelete = false;
                    if (Util.IsBulkCopy(pointer.GetType()))
                    {
                        node.GetExp().Apply(new MoveMethodDeclsOut("pointerVar", data));
                        pointerString = node.GetExp();

                        ANamedType aBaseType = (ANamedType) pointer.GetType();
                        /* Insert
                         *
                         * string deleteMeVar = node.getExp();
                         * DeleteStruct<name>(deleteMeVar);
                         *
                         */

                       /* AALocalDecl deleteMeVar = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                                  new ANamedType(new TIdentifier("string"), null),
                                                                  new TIdentifier("deleteMe"), node.GetExp());*/
                        //pointerString = deleteMeVar;
                        //ALocalLvalue deleteMeUse = new ALocalLvalue(new TIdentifier("deleteMeVar"));

                        PExp deleteExp = Util.MakeClone(pointerString, data);
                        AStructDecl structDecl = data.StructTypeLinks[aBaseType];
                        if (isIntPointer)
                        {
                            GlobalStructVars vars = CreateStructFields(node, structDecl, data);
                            int allocateLimit = int.Parse(structDecl.GetIntDim().Text);
                            if (vars.IdentifierArray != null)
                            {
                                int usedBits = allocateLimit == 0
                                                   ? 0
                                                   : ((int) Math.Floor(Math.Log(allocateLimit, 2)) + 1);
                                int bitsLeft = 31 - usedBits;
                                int biggestIdentifier = (1 << (bitsLeft + 1)) - 1;

                                AIntConstExp bitsLeftConst = new AIntConstExp(new TIntegerLiteral(bitsLeft.ToString()));
                                deleteExp = new ABinopExp(deleteExp, new ARBitShiftBinop(new TRBitShift(">>")),
                                                          bitsLeftConst);

                                data.ExpTypes[bitsLeftConst] =
                                    data.ExpTypes[deleteExp] = new ANamedType(new TIdentifier("int"), null);
                            }
                        }

                        ASimpleInvokeExp deleteStructInvoke = new ASimpleInvokeExp(new TIdentifier("DeleteStruct" + aBaseType.AsIdentifierString()), new ArrayList());
                        deleteStructInvoke.GetArgs().Add(deleteExp);

                        AABlock pBlock = (AABlock)node.Parent();
                        //pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node), new ALocalDeclStm(new TSemicolon(";"), deleteMeVar));
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(node), new AExpStm(new TSemicolon(";"), deleteStructInvoke));
                        //visitMeNext.Add(deleteMeVar);
                        visitMeNext.Add(deleteStructInvoke);

                        /*data.ExpTypes[(PExp) deleteStructInvoke.GetArgs()[0]] =
                            data.LvalueTypes[deleteMeUse] = new ANamedType(new TIdentifier("string"), null);*/
                        data.ExpTypes[deleteStructInvoke] = new AVoidType(new TVoid("void"));

                        //data.Locals[pBlock].Add(deleteMeVar);

                        //data.LocalLinks[deleteMeUse] = deleteMeVar;

                        if (!deleteStructMethod.ContainsKey(structDecl))
                            CreateDeleteStructMethod(node, structDecl, data);
                        data.SimpleMethodLinks[deleteStructInvoke] = deleteStructMethod[structDecl];
                        createdStructDelete = true;
                    }
                    if (!isIntPointer)
                    {
                        /*
                         * Convert delete <exp>
                         * to
                         * DeleteSimple(<exp>);
                         *
                         */

                        ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("DeleteObject"),
                                                                       new ArrayList() {pointerString});
                        /*if (pointerString == null)
                        {
                            invoke.GetArgs().Add(node.GetExp());
                        }
                        else
                        {
                            ALocalLvalue local = new ALocalLvalue(new TIdentifier("pointerString"));
                            invoke.GetArgs().Add(new ALvalueExp(local));

                            data.LocalLinks[local] = pointerString;
                            data.LvalueTypes[local] =
                                data.ExpTypes[(PExp)invoke.GetArgs()[0]] = new ANamedType(new TIdentifier("string"), null);
                        }*/
                        data.ExpTypes[invoke] = new AVoidType(new TVoid("void"));
                        if (deleteObjectMethod == null)
                            CreateDeleteObjectMethod(node, data);
                        data.SimpleMethodLinks[invoke] = deleteObjectMethod;
                        visitMeNext.Add(invoke);

                        node.ReplaceBy(new AExpStm(new TSemicolon(";"), invoke));
                    }
                    else if (createdStructDelete)
                    {
                        node.Parent().RemoveChild(node);
                    }
                    else
                    {
                        //There is an enrichment

                        PExp deleteExp = pointerString;
                        AEnrichmentDecl enrichmentDecl = data.EnrichmentTypeLinks[pointer.GetType()];
                        if (isIntPointer)
                        {
                            GlobalStructVars vars = CreateEnrichmentFields(node, enrichmentDecl, data);
                            int allocateLimit = int.Parse(enrichmentDecl.GetIntDim().Text);
                            if (vars.IdentifierArray != null)
                            {
                                int usedBits = allocateLimit == 0
                                                   ? 0
                                                   : ((int)Math.Floor(Math.Log(allocateLimit, 2)) + 1);
                                int bitsLeft = 31 - usedBits;

                                AIntConstExp bitsLeftConst = new AIntConstExp(new TIntegerLiteral(bitsLeft.ToString()));
                                deleteExp = new ABinopExp(deleteExp, new ARBitShiftBinop(new TRBitShift(">>")),
                                                          bitsLeftConst);

                                data.ExpTypes[bitsLeftConst] =
                                    data.ExpTypes[deleteExp] = new ANamedType(new TIdentifier("int"), null);
                            }
                        }

                        ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("DeleteObject"),
                                                                       new ArrayList() { deleteExp });

                        data.ExpTypes[invoke] = new AVoidType(new TVoid("void"));
                        data.SimpleMethodLinks[invoke] = CreateDeleteEnrichmentMethod(node, enrichmentDecl, data);
                        visitMeNext.Add(invoke);

                        node.ReplaceBy(new AExpStm(new TSemicolon(";"), invoke));

                    }
                }
                bool hadPointerPreviously = hadPointer;
                PExp previosNameExp = nameExp;
                for (int i = 0; i < visitMeNext.Count; i++)
                {
                    hadPointer = false;
                    nameExp = null;
                    visitMeNext[i].Apply(this);
                }
                hadPointer = hadPointerPreviously;
                nameExp = previosNameExp;
            }
            public override void CaseAPArrayLengthLvalue(APArrayLengthLvalue node)
            {
                base.CaseAPArrayLengthLvalue(node);
                ABinopExp binopExp = new ABinopExp(nameExp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"\\\\Length\"")));
                ABooleanConstExp trueConst = new ABooleanConstExp(new ATrueBool());
                ASimpleInvokeExp invoke = new ASimpleInvokeExp(new TIdentifier("DataTableGetInt"), new ArrayList(){trueConst, binopExp});
                ALvalueExp parent = (ALvalueExp) node.Parent();
                parent.ReplaceBy(invoke);

                data.ExpTypes[binopExp] =
                    data.ExpTypes[binopExp.GetRight()] = new ANamedType(new TIdentifier("string"), null);

                data.ExpTypes[trueConst] = new ANamedType(new TIdentifier("bool"), null);

                data.ExpTypes[invoke] = new ANamedType(new TIdentifier("int"), null);

                data.SimpleMethodLinks[invoke] =
                    data.Libraries.Methods.First(m => m.GetName().Text == invoke.GetName().Text);

                nameExp = null;
                hadPointer = false;
            }
            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 CaseAArrayLvalue(AArrayLvalue node)
            {
                hadPointer = false;
                node.GetIndex().Apply(this);
                if (hadPointer)
                {//The index is a dynamic int
                    string typeName = ((ANamedType) data.ExpTypes[node.GetIndex()]).AsString();
                    node.GetIndex().ReplaceBy(CreateDynaicGetStm(typeName));
                }
                node.GetBase().Apply(this);
                if (hadPointer)
                {

                    //if (Util.GetAncestor<AAssignmentExp>(node) != null || Util.GetAncestor<APArrayLengthLvalue>(node) != null)
                    {
                        //Todo: Check if the index is within array (runtime)

                        ASimpleInvokeExp intToString = new ASimpleInvokeExp(new TIdentifier("IntToString"),
                                                                            new ArrayList());
                        intToString.GetArgs().Add(Util.MakeClone(node.GetIndex(), data));

                        ABinopExp binopExp1 = new ABinopExp(nameExp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"[\"")));
                        ABinopExp binopExp2 = new ABinopExp(binopExp1, new APlusBinop(new TPlus("+")), intToString);
                        ABinopExp binopExp3 = new ABinopExp(binopExp2, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"]\"")));

                        data.ExpTypes[binopExp1] =
                        data.ExpTypes[binopExp2] =
                        data.ExpTypes[binopExp3] =
                        data.ExpTypes[binopExp1.GetRight()] =
                        data.ExpTypes[binopExp3.GetRight()] =
                            data.ExpTypes[intToString] =new ANamedType(new TIdentifier("string"), null);
                        data.SimpleMethodLinks[intToString] =
                            data.Libraries.Methods.First(method => method.GetName().Text == intToString.GetName().Text);
                        nameExp = binopExp3;
                    }
                    CheckDynamicLvalue(node);
                }
            }
            public static AMethodDecl CreateDeleteArrayMethod(Node node, SharedData data)
            {
                if (deleteArrayMethod != null)
                    return deleteArrayMethod;
                /*  void DeleteArray(string id)
                    {
                        int length = DataTableGetInt(true, id + "\\Length");
                        while (length > 0)
                        {
                            length = length - 1;
                            DataTableValueRemove(true, id + "[" + IntToString(length) + "]");
                        }
                        DataTableValueRemove(true, id + "\\Length");
                        DataTableValueRemove(true, id + "\\Exists");
                    }
                 */

                AALocalDecl idDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("string"), null), new TIdentifier("id"), null);
                AABlock block = new AABlock();
                AMethodDecl method = new AMethodDecl(new APublicVisibilityModifier(), null, null, null, null, null, new AVoidType(new TVoid("void")),
                                                     new TIdentifier("DeleteArray"), new ArrayList() { idDecl }, block);

                ALocalLvalue idLink1 = new ALocalLvalue(new TIdentifier("id"));
                ALvalueExp idLink1Exp = new ALvalueExp(idLink1);
                ABinopExp binopExp1 = new ABinopExp(idLink1Exp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"\\\\Length\"")));
                ABooleanConstExp trueConst1 = new ABooleanConstExp(new ATrueBool());
                ASimpleInvokeExp dataTableGetIntInvoke = new ASimpleInvokeExp(new TIdentifier("DataTableGetInt"), new ArrayList{trueConst1, binopExp1});
                AALocalDecl lengthDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("int"), null), new TIdentifier("length"), dataTableGetIntInvoke);
                block.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), lengthDecl));

                ALocalLvalue lengthLink1 = new ALocalLvalue(new TIdentifier("length"));
                ALvalueExp lengthLink1Exp = new ALvalueExp(lengthLink1);
                ABinopExp binopExp2 = new ABinopExp(lengthLink1Exp, new AGtBinop(new TGt(">")), new AIntConstExp(new TIntegerLiteral("0")));
                AABlock whileBlock = new AABlock();
                block.GetStatements().Add(new AWhileStm(new TLParen("("), binopExp2,
                                                        new ABlockStm(new TLBrace("{"), whileBlock)));

                ALocalLvalue lengthLink2 = new ALocalLvalue(new TIdentifier("length"));
                ALvalueExp lengthLink2Exp = new ALvalueExp(lengthLink2);
                ALocalLvalue lengthLink3 = new ALocalLvalue(new TIdentifier("length"));
                ABinopExp binopExp3 = new ABinopExp(lengthLink2Exp, new AMinusBinop(new TMinus("-")), new AIntConstExp(new TIntegerLiteral("1")));
                AAssignmentExp assignment = new AAssignmentExp(new TAssign("="), lengthLink3, binopExp3);
                whileBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), assignment));

                ABooleanConstExp trueConst2 = new ABooleanConstExp(new ATrueBool());
                ALocalLvalue idLink2 = new ALocalLvalue(new TIdentifier("id"));
                ALvalueExp idLink2Exp = new ALvalueExp(idLink2);
                ALocalLvalue lengthLink4 = new ALocalLvalue(new TIdentifier("length"));
                ALvalueExp lengthLink4Exp = new ALvalueExp(lengthLink4);
                ASimpleInvokeExp intToStringInvoke = new ASimpleInvokeExp(new TIdentifier("IntToString"), new ArrayList(){lengthLink4Exp});
                ABinopExp binopExp4 = new ABinopExp(idLink2Exp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"[\"")));
                ABinopExp binopExp5 = new ABinopExp(binopExp4, new APlusBinop(new TPlus("+")), intToStringInvoke);
                ABinopExp binopExp6 = new ABinopExp(binopExp5, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"]\"")));
                ASimpleInvokeExp dataTableRemoveInvoke1 = new ASimpleInvokeExp(new TIdentifier("DataTableValueRemove"), new ArrayList(){trueConst2, binopExp6});
                whileBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), dataTableRemoveInvoke1));

                ABooleanConstExp trueConst3 = new ABooleanConstExp(new ATrueBool());
                ALocalLvalue idLink3 = new ALocalLvalue(new TIdentifier("id"));
                ALvalueExp idLink3Exp = new ALvalueExp(idLink3);
                ABinopExp binopExp7 = new ABinopExp(idLink3Exp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"\\\\Length\"")));
                ASimpleInvokeExp dataTableRemoveInvoke2 = new ASimpleInvokeExp(new TIdentifier("DataTableValueRemove"), new ArrayList() { trueConst3, binopExp7 });
                block.GetStatements().Add(new AExpStm(new TSemicolon(";"), dataTableRemoveInvoke2));

                ABooleanConstExp trueConst4 = new ABooleanConstExp(new ATrueBool());
                ALocalLvalue idLink4 = new ALocalLvalue(new TIdentifier("id"));
                ALvalueExp idLink4Exp = new ALvalueExp(idLink4);
                ABinopExp binopExp8 = new ABinopExp(idLink4Exp, new APlusBinop(new TPlus("+")), new AStringConstExp(new TStringLiteral("\"\\\\Exists\"")));
                ASimpleInvokeExp dataTableRemoveInvoke3 = new ASimpleInvokeExp(new TIdentifier("DataTableValueRemove"), new ArrayList() { trueConst4, binopExp8 });
                block.GetStatements().Add(new AExpStm(new TSemicolon(";"), dataTableRemoveInvoke3));

                AASourceFile sourceFile = Util.GetAncestor<AASourceFile>(node);
                sourceFile.GetDecl().Add(method);
                data.Methods.Add(new SharedData.DeclItem<AMethodDecl>(sourceFile, method));

                data.Locals[block] = new List<AALocalDecl> { idDecl, lengthDecl };
                data.LocalLinks[idLink1] =
                    data.LocalLinks[idLink2] =
                    data.LocalLinks[idLink3] =
                    data.LocalLinks[idLink4] = idDecl;
                data.LocalLinks[lengthLink1] =
                    data.LocalLinks[lengthLink2] =
                    data.LocalLinks[lengthLink3] =
                    data.LocalLinks[lengthLink4] = lengthDecl;

                data.SimpleMethodLinks[dataTableRemoveInvoke1] =
                data.SimpleMethodLinks[dataTableRemoveInvoke2] =
                data.SimpleMethodLinks[dataTableRemoveInvoke3] =
                    data.Libraries.Methods.First(m => m.GetName().Text == dataTableRemoveInvoke1.GetName().Text);
                data.SimpleMethodLinks[dataTableGetIntInvoke] =
                    data.Libraries.Methods.First(m => m.GetName().Text == dataTableGetIntInvoke.GetName().Text);
                data.SimpleMethodLinks[intToStringInvoke] =
                    data.Libraries.Methods.First(m => m.GetName().Text == intToStringInvoke.GetName().Text);

                data.LvalueTypes[idLink1] =
                    data.LvalueTypes[idLink2] =
                    data.LvalueTypes[idLink3] =
                    data.LvalueTypes[idLink4] =
                    data.ExpTypes[idLink1Exp] =
                    data.ExpTypes[idLink2Exp] =
                    data.ExpTypes[idLink3Exp] =
                    data.ExpTypes[idLink4Exp] =
                    data.ExpTypes[binopExp1] =
                    data.ExpTypes[binopExp4] =
                    data.ExpTypes[binopExp5] =
                    data.ExpTypes[binopExp6] =
                    data.ExpTypes[binopExp7] =
                    data.ExpTypes[binopExp8] =
                    data.ExpTypes[binopExp1.GetRight()] =
                    data.ExpTypes[binopExp4.GetRight()] =
                    data.ExpTypes[binopExp6.GetRight()] =
                    data.ExpTypes[binopExp7.GetRight()] =
                    data.ExpTypes[binopExp8.GetRight()] =
                    data.ExpTypes[intToStringInvoke] = new ANamedType(new TIdentifier("string"), null);

                data.ExpTypes[trueConst1] =
                    data.ExpTypes[trueConst2] =
                    data.ExpTypes[trueConst3] =
                    data.ExpTypes[trueConst4] =
                    data.ExpTypes[binopExp2] = new ANamedType(new TIdentifier("bool"), null);

                data.LvalueTypes[lengthLink1] =
                    data.LvalueTypes[lengthLink2] =
                    data.LvalueTypes[lengthLink3] =
                    data.LvalueTypes[lengthLink4] =
                    data.ExpTypes[lengthLink1Exp] =
                    data.ExpTypes[lengthLink2Exp] =
                    data.ExpTypes[lengthLink4Exp] =
                    data.ExpTypes[binopExp3] =
                    data.ExpTypes[binopExp2.GetRight()] =
                    data.ExpTypes[binopExp3.GetRight()] =
                    data.ExpTypes[dataTableGetIntInvoke] =
                    data.ExpTypes[assignment] = new ANamedType(new TIdentifier("int"), null);

                data.ExpTypes[dataTableRemoveInvoke1] =
                    data.ExpTypes[dataTableRemoveInvoke2] =
                    data.ExpTypes[dataTableRemoveInvoke3] = new AVoidType(new TVoid("void"));

                deleteArrayMethod = method;
                return deleteArrayMethod;
            }
 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());
                 }
             }
         }
     }
 }
            public override void CaseAPointerLvalue(APointerLvalue node)
            {
                //Build the list
                currentPointer.Clear();
                base.CaseAPointerLvalue(node);

                //Todo: insert runtime check here
                //if (currentPointer.Count == 0 || !setPointers.Contains(MakePointer(currentPointer)))
                if (!isSet)
                {
                    PStm pStm = Util.GetAncestor<PStm>(node);
                    if (pStm != null)
                    {
                        AABlock pBlock = (AABlock) pStm.Parent();
                        /*
                         *  if (<pointer> == null)
                         *  {
                         *      UIDisplayMessage(PlayerGroupAll, messageAreaDebug, StringToText(<filename>[<lineNr>:<pos>] + " null pointer exception"));
                         *      int i = 1 / 0;
                         *  }
                         */
                        AASourceFile currentSourceFile = Util.GetAncestor<AASourceFile>(node);

                        node.GetBase().Apply(new MoveMethodDeclsOut("pointerVar", data));
                        PExp pointer = Util.MakeClone(node.GetBase(), data);
                        ABinopExp cond = new ABinopExp(pointer, new AEqBinop(new TEq("==")), new ANullExp());
                        AABlock ifBlock = new AABlock();
                        ASimpleInvokeExp playerGroupAllInvoke = new ASimpleInvokeExp(new TIdentifier("PlayerGroupAll"), new ArrayList());
                        AFieldLvalue messageAreaDebugLink = new AFieldLvalue(new TIdentifier("c_messageAreaDebug"));
                        ALvalueExp messageAreaDebugLinkExp = new ALvalueExp(messageAreaDebugLink);
                        ASimpleInvokeExp stringToTextInvoke = new ASimpleInvokeExp(new TIdentifier("StringToText"),
                                                                                   new ArrayList()
                                                                                       {
                                                                                           new AStringConstExp(
                                                                                               new TStringLiteral("\"" +
                                                                                                                  currentSourceFile
                                                                                                                      .
                                                                                                                      GetName
                                                                                                                      ()
                                                                                                                      .
                                                                                                                      Text +
                                                                                                                  "[" +
                                                                                                                  node.
                                                                                                                      GetTokens
                                                                                                                      ()
                                                                                                                      .
                                                                                                                      Line +
                                                                                                                  "," +
                                                                                                                  node.
                                                                                                                      GetTokens
                                                                                                                      ()
                                                                                                                      .
                                                                                                                      Pos +
                                                                                                                  "]: Null pointer exception\""))
                                                                                       });
                        ASimpleInvokeExp displayMessageInvoke = new ASimpleInvokeExp(
                            new TIdentifier("UIDisplayMessage"),
                            new ArrayList() {playerGroupAllInvoke, messageAreaDebugLinkExp, stringToTextInvoke});
                        ifBlock.GetStatements().Add(new AExpStm(new TSemicolon(";"), displayMessageInvoke));

                        ABinopExp iDeclInit = new ABinopExp(new AIntConstExp(new TIntegerLiteral("1")),
                                                            new ADivideBinop(new TDiv("/")),
                                                            new AIntConstExp(new TIntegerLiteral("0")));
                        AALocalDecl iDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, new ANamedType(new TIdentifier("int"), null), new TIdentifier("i"), iDeclInit);
                        ifBlock.GetStatements().Add(new ALocalDeclStm(new TSemicolon(";"), iDecl));

                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm),
                                                      new AIfThenStm(new TLParen("("), cond,
                                                                     new ABlockStm(new TLBrace("{"), ifBlock)));

                        data.Locals[ifBlock] = new List<AALocalDecl>(){iDecl};
                        data.ExpTypes[cond.GetRight()] = new ANullType();
                        data.ExpTypes[cond] = new ANamedType(new TIdentifier("bool"), null);
                        data.ExpTypes[playerGroupAllInvoke] = new ANamedType(new TIdentifier("playergroup"), null);
                        data.ExpTypes[messageAreaDebugLinkExp] =
                            data.LvalueTypes[messageAreaDebugLink] =
                            data.ExpTypes[iDeclInit] =
                            data.ExpTypes[iDeclInit.GetLeft()] =
                            data.ExpTypes[iDeclInit.GetRight()] = new ANamedType(new TIdentifier("int"), null);
                        data.ExpTypes[stringToTextInvoke] = new ANamedType(new TIdentifier("text"), null);
                        data.ExpTypes[(PExp) stringToTextInvoke.GetArgs()[0]] = new ANamedType(new TIdentifier("string"), null);
                        data.ExpTypes[displayMessageInvoke] = new AVoidType(new TVoid("void"));

                        data.SimpleMethodLinks[playerGroupAllInvoke] =
                            data.Libraries.Methods.Find(m => m.GetName().Text == playerGroupAllInvoke.GetName().Text);
                        data.SimpleMethodLinks[displayMessageInvoke] =
                            data.Libraries.Methods.Find(m => m.GetName().Text == displayMessageInvoke.GetName().Text);
                        data.SimpleMethodLinks[stringToTextInvoke] =
                            data.Libraries.Methods.Find(m => m.GetName().Text == stringToTextInvoke.GetName().Text);
                        data.FieldLinks[messageAreaDebugLink] =
                            data.Libraries.Fields.Find(f => f.GetName().Text == messageAreaDebugLink.GetName().Text);

                        if (currentPointer.Count > 0)
                        {
                            setPointers.Add(MakePointer(currentPointer));
                        }
                    }
                }

                currentPointer.Add(new PointerPointer());
                currentPointer = MakePointer(currentPointer);
                isSet = Contains(setPointers, currentPointer);
                isExposed = Contains(exposedPointers, currentPointer);

                //If the currentPointer is in null pointers, report error.. and then again - we might not reach this statement - warning, and runtime check
                //If the currentPointer is not in setPointers, insert runtime check
            }