public override void CaseAArrayLvalue(AArrayLvalue node)
 {
     InAArrayLvalue(node);
     if (node.GetIndex() != null)
     {
         node.GetIndex().Apply(this);
     }
     if (node.GetBase() != null)
     {
         node.GetBase().Apply(this);
     }
     if (node.GetToken() != null)
     {
         node.GetToken().Apply(this);
     }
     OutAArrayLvalue(node);
 }
        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."));
        }