public virtual void CaseAPointerLvalue(APointerLvalue node)
 {
     DefaultCase(node);
 }
 public override void CaseAPointerLvalue(APointerLvalue node)
 {
     InAPointerLvalue(node);
     if (node.GetBase() != null)
     {
         node.GetBase().Apply(this);
     }
     if (node.GetTokens() != null)
     {
         node.GetTokens().Apply(this);
     }
     OutAPointerLvalue(node);
 }
 public override void CaseAPointerLvalue(APointerLvalue node)
 {
     IsConst = false;
 }
        public override void OutAPointerMultiLvalue(APointerMultiLvalue node)
        {
            ALvalueExp lvalueExp;
            APointerLvalue pointerLvalue = new APointerLvalue((TStar) node.GetTokens()[0], node.GetBase());

            while (node.GetTokens().Count > 0)
            {
                lvalueExp = new ALvalueExp(pointerLvalue);
                pointerLvalue = new APointerLvalue((TStar) node.GetTokens()[0], lvalueExp);
            }

            node.ReplaceBy(pointerLvalue);
            pointerLvalue.Apply(this);
        }
        public override void OutAArrayLvalue(AArrayLvalue node)
        {
            PType type = data.ExpTypes[node.GetBase()];
            PType argType = data.ExpTypes[node.GetIndex()];

            List<APropertyDecl> matchingArrayProperties = new List<APropertyDecl>();
            List<APropertyDecl> implicitStructArrayProperties = new List<APropertyDecl>();

            if (type is ANamedType && data.StructTypeLinks.ContainsKey((ANamedType)type))
            {
                AStructDecl structDecl = data.StructTypeLinks[(ANamedType) type];
                foreach (APropertyDecl property in data.StructProperties[structDecl])
                {
                    if (property.GetName().Text == "")
                    {
                        PType proprtyArgType = data.ArrayPropertyLocals[property][0].GetType();
                        if (Assignable(argType, proprtyArgType))
                            matchingArrayProperties.Add(property);
                    }
                }
            }

            if (type is APointerType)
            {
                APointerType aType = (APointerType)type;
                PType baseType = aType.GetType();
                if (baseType is ANamedType && data.StructTypeLinks.ContainsKey((ANamedType)baseType))
                {
                    AStructDecl structDecl = data.StructTypeLinks[(ANamedType)baseType];
                    foreach (APropertyDecl property in data.StructProperties[structDecl])
                    {
                        if (property.GetName().Text == "")
                        {
                            PType proprtyArgType = data.ArrayPropertyLocals[property][0].GetType();
                            if (Assignable(argType, proprtyArgType))
                                implicitStructArrayProperties.Add(property);
                        }
                    }
                }
            }

            List<IList> visibleDecls = Util.GetVisibleDecls(node, true);
            foreach (IList declList in visibleDecls)
            {
                foreach (PDecl decl in declList)
                {
                    if (decl is AEnrichmentDecl)
                    {
                        AEnrichmentDecl enrichment = (AEnrichmentDecl)decl;
                        if (Util.TypesEqual(type, enrichment.GetType(), data))
                        {
                            foreach (PDecl enrichmentDecl in enrichment.GetDecl())
                            {
                                if (enrichmentDecl is APropertyDecl)
                                {
                                    APropertyDecl property = (APropertyDecl) enrichmentDecl;
                                    if (property.GetName().Text == "")
                                    {
                                        PType proprtyArgType = data.ArrayPropertyLocals[property][0].GetType();
                                        if (Assignable(argType, proprtyArgType))
                                            matchingArrayProperties.Add(property);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            bool matchesNormalArray = false;
            ALvalueExp replaceBaseExp = null;
            if (Assignable(argType, new ANamedType(new TIdentifier("int"), null)))
            {
                if (type is AArrayTempType)
                {
                    AArrayTempType aType = (AArrayTempType) type;
                    type = aType.GetType();
                    matchesNormalArray = true;
                }
                else if (type is ADynamicArrayType)
                {
                    ADynamicArrayType aType = (ADynamicArrayType) type;
                    type = aType.GetType();
                    matchesNormalArray = true;
                }
                else if (type is APointerType)
                {
                    //Implicit conversion for a[] to (*a)[]
                    APointerType aType = (APointerType) type;
                    if (aType.GetType() is AArrayTempType || aType.GetType() is ADynamicArrayType)
                    {
                        APointerLvalue pointer = new APointerLvalue(new TStar("*"), node.GetBase());
                        replaceBaseExp = new ALvalueExp(pointer);
                        matchesNormalArray = true;
                    }
                }
            }
            if (matchingArrayProperties.Count == 0 && !matchesNormalArray && implicitStructArrayProperties.Count == 0)
                errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile, LocRM.GetString("ErrorText72")));

            if (matchingArrayProperties.Count + (matchesNormalArray ? 1 : 0) > 1)
            {
                List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>();
                foreach (APropertyDecl property in matchingArrayProperties)
                {
                    subErrors.Add(new ErrorCollection.Error(property.GetName(), LocRM.GetString("ErrorText62")));
                }
                if (matchesNormalArray)
                    subErrors.Add(new ErrorCollection.Error(node.GetToken(), LocRM.GetString("ErrorText74")));
                errors.Add(new ErrorCollection.Error(node.GetToken(), LocRM.GetString("ErrorText73"), false, subErrors.ToArray()));
                throw new ParserException(node.GetToken(), "TypeChecking.OutAArrayLvalue");
            }

            if (matchingArrayProperties.Count + (matchesNormalArray ? 1 : 0) == 0 &&
                implicitStructArrayProperties.Count > 1)
            {
                List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>();
                foreach (APropertyDecl property in implicitStructArrayProperties)
                {
                    subErrors.Add(new ErrorCollection.Error(property.GetName(), LocRM.GetString("ErrorText62")));
                }
                errors.Add(new ErrorCollection.Error(node.GetToken(), LocRM.GetString("ErrorText73"), false, subErrors.ToArray()));
                throw new ParserException(node.GetToken(), "TypeChecking.OutAArrayLvalue");
            }

            if (matchingArrayProperties.Count == 1)
            {
                APropertyDecl property = matchingArrayProperties[0];
                type = property.GetType();
                data.ArrayPropertyLinks[node] = new Util.Pair<APropertyDecl, bool>(property, false);

                CheckPropertyAccessibility(property, node.Parent() is AAssignmentExp, node.GetToken());
            }
            else if (implicitStructArrayProperties.Count == 1)
            {
                APropertyDecl property = implicitStructArrayProperties[0];
                type = property.GetType();
                data.ArrayPropertyLinks[node] = new Util.Pair<APropertyDecl, bool>(property, true);

                CheckPropertyAccessibility(property, node.Parent() is AAssignmentExp, node.GetToken());
            }

            if (replaceBaseExp == null)
                data.LvalueTypes[node] = type;
            else
            {
                node.SetBase(replaceBaseExp);
                //pointer.Apply(this);
                OutAPointerLvalue((APointerLvalue)replaceBaseExp.GetLvalue());
                OutALvalueExp(replaceBaseExp);
                OutAArrayLvalue(node);
            }

            //if (!Assignable(data.ExpTypes[node.GetIndex()], new ANamedType(new TIdentifier("int"), null)))
            //    errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile, "Indexes of arrays must be of integer type."));
        }
        public override void OutAPointerLvalue(APointerLvalue node)
        {
            PType type = data.ExpTypes[node.GetBase()];
            if (!(type is APointerType))
            {
                errors.Add(new ErrorCollection.Error(node.GetTokens(), currentSourceFile, LocRM.GetString("ErrorText149")));
                data.LvalueTypes[node] = type;
            }
            else
            {
                data.LvalueTypes[node] = ((APointerType) type).GetType();
            }

            base.OutAPointerLvalue(node);
        }
        public override void CaseASimpleInvokeExp(ASimpleInvokeExp node)
        {
            AMethodDecl decl = finalTrans.data.SimpleMethodLinks[node];
            if (structMethods.Contains(decl))
            {//The target is a struct method that has been moved out
                if (node.GetArgs().Count < decl.GetFormals().Count && Util.HasAncestor<AStructDecl>(node))
                {//If this is the case, we Must be inside the same struct as the target. - Not with enheritance
                    ALocalLvalue local = new ALocalLvalue(new TIdentifier("tempName"));
                    ALvalueExp exp = new ALvalueExp(local);
                    finalTrans.data.LvalueTypes[local] =
                        finalTrans.data.ExpTypes[exp] = structFormal.GetType();
                    finalTrans.data.LocalLinks[local] = structFormal;

                    //If we're calling from class to struct, we must depointer it
                    AStructDecl currentStruct =
                        finalTrans.data.StructMethods.First(
                            pair => pair.Value.Contains(Util.GetAncestor<AMethodDecl>(node))).Key;
                    AStructDecl baseStruct =
                        finalTrans.data.StructMethods.First(
                            pair => pair.Value.Contains(decl)).Key;
                    if (currentStruct.GetClassToken() != baseStruct.GetClassToken()) //It's not possible to call from struct to class
                    {
                        APointerLvalue pointerLvalue = new APointerLvalue(new TStar("*"), exp);
                        exp = new ALvalueExp(pointerLvalue);

                        finalTrans.data.LvalueTypes[pointerLvalue] =
                            finalTrans.data.ExpTypes[exp] = ((APointerType)structFormal.GetType()).GetType();
                    }

                    node.GetArgs().Add(exp);
                }
            }
            else if (Util.GetAncestor<AStructDecl>(decl) != null && OldParentStruct.ContainsKey(Util.GetAncestor<AMethodDecl>(node)))
            {//The target is a struct method that hasn't been moved out
                if (Util.GetAncestor<AStructDecl>(decl) == OldParentStruct[Util.GetAncestor<AMethodDecl>(node)] && decl.GetStatic() == null)
                {//We have an internal struct call. Expect to have one too many args
                    if (node.GetArgs().Count == decl.GetFormals().Count)
                    {
                        ALocalLvalue local = new ALocalLvalue(new TIdentifier("tempName"));
                        ALvalueExp exp = new ALvalueExp(local);
                        finalTrans.data.LvalueTypes[local] =
                            finalTrans.data.ExpTypes[exp] = structFormal.GetType();
                        finalTrans.data.LocalLinks[local] = structFormal;

                        //If we're calling from class to struct, we must depointer it
                        AStructDecl currentStruct =
                            finalTrans.data.StructMethods.First(
                                pair => pair.Value.Contains(Util.GetAncestor<AMethodDecl>(node))).Key;
                        AStructDecl baseStruct =
                            finalTrans.data.StructMethods.First(
                                pair => pair.Value.Contains(decl)).Key;
                        if (currentStruct.GetClassToken() != baseStruct.GetClassToken()) //It's not possible to call from struct to class
                        {
                            APointerLvalue pointerLvalue = new APointerLvalue(new TStar("*"), exp);
                            exp = new ALvalueExp(pointerLvalue);

                            finalTrans.data.LvalueTypes[pointerLvalue] =
                                finalTrans.data.ExpTypes[exp] = ((APointerType)structFormal.GetType()).GetType();
                        }

                        node.GetArgs().Add(exp);
                    }
                }
            }
            base.CaseASimpleInvokeExp(node);
        }
            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
            }
            private AALocalDecl TurnDynamic(PExp exp, AALocalDecl targetDecl, PType type, bool assignBefore = true, bool assignAfter = false, bool makeDelete = true)
            {
                exp.Apply(mover);
                //insert
                //<basetype>[]* bulkCopyVar = new <baseType>[<dim>]();
                //bulkCopyVar[0] = arg[0];
                //bulkCopyVar[1] = arg[1];
                //bulkCopyVar[2] = arg[2];
                //...
                //Invoke(..., bulkCopyVar, ...);

                //If we need to clean up after, move the exp to it's own statement.

                AALocalDecl newLocal;
                if (type is AArrayTempType)
                {
                    AArrayTempType aType = (AArrayTempType) type;
                    ANewExp newExp = new ANewExp(new TNew("new"), new AArrayTempType(
                                                                       new TLBracket("["),
                                                                       Util.MakeClone(aType.GetType(),
                                                                                      data),
                                                                       Util.MakeClone(aType.GetDimention(), data),
                                                                       (TIntegerLiteral)
                                                                       aType.GetIntDim().Clone()),
                                                 new ArrayList());
                    newLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                               new APointerType(new TStar("*"),
                                                                new ADynamicArrayType(
                                                                    new TLBracket("["),
                                                                    Util.MakeClone(aType.GetType(),
                                                                                   data))),
                                               new TIdentifier("bulkCopyVar"),
                                               newExp
                        );
                }
                else
                {
                    ANewExp newExp = new ANewExp(new TNew("new"), Util.MakeClone(type, data),
                                                 new ArrayList());
                    newLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                               new APointerType(new TStar("*"),
                                                                Util.MakeClone(type, data)),
                                               new TIdentifier("bulkCopyVar"),
                                               newExp
                        );
                }
                PStm pStm = Util.GetAncestor<PStm>(exp);
                AABlock pBlock = (AABlock) pStm.Parent();
                pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm),
                                                new ALocalDeclStm(new TSemicolon(";"), newLocal));
                PLvalue bulkCopyRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                data.LocalLinks[(ALocalLvalue) bulkCopyRef] = newLocal;
                data.LvalueTypes[bulkCopyRef] = newLocal.GetType();

                ALvalueExp bulkCopyRefExp;
                //if (!(type is AArrayTempType))
                {
                    bulkCopyRefExp = new ALvalueExp(bulkCopyRef);
                    bulkCopyRef = new APointerLvalue(new TStar("*"), bulkCopyRefExp);
                    data.ExpTypes[bulkCopyRefExp] = newLocal.GetType();
                    data.LvalueTypes[bulkCopyRef] = type;
                }

                if (assignBefore)
                {
                    List<PStm> stms = MakeAssignments(bulkCopyRef, exp, new List<AALocalDecl>() {targetDecl});
                    foreach (PStm stm in stms)
                    {
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), stm);
                    }
                }
                int addStms = 1;
                if (assignAfter)
                {
                    bulkCopyRefExp = new ALvalueExp(bulkCopyRef);
                    data.ExpTypes[bulkCopyRefExp] = data.LvalueTypes[bulkCopyRef];
                    List<PStm> stms = MakeAssignments(((ALvalueExp)exp).GetLvalue(), bulkCopyRefExp, new List<AALocalDecl>() {targetDecl});
                    addStms += stms.Count;
                    foreach (PStm stm in stms)
                    {
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + 1, stm);
                    }
                }

                bulkCopyRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                bulkCopyRefExp = new ALvalueExp(bulkCopyRef);
                data.LocalLinks[(ALocalLvalue) bulkCopyRef] = newLocal;
                data.LvalueTypes[bulkCopyRef] = data.ExpTypes[bulkCopyRefExp] = newLocal.GetType();
                exp.ReplaceBy(bulkCopyRefExp);

                /*if (formal.GetRef() != null || formal.GetOut() != null)
                {
                    //Get args back
                }*/
                //Delete object

                if (makeDelete)
                {
                    bulkCopyRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                    bulkCopyRefExp = new ALvalueExp(bulkCopyRef);
                    data.LocalLinks[(ALocalLvalue) bulkCopyRef] = newLocal;
                    data.LvalueTypes[bulkCopyRef] = data.ExpTypes[bulkCopyRefExp] = newLocal.GetType();
                    pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + addStms,
                                                  new ADeleteStm(new TDelete("delete"), bulkCopyRefExp));
                }
                return newLocal;
            }
        public override void OutAStructDecl(AStructDecl node)
        {
            //Insert init in each constructor
            AThisLvalue thisLvalue = new AThisLvalue(new TThis("this"));
            ALvalueExp thisExp = new ALvalueExp(thisLvalue);
            APointerLvalue pointerLvalue = new APointerLvalue(new TStar("*"), thisExp);

            ANamedType namedType = new ANamedType(new TIdentifier(node.GetName().Text), null);
            data.StructTypeLinks[namedType] = node;
            data.LvalueTypes[thisLvalue] =
                data.ExpTypes[thisExp] = new APointerType(new TStar("*"), namedType);
            data.LvalueTypes[pointerLvalue] = namedType;

            foreach (AConstructorDecl constructor in node.GetLocals().OfType<ADeclLocalDecl>().Select(decl => decl.GetDecl()).OfType<AConstructorDecl>())
            {
                AABlock block = new AABlock(new ArrayList(), new TRBrace("}"));
                MakeAssignments(block, namedType, pointerLvalue, false);

                ((AABlock)constructor.GetBlock()).GetStatements().Insert(0, new ABlockStm(new TLBrace("{"), block));
            }

            base.OutAStructDecl(node);
        }
            public override void CaseAPointerLvalue(APointerLvalue node)
            {
                hadPointer = false;
                nameExp = null;
                base.CaseAPointerLvalue(node);
                if (Util.IsIntPointer(node, data.LvalueTypes[node], data))
                {
                    if (nameExp != null)
                    {
                        //Create a data table get string exp
                        nameExp = CreateDynaicGetStm("int");
                    }
                    else
                    {
                        nameExp = node.GetBase();
                    }
                    //Replace by str_Array[<base>];
                    //If this is a compared pointer, replace it by str_Array[<base> >> <<bitsLeft>>]
                    GlobalStructVars vars;
                    int allocateLimit;
                    if (data.EnrichmentTypeLinks.ContainsKey(data.LvalueTypes[node]))
                    {
                        AEnrichmentDecl enrichmentDecl = data.EnrichmentTypeLinks[data.LvalueTypes[node]];
                        vars = CreateEnrichmentFields(node, enrichmentDecl, data);
                        allocateLimit = int.Parse(enrichmentDecl.GetIntDim().Text);
                    }
                    else
                    {
                        AStructDecl structDecl = data.StructTypeLinks[(ANamedType)data.LvalueTypes[node]];
                        vars = CreateStructFields(node, structDecl, data);
                        allocateLimit = int.Parse(structDecl.GetIntDim().Text);
                    }

                    AFieldLvalue array = new AFieldLvalue(new TIdentifier(vars.Array.GetName().Text));
                    ALvalueExp arrayExp = new ALvalueExp(array);

                    PExp arrayIndex = nameExp;
                    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()));
                        arrayIndex = new ABinopExp(arrayIndex, new ARBitShiftBinop(new TRBitShift(">>")), bitsLeftConst);

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

                    AArrayLvalue replacer = new AArrayLvalue(new TLBracket("["), arrayExp, arrayIndex);
                    node.ReplaceBy(replacer);

                    data.FieldLinks[array] = vars.Array;
                    data.LvalueTypes[array] = data.ExpTypes[arrayExp] = vars.Array.GetType();
                    data.LvalueTypes[replacer] = ((AArrayTempType) vars.Array.GetType()).GetType();

                    hadPointer = false;
                    nameExp = null;
                    return;
                }
                //if (Util.GetAncestor<AAssignmentExp>(node) != null || Util.GetAncestor<APArrayLengthLvalue>(node) != null)
                {
                    if (nameExp != null)
                    {
                        //Create a data table get string exp

                        nameExp = CreateDynaicGetStm("string");
                    }
                    else
                    {
                        nameExp = node.GetBase();
                    }
                }
                hadPointer = true;
                CheckDynamicLvalue(node);
                //Todo: Insert runtime check that the pointer is actually not null / points to a delete object
                //(unless the same pointer was checked before, and it has not been assigned to since, and there has not been a method call since.
            }
            public override void OutASimpleInvokeExp(ASimpleInvokeExp node)
            {
                if (data.BulkCopyProcessedInvokes.Contains(node))
                {
                    base.OutASimpleInvokeExp(node);
                    return;
                }

                //If anything needs to be put after the invoke, move it to it's own local decl or exp statement
                AMethodDecl method = data.SimpleMethodLinks[node];

                if (!processedMethods.Contains(method))
                    CaseAMethodDecl(method);

                bool moveOut = Util.IsBulkCopy(data.ExpTypes[node]);
                PType type;
                if (!moveOut)
                    for (int i = 0; i < node.GetArgs().Count; i++)
                    {
                        PExp arg = (PExp)node.GetArgs()[i];
                        AALocalDecl formal = (AALocalDecl)method.GetFormals()[i];
                        type = data.ExpTypes[arg];
                        if (Util.IsBulkCopy(type) || formal.GetRef() != null || formal.GetOut() != null)
                        {
                            moveOut = true;
                            break;
                        }
                    }
                if (moveOut && !(node.Parent() is AExpStm || node.Parent() is AALocalDecl))
                {
                    PStm pStm = Util.GetAncestor<PStm>(node);
                    AABlock pBlock = (AABlock) pStm.Parent();

                    //Can not be a void type, since it is not in an expStm
                    AALocalDecl localDecl = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null, Util.MakeClone(data.ExpTypes[node], data),
                                                            new TIdentifier("bulkCopyVar"), null);
                    ALocalLvalue bulkCopyVarRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                    ALvalueExp bulkCopyVarRefExp = new ALvalueExp(bulkCopyVarRef);
                    node.ReplaceBy(bulkCopyVarRefExp);
                    localDecl.SetInit(node);
                    pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm), new ALocalDeclStm(new TSemicolon(";"), localDecl));

                    data.LocalLinks[bulkCopyVarRef] = localDecl;
                    data.LvalueTypes[bulkCopyVarRef] =
                        data.ExpTypes[bulkCopyVarRefExp] = localDecl.GetType();
                }

                //Replace bulk copy arguments with a new pointer
                for (int i = 0; i < node.GetArgs().Count; i++)
                {
                    PExp arg = (PExp) node.GetArgs()[i];
                    AALocalDecl formal = (AALocalDecl) method.GetFormals()[i];
                    if (oldParameterTypes.ContainsKey(formal))
                        type = oldParameterTypes[formal];// data.ExpTypes[arg];
                    else
                        type = formal.GetType();
                    if (Util.IsBulkCopy(type) || formal.GetRef() != null || formal.GetOut() != null)
                    {
                        if (formal.GetRef() != null && arg is ALvalueExp)
                        {
                            ALvalueExp aArg = (ALvalueExp) arg;
                            if (aArg.GetLvalue() is APointerLvalue)
                            {
                                APointerLvalue pointer = (APointerLvalue) aArg.GetLvalue();
                                if (Util.TypesEqual(formal.GetType(), data.ExpTypes[pointer.GetBase()], data))
                                {//Just send the arg
                                    aArg.ReplaceBy(pointer.GetBase());
                                    continue;
                                }
                            }
                        }

                        TurnDynamic(arg, formal,
                                    oldParameterTypes.ContainsKey(formal) ? oldParameterTypes[formal] : formal.GetType(),
                                    formal.GetOut() == null,
                                    formal.GetRef() != null || formal.GetOut() != null);
                    }
                }
                //Do return stm
                type = data.ExpTypes[node];
                if (Util.IsBulkCopy(type))
                {
                    PStm pStm = Util.GetAncestor<PStm>(node);
                    AABlock pBlock = (AABlock)pStm.Parent();
                    bool isReturnUsed = !(node.Parent() is AExpStm);
                    if (isReturnUsed)
                    {
                        //Make
                        //var bulkCopyVar = <node>(...);
                        //<usage>... *bulkCopyVar ... </usage>
                        //delete bulkCopyVar;
                        bool isArray = type is AArrayTempType;
                        AALocalDecl newLocal = new AALocalDecl(new APublicVisibilityModifier(), null, null, null, null,
                                                               new APointerType(new TStar("*"),
                                                                                isArray
                                                                                    ? new ADynamicArrayType(
                                                                                          new TLBracket("["),
                                                                                          Util.MakeClone(
                                                                                              ((AArrayTempType) type).
                                                                                                  GetType(), data))
                                                                                    : Util.MakeClone(type, data)),
                                                               new TIdentifier("bulkCopyVar"), null);
                        data.ExpTypes[node] = newLocal.GetType();

                        ALocalLvalue newLocalRef;
                        ALvalueExp newLocalRefExp;
                        newLocalRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                        newLocalRefExp = new ALvalueExp(newLocalRef);
                        APointerLvalue newLocalPointer = new APointerLvalue(new TStar("*"), newLocalRefExp);
                        ALvalueExp newLocalPointerExp = new ALvalueExp(newLocalPointer);
                        node.ReplaceBy(newLocalPointerExp);

                        data.LocalLinks[newLocalRef] = newLocal;
                        data.LvalueTypes[newLocalRef] =
                            data.ExpTypes[newLocalRefExp] = newLocal.GetType();
                        data.LvalueTypes[newLocalPointer] =
                            data.ExpTypes[newLocalPointerExp] = ((APointerType) newLocal.GetType()).GetType();

                        newLocal.SetInit(node);

                        newLocalRef = new ALocalLvalue(new TIdentifier("bulkCopyVar"));
                        newLocalRefExp = new ALvalueExp(newLocalRef);
                        data.LocalLinks[newLocalRef] = newLocal;
                        data.LvalueTypes[newLocalRef] =
                            data.ExpTypes[newLocalRefExp] = newLocal.GetType();

                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm),
                                                      new ALocalDeclStm(new TSemicolon(";"), newLocal));
                        pBlock.GetStatements().Insert(pBlock.GetStatements().IndexOf(pStm) + 1,
                                                      new ADeleteStm(new TDelete("delete"), newLocalRefExp));
                    }
                    else
                    {
                        //Make delete <node>(...);
                        pStm.ReplaceBy(new ADeleteStm(new TDelete("delete"), node));
                    }
                }
                base.OutASimpleInvokeExp(node);
            }
            public override void CaseAMethodDecl(AMethodDecl node)
            {
                if (processedMethods.Contains(node))
                    return;
                processedMethods.Add(node);
                //For each bulk copy param, make it a pointer type
                foreach (AALocalDecl formal in node.GetFormals())
                {
                    PType type = formal.GetType();
                    if (Util.IsBulkCopy(type) || formal.GetRef() != null || formal.GetOut() != null)
                    {
                        if (type is AArrayTempType)
                        {//make dynamic array
                            AArrayTempType aType = (AArrayTempType) type;
                            List<PExp> exps = new List<PExp>();
                            PType newType = new APointerType(new TStar("*"),
                                                             new ADynamicArrayType((TLBracket)aType.GetToken().Clone(),
                                                                         Util.MakeClone(aType.GetType(), data)));
                            /*exps.AddRange(data.ExpTypes.Where(k => k.Value == type).Select(k => k.Key));
                            foreach (PExp exp in exps)
                            {
                                data.ExpTypes[exp] = newType;
                            }*/
                            formal.SetType(newType);
                            foreach (KeyValuePair<ALocalLvalue, AALocalDecl> pair in data.LocalLinks)
                            {
                                if (pair.Value == formal)
                                {//Replace with *lvalue
                                    ALvalueExp innerExp = new ALvalueExp();
                                    APointerLvalue replacement = new APointerLvalue(new TStar("*"), innerExp);
                                    pair.Key.ReplaceBy(replacement);
                                    innerExp.SetLvalue(pair.Key);
                                    data.ExpTypes[innerExp] = data.LvalueTypes[pair.Key] = formal.GetType();
                                    data.LvalueTypes[replacement] = ((APointerType)newType).GetType();

                                    //if (replacement.Parent() is ALvalueExp)
                                    //    data.ExpTypes[(PExp)replacement.Parent()] = data.LvalueTypes[replacement];
                                }
                            }
                        }
                        else
                        {//Make pointer
                            formal.SetType(new APointerType(new TStar("*"), type));
                            foreach (KeyValuePair<ALocalLvalue, AALocalDecl> pair in data.LocalLinks)
                            {
                                if (pair.Value == formal)
                                {//Replace with *lvalue
                                    ALvalueExp innerExp = new ALvalueExp();
                                    APointerLvalue replacement = new APointerLvalue(new TStar("*"), innerExp);
                                    pair.Key.ReplaceBy(replacement);
                                    innerExp.SetLvalue(pair.Key);
                                    data.ExpTypes[innerExp] = data.LvalueTypes[pair.Key] = formal.GetType();
                                    data.LvalueTypes[replacement] = type;
                                }
                            }
                        }
                    }
                }
                if (Util.IsBulkCopy(node.GetReturnType()))
                {
                    PType oldType = node.GetReturnType();
                    PType newType;
                    if (node.GetReturnType() is AArrayTempType)
                    {//make dynamic array
                        AArrayTempType aType = (AArrayTempType) node.GetReturnType();
                        newType = new APointerType(new TStar("*"),
                                                   new ADynamicArrayType((TLBracket) aType.GetToken().Clone(),
                                                                         Util.MakeClone(aType.GetType(), data)));
                        node.SetReturnType(newType);
                    }
                    else
                    {//Make pointer
                        newType = new APointerType(new TStar("*"), node.GetReturnType());
                        node.SetReturnType(newType);
                    }
                    /*List<PExp> exps = new List<PExp>();
                    exps.AddRange(data.ExpTypes.Where(k => k.Value == oldType).Select(k => k.Key));
                    foreach (PExp exp in exps)
                    {
                        data.ExpTypes[exp] = newType;
                    }
                    List<PLvalue> lvalues = new List<PLvalue>();
                    lvalues.AddRange(data.LvalueTypes.Where(k => k.Value == oldType).Select(k => k.Key));
                    foreach (PLvalue lvalue in lvalues)
                    {
                        data.LvalueTypes[lvalue] = newType;
                    }*/
                }
                 	            base.CaseAMethodDecl(node);
            }
 public virtual void InAPointerLvalue(APointerLvalue node)
 {
     DefaultIn(node);
 }
        public static PLvalue Link(AAName name, Node refNode, List<Node> list, SharedData data)
        {
            List<TIdentifier> identifierList = new List<TIdentifier>();
            {
                int count = name.GetIdentifier().Count;
                if (count < list.Count)
                {
                    for (int i = 0; i < list.Count - count; i++)
                    {
                        if (list[i] is AStructDecl)
                            identifierList.Add(((AStructDecl)list[i]).GetName());
                    }

                    for (int i = 0; i < count; i++)
                    {
                        TIdentifier iden = (TIdentifier)name.GetIdentifier()[i];
                        identifierList.Add(iden);
                    }
                }
                else
                    for (int i = count - list.Count; i < count; i++)
                    {
                        TIdentifier iden = (TIdentifier)name.GetIdentifier()[i];
                        identifierList.Add(iden);
                    }
            }
            PLvalue baseLvalue = null;
            Node node = list[0];
            list.RemoveAt(0);
            TIdentifier identifier = identifierList[0];
            identifierList.RemoveAt(0);
            if (node is AALocalDecl)
            {
                AALocalDecl aNode = (AALocalDecl)node;
                if (node.Parent() is AStructDecl)
                {//Struct local
                    //Make it this->var or this.var
                    AStructDecl pStruct = Util.GetAncestor<AStructDecl>(node);
                    if (pStruct.GetClassToken() != null || Util.HasAncestor<AConstructorDecl>(refNode) || Util.HasAncestor<ADeconstructorDecl>(refNode))
                    {//(*this).
                        baseLvalue = new AThisLvalue(new TThis("this"));
                        baseLvalue = new APointerLvalue(new TStar("*"), new ALvalueExp(baseLvalue));
                        baseLvalue = new AStructLvalue(new ALvalueExp(baseLvalue), new ADotDotType(new TDot(".")),
                                                       identifier);
                        data.StructFieldLinks[(AStructLvalue)baseLvalue] = aNode;
                    }
                    else
                    {//struct.
                        baseLvalue = new AStructFieldLvalue(identifier);
                        data.StructMethodFieldLinks[(AStructFieldLvalue)baseLvalue] = aNode;
                    }
                }
                else
                {//Method/constructor/deconstructor local
                    ALocalLvalue replaceNode = new ALocalLvalue(identifier);
                    data.LocalLinks[replaceNode] = aNode;
                    baseLvalue = replaceNode;
                }
            }
            else if (node is APropertyDecl)
            {
                APropertyDecl aNode = (APropertyDecl)node;
                if (Util.HasAncestor<AStructDecl>(node))
                {//Property in current struct
                    AStructDecl pStruct = Util.GetAncestor<AStructDecl>(node);
                    if (pStruct.GetClassToken() != null || Util.HasAncestor<AConstructorDecl>(refNode) || Util.HasAncestor<ADeconstructorDecl>(refNode))
                    {//(*this).
                        baseLvalue = new AThisLvalue(new TThis("this"));
                        baseLvalue = new APointerLvalue(new TStar("*"), new ALvalueExp(baseLvalue));
                        baseLvalue = new AStructLvalue(new ALvalueExp(baseLvalue), new ADotDotType(new TDot(".")),
                                                       identifier);
                        data.StructPropertyLinks[(AStructLvalue)baseLvalue] = aNode;
                    }
                    else
                    {//struct.
                        baseLvalue = new AStructFieldLvalue(identifier);
                        data.StructMethodPropertyLinks[(AStructFieldLvalue)baseLvalue] = aNode;
                    }
                }
                else
                {//Global property
                    baseLvalue = new APropertyLvalue(identifier);
                    data.PropertyLinks[(APropertyLvalue)baseLvalue] = aNode;
                }
            }
            else if (node is AFieldDecl)
            {
                baseLvalue = new AFieldLvalue(identifier);
                data.FieldLinks[(AFieldLvalue)baseLvalue] = (AFieldDecl)node;
            }
            else if (node is AStructDecl)
            {
                AStructDecl targetStruct = (AStructDecl)node;
                node = list[0];
                list.RemoveAt(0);
                identifier = identifierList[0];
                identifierList.RemoveAt(0);

                AStructFieldLvalue lvalue = new AStructFieldLvalue(identifier);
                if (node is AALocalDecl)
                    data.StructMethodFieldLinks[lvalue] = (AALocalDecl)node;
                else
                    data.StructMethodPropertyLinks[lvalue] = (APropertyDecl)node;

                baseLvalue = lvalue;
            }
            while (list.Count > 0)
            {
                node = list[0];
                list.RemoveAt(0);
                identifier = identifierList[0];
                identifierList.RemoveAt(0);

                baseLvalue = new AStructLvalue(new ALvalueExp(baseLvalue), new ADotDotType(new TDot(".")),
                                                identifier);
                if (node is AALocalDecl)
                {//Struct local
                    data.StructFieldLinks[(AStructLvalue) baseLvalue] = (AALocalDecl) node;
                }
                else if (node is APropertyDecl)
                {//Struct property
                    data.StructPropertyLinks[(AStructLvalue) baseLvalue] = (APropertyDecl) node;
                }
                //Don't link array length stuff
            }
            return baseLvalue;
        }
 public virtual void OutAPointerLvalue(APointerLvalue node)
 {
     DefaultOut(node);
 }
 public override void OutAPointerLvalue(APointerLvalue node)
 {
     data.LvalueTypes[node] = ((APointerType) data.ExpTypes[node.GetBase()]).GetType();
 }