public void Visit(PostfixExpression_Index x)
 {
     HandleIndexSliceExpression(x);
     if (x.Arguments != null)
     {
         res.CurrentlyTypedArgumentIndex = x.Arguments.Length;
     }
 }
Beispiel #2
0
 public ArrayAccessSymbol(PostfixExpression_Index indexExpr, AbstractType arrayValueType)
     : base(arrayValueType,indexExpr)
 {
 }
        public AbstractType Visit(PostfixExpression_Index x)
        {
            var foreExpression = EvalForeExpression(x);

            // myArray[0]; myArray[0..5];
            // opIndex/opSlice ?
            if (foreExpression is MemberSymbol)
            {
                foreExpression = DResolver.StripMemberSymbols(foreExpression);
            }

            var udt = foreExpression as UserDefinedType;

            if (udt != null)
            {
                ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

                var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(OpIndexIdHash, AmbiguousType.TryDissolve(foreExpression), ctxt, x, false);
                if (overloads != null && overloads.Length > 0)
                {
                    var indexArgs = x.Arguments != null ? new AbstractType[x.Arguments.Length] : null;
                    for (int i = 0; i < indexArgs.Length; i++)
                    {
                        if (x.Arguments[i] != null)
                        {
                            indexArgs[i] = x.Arguments[i].Accept(this);
                        }
                    }

                    overloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(overloads, indexArgs, true, ctxt);
                    ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
                    return(TryPretendMethodExecution(AmbiguousType.Get(overloads, x), x, indexArgs));
                }
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);

                if (foreExpression is TemplateIntermediateType)
                {                //TODO: Proper resolution of alias this declarations
                    var tit = foreExpression as TemplateIntermediateType;
                    var ch  = tit.Definition[DVariable.AliasThisIdentifierHash];
                    if (ch != null)
                    {
                        foreach (DVariable aliasThis in ch)
                        {
                            foreExpression = TypeDeclarationResolver.HandleNodeMatch(aliasThis, ctxt, foreExpression);
                            if (foreExpression != null)
                            {
                                break;                                 // HACK: Just omit other alias this' to have a quick run-through
                            }
                        }
                    }

                    if (foreExpression == null)
                    {
                        return(tit);
                    }
                }
            }

            foreExpression = DResolver.StripMemberSymbols(foreExpression);

            if (foreExpression is AssocArrayType)
            {
                var ar = foreExpression as AssocArrayType;

                /*
                 * myType_Array[0] -- returns TypeResult myType
                 * return the value type of a given array result
                 */
                //TODO: Handle opIndex overloads
                if (ar.ValueType != null)
                {
                    ar.ValueType.NonStaticAccess = true;
                }

                return(new ArrayAccessSymbol(x, ar.ValueType));
            }

            /*
             * int* a = new int[10];
             *
             * a[0] = 12;
             */
            else if (foreExpression is PointerType)
            {
                var b = (foreExpression as PointerType).Base;
                if (b != null)
                {
                    b.NonStaticAccess = true;
                }
                return(b);
            }
            //return new ArrayAccessSymbol(x,((PointerType)foreExpression).Base);

            else if (foreExpression is DTuple)
            {
                var tt = foreExpression as DTuple;

                if (x.Arguments != null && x.Arguments.Length != 0)
                {
                    var idx = Evaluation.EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                    if (tt.Items == null)
                    {
                        ctxt.LogError(tt.DeclarationOrExpressionBase, "No items in Type tuple");
                    }
                    else if (idx == null || !DTokens.IsBasicType_Integral(idx.BaseTypeToken))
                    {
                        ctxt.LogError(x.Arguments[0], "Index expression must evaluate to integer value");
                    }
                    else if (idx.Value > (decimal)Int32.MaxValue ||
                             (int)idx.Value >= tt.Items.Length || idx.Value < 0m)
                    {
                        ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                    }
                    else
                    {
                        return(AbstractType.Get(tt.Items[(int)idx.Value]));
                    }
                }
            }

            ctxt.LogError(x, "No matching base type for indexing operation");
            return(null);
        }
        public ISymbolValue Visit(PostfixExpression_Index x)
        {
            var foreExpression = EvalForeExpression(x);

            //TODO: Access pointer arrays(?)

            if (foreExpression is ArrayValue)             // ArrayValue must be checked first due to inheritance!
            {
                var av = foreExpression as ArrayValue;

                // Make $ operand available
                var arrLen_Backup = ValueProvider.CurrentArrayLength;
                ValueProvider.CurrentArrayLength = av.Elements.Length;

                var n = x.Arguments.Length > 0 && x.Arguments[0] != null ? x.Arguments[0].Accept(this) as PrimitiveValue : null;

                ValueProvider.CurrentArrayLength = arrLen_Backup;

                if (n == null)
                {
                    EvalError(x.Arguments[0], "Returned no value");
                    return(null);
                }

                int i = 0;
                try
                {
                    i = Convert.ToInt32(n.Value);
                }
                catch
                {
                    EvalError(x.Arguments[0], "Index expression must be of type int");
                    return(null);
                }

                if (i < 0 || i > av.Elements.Length)
                {
                    EvalError(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                    return(null);
                }

                return(av.Elements[i]);
            }
            else if (foreExpression is AssociativeArrayValue)
            {
                var aa = (AssociativeArrayValue)foreExpression;

                var key = x.Arguments.Length > 0 && x.Arguments[0] != null ? x.Arguments[0].Accept(this) as PrimitiveValue : null;

                if (key == null)
                {
                    EvalError(x.Arguments[0], "Returned no value");
                    return(null);
                }

                ISymbolValue val = null;

                foreach (var kv in aa.Elements)
                {
                    if (kv.Key.Equals(key))
                    {
                        return(kv.Value);
                    }
                }

                EvalError(x, "Could not find key '" + val + "'");
                return(null);
            }

            //TODO: myClassWithAliasThis[0] -- Valid!!

            EvalError(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);
            return(null);
        }
Beispiel #5
0
        IExpression PostfixExpression(IBlockNode Scope = null)
        {
            IExpression leftExpr = null;

            /*
             * Despite the following syntax is an explicit UnaryExpression (see http://dlang.org/expression.html#UnaryExpression),
             * stuff like (MyType).init[] is actually allowed - so it's obviously a PostfixExpression! (Nov 13 2013)
             */

            // ( Type ) . Identifier
            if (laKind == OpenParenthesis)
            {
                Lexer.StartPeek();
                OverPeekBrackets(OpenParenthesis, false);
                var dotToken = Lexer.CurrentPeekToken;

                if (Lexer.CurrentPeekToken.Kind == DTokens.Dot &&
                    (Peek().Kind == DTokens.Identifier || Lexer.CurrentPeekToken.Kind == EOF))
                {
                    var wkParsing = AllowWeakTypeParsing;
                    AllowWeakTypeParsing = true;
                    Lexer.PushLookAheadBackup();
                    Step();
                    var startLoc = t.Location;

                    var td = Type();

                    AllowWeakTypeParsing = wkParsing;

                    /*
                     * (a. -- expression: (a.myProp + 2) / b;
                     * (int. -- must be expression anyway
                     * (const).asdf -- definitely unary expression ("type")
                     * (const). -- also treat it as type accessor
                     */
                    if (td != null &&
                        laKind == CloseParenthesis && Lexer.CurrentPeekToken == dotToken) // Also take it as a type declaration if there's nothing following (see Expression Resolving)
                    {
                        Step();  // Skip to )
                        if (laKind == DTokens.Dot)
                        {
                            Step();  // Skip to .
                            if ((laKind == DTokens.Identifier && Peek(1).Kind != Not && Peek(1).Kind != OpenParenthesis) || IsEOF)
                            {
                                Lexer.PopLookAheadBackup();
                                Step();  // Skip to identifier

                                leftExpr = new UnaryExpression_Type()
                                {
                                    Type = td,
                                    AccessIdentifier = t.Value,
                                    Location = startLoc,
                                    EndLocation = t.EndLocation
                                };
                            }
                            else
                                Lexer.RestoreLookAheadBackup();
                        }
                        else
                            Lexer.RestoreLookAheadBackup();
                    }
                    else
                        Lexer.RestoreLookAheadBackup();
                }
            }

            // PostfixExpression
            if(leftExpr == null)
                leftExpr = PrimaryExpression(Scope);

            while (!IsEOF)
            {
                switch (laKind)
                {
                    case Dot:
                        Step();

                        var pea = new PostfixExpression_Access {
                            PostfixForeExpression = leftExpr
                        };

                        leftExpr = pea;

                        if (laKind == New)
                            pea.AccessExpression = PostfixExpression(Scope);
                        else if (IsTemplateInstance)
                            pea.AccessExpression = TemplateInstance(Scope);
                        else if (Expect(Identifier))
                            pea.AccessExpression = new IdentifierExpression(t.Value) {
                                Location = t.Location,
                                EndLocation = t.EndLocation
                            };
                        else if (IsEOF)
                            pea.AccessExpression = new TokenExpression(DTokens.Incomplete);

                        pea.EndLocation = t.EndLocation;
                        break;
                    case Increment:
                    case Decrement:
                        Step();
                        var peid = t.Kind == Increment ? (PostfixExpression)new PostfixExpression_Increment() : new PostfixExpression_Decrement();
                        peid.EndLocation = t.EndLocation;
                        peid.PostfixForeExpression = leftExpr;
                        leftExpr = peid;
                        break;
                    // Function call
                    case OpenParenthesis:
                        Step();
                        var pemc = new PostfixExpression_MethodCall();
                        pemc.PostfixForeExpression = leftExpr;
                        leftExpr = pemc;

                        if (laKind == CloseParenthesis)
                            Step();
                        else
                        {
                            pemc.Arguments = ArgumentList(Scope).ToArray();
                            Expect(CloseParenthesis);
                        }

                        if(IsEOF)
                            pemc.EndLocation = CodeLocation.Empty;
                        else
                            pemc.EndLocation = t.EndLocation;
                        break;
                    // IndexExpression | SliceExpression
                    case OpenSquareBracket:
                        Step();

                        if (laKind != CloseSquareBracket)
                        {
                            var firstEx = AssignExpression(Scope);
                            // [ AssignExpression .. AssignExpression ]
                            if (laKind == DoubleDot)
                            {
                                Step();

                                leftExpr = new PostfixExpression_Slice()
                                {
                                    FromExpression = firstEx,
                                    PostfixForeExpression = leftExpr,
                                    ToExpression = AssignExpression(Scope)
                                };
                            }
                            // [ ArgumentList ]
                            else if (laKind == CloseSquareBracket || laKind == (Comma))
                            {
                                var args = new List<IExpression>();
                                args.Add(firstEx);
                                if (laKind == Comma)
                                {
                                    Step();
                                    args.AddRange(ArgumentList(Scope));
                                }

                                leftExpr = new PostfixExpression_Index()
                                {
                                    PostfixForeExpression = leftExpr,
                                    Arguments = args.ToArray()
                                };
                            }
                        }
                        else // Empty array literal = SliceExpression
                        {
                            leftExpr = new PostfixExpression_Slice()
                            {
                                PostfixForeExpression=leftExpr
                            };
                        }

                        Expect(CloseSquareBracket);
                        if(leftExpr is PostfixExpression)
                            ((PostfixExpression)leftExpr).EndLocation = t.EndLocation;
                        break;
                    default:
                        return leftExpr;
                }
            }

            return leftExpr;
        }
Beispiel #6
0
 public ArrayAccessSymbol(PostfixExpression_Index indexExpr, AbstractType arrayValueType) :
     base(arrayValueType, indexExpr)
 {
 }
Beispiel #7
0
 IExpression ParseAsmBracketExpression(IBlockNode Scope, IStatement Parent)
 {
     var left = ParseAsmUnaryExpression(Scope, Parent);
     while (laKind == OpenSquareBracket)
     {
         Step();
         var e = new PostfixExpression_Index();
         e.PostfixForeExpression = left;
         e.Arguments = new IExpression[] { ParseAsmExpression(Scope, Parent) };
         Expect(CloseSquareBracket);
         left = e;
     }
     return left;
 }
Beispiel #8
0
        IExpression ParseAsmPrimaryExpression(IBlockNode Scope, IStatement Parent)
        {
            switch (laKind)
            {
                case OpenSquareBracket:
                    Step();
                    var e = new PostfixExpression_Index() { EndLocation = t.EndLocation };
                    e.Arguments = new IExpression[] { ParseAsmExpression(Scope, Parent) };
                    Expect(CloseSquareBracket);
                    return e;
                case Dollar:
                    var ins = Parent as AsmStatement.InstructionStatement;
                    if (ins == null || (!ins.IsJmpFamily && ins.Operation != AsmStatement.InstructionStatement.OpCode.call))
                        SynErr(Dollar, "The $ operator is only valid on jmp and call instructions!");
                    Step();
                    return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation };
                case Literal:
                    Step();
                    return new IdentifierExpression(t.LiteralValue, t.LiteralFormat, t.Subformat) { Location = t.Location, EndLocation = t.EndLocation };

                // AsmTypePrefix
                case DTokens.Byte:
                case DTokens.Short:
                case DTokens.Int:
                case DTokens.Float:
                case DTokens.Double:
                case DTokens.Real:

                case __LOCAL_SIZE:
                    Step ();
                    return new TokenExpression(t.Kind)  { Location = t.Location, EndLocation = t.EndLocation };
                case Identifier:
                    Step();
                    if (AsmRegisterExpression.IsRegister(t.Value))
                    {
                        string reg = t.Value;
                        if (reg == "ST" && laKind == OpenParenthesis)
                        {
                            reg += "(";
                            Step();
                            Expect(Literal);
                            reg += t.LiteralValue.ToString();
                            if (laKind != CloseParenthesis)
                                SynErr(CloseParenthesis);
                            else
                                Step();
                            reg += ")";
                        }
                        switch (reg)
                        {
                            case "ES":
                            case "CS":
                            case "SS":
                            case "DS":
                            case "GS":
                            case "FS":
                                if (laKind == Colon)
                                {
                                    var ex = new AsmRegisterExpression() { Location = t.Location, EndLocation = t.EndLocation, Register = string.Intern(reg) };
                                    Step();
                                    // NOTE: DMD actually allows you to not have an expression after a
                                    //       segment specifier, however I consider this a bug, and, as
                                    //       such, am making an expression in that form fail to parse.
                                    return new UnaryExpression_SegmentBase() { RegisterExpression = ex, UnaryExpression = ParseAsmExpression(Scope, Parent) };
                                }
                                break;
                        }
                        return new AsmRegisterExpression() { Location = t.Location, EndLocation = t.EndLocation, Register = string.Intern(reg) };
                    }
                    else
                    {
                        IExpression outer = new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation };
                        while (laKind == Dot)
                        {
                            Step();
                            if (laKind != Identifier)
                                SynErr(Identifier);
                            outer = new PostfixExpression_Access() { AccessExpression = new IdentifierExpression(la.Value), PostfixForeExpression = outer };
                            Step();
                        }
                        return outer;
                    }
                default:
                    SynErr(Identifier, "Expected a $, literal or an identifier!");
                    Step();
                    if (IsEOF)
                        return new TokenExpression(Incomplete);
                    return null;
            }
        }
Beispiel #9
0
 public override void Visit(PostfixExpression_Index x)
 {
     CallExpressionStack.Push(x);
     base.Visit(x);
     CallExpressionStack.Pop();
 }
        ISemantic E(PostfixExpression_Index x, ISemantic foreExpression)
        {
            if (eval)
            {
                //TODO: Access pointer arrays(?)

                if (foreExpression is ArrayValue) // ArrayValue must be checked first due to inheritance!
                {
                    var av = foreExpression as ArrayValue;

                    // Make $ operand available
                    var arrLen_Backup = ValueProvider.CurrentArrayLength;
                    ValueProvider.CurrentArrayLength = av.Elements.Length;

                    var n = E(x.Arguments[0]) as PrimitiveValue;

                    ValueProvider.CurrentArrayLength = arrLen_Backup;

                    if (n == null){
                        EvalError(x.Arguments[0], "Returned no value");
                        return null;
                    }

                    int i = 0;
                    try{
                        i = Convert.ToInt32(n.Value);
                    }
                    catch
                    {
                        EvalError(x.Arguments[0], "Index expression must be of type int");
                        return null;
                    }

                    if (i < 0 || i > av.Elements.Length){
                        EvalError(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                        return null;
                    }

                    return av.Elements[i];
                }
                else if (foreExpression is AssociativeArrayValue)
                {
                    var aa = (AssociativeArrayValue)foreExpression;

                    var key = E(x.Arguments[0]);

                    if (key == null){
                        EvalError(x.Arguments[0], "Returned no value");
                        return null;
                    }

                    ISymbolValue val = null;

                    foreach (var kv in aa.Elements)
                        if (kv.Key.Equals(key))
                            return kv.Value;

                    EvalError(x, "Could not find key '" + val + "'");
                    return null;
                }

                EvalError(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);
                return null;
            }
            else
            {
                foreExpression = DResolver.StripMemberSymbols(AbstractType.Get(foreExpression));

                if (foreExpression is AssocArrayType) {
                    var ar = foreExpression as AssocArrayType;
                    /*
                     * myType_Array[0] -- returns TypeResult myType
                     * return the value type of a given array result
                     */
                    //TODO: Handle opIndex overloads

                    return new ArrayAccessSymbol(x,ar.ValueType);
                }
                /*
                 * int* a = new int[10];
                 *
                 * a[0] = 12;
                 */
                else if (foreExpression is PointerType)
                    return (foreExpression as PointerType).Base;
                    //return new ArrayAccessSymbol(x,((PointerType)foreExpression).Base);

                else if (foreExpression is DTuple)
                {
                    var tt = foreExpression as DTuple;

                    if (x.Arguments != null && x.Arguments.Length != 0)
                    {
                        var idx = EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                        if (idx == null || !DTokens.BasicTypes_Integral[idx.BaseTypeToken])
                        {
                            ctxt.LogError(x.Arguments[0], "Index expression must evaluate to integer value");
                        }
                        else if (idx.Value > (decimal)Int32.MaxValue ||
                                 (int)idx.Value >= tt.Items.Length ||
                                 (int)idx.Value < 0)
                        {
                            ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                        }
                        else
                        {
                            return tt.Items[(int)idx.Value];
                        }
                    }
                }

                ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            }

            return null;
        }
Beispiel #11
0
        IExpression PostfixExpression(IBlockNode Scope = null)
        {
            var curLastParsedObj = LastParsedObject;

            // PostfixExpression
            IExpression leftExpr = PrimaryExpression(Scope);

            if(curLastParsedObj==LastParsedObject)
                LastParsedObject = leftExpr;

            while (!IsEOF)
            {
                if (laKind == Dot)
                {
                    Step();

                    var e = new PostfixExpression_Access {
                        PostfixForeExpression=leftExpr
                    };
                    LastParsedObject = e;

                    leftExpr = e;

                    if (laKind == New)
                        e.AccessExpression = NewExpression(Scope);
                    else if (IsTemplateInstance)
                        e.AccessExpression = TemplateInstance();
                    else if (Expect(Identifier))
                        e.AccessExpression = new IdentifierExpression(t.Value) { Location=t.Location, EndLocation=t.EndLocation };

                    e.EndLocation = t.EndLocation;
                }
                else if (laKind == Increment || laKind == Decrement)
                {
                    Step();
                    var e = t.Kind == Increment ? (PostfixExpression)new PostfixExpression_Increment() : new PostfixExpression_Decrement();
                    LastParsedObject = e;
                    e.EndLocation = t.EndLocation;
                    e.PostfixForeExpression = leftExpr;
                    leftExpr = e;
                }

                // Function call
                else if (laKind == OpenParenthesis)
                {
                    Step();
                    var ae = new PostfixExpression_MethodCall();
                    LastParsedObject = ae;
                    ae.PostfixForeExpression = leftExpr;
                    leftExpr = ae;

                    if (laKind != CloseParenthesis)
                        ae.Arguments = ArgumentList(Scope).ToArray();
                    Step();
                    ae.EndLocation = t.EndLocation;
                }

                // IndexExpression | SliceExpression
                else if (laKind == OpenSquareBracket)
                {
                    Step();

                    if (laKind != CloseSquareBracket)
                    {
                        var firstEx = AssignExpression(Scope);
                        // [ AssignExpression .. AssignExpression ]
                        if (laKind == DoubleDot)
                        {
                            Step();

                            leftExpr = new PostfixExpression_Slice()
                            {
                                FromExpression = firstEx,
                                PostfixForeExpression = leftExpr,
                                ToExpression = AssignExpression(Scope)
                            };
                            LastParsedObject = leftExpr;
                        }
                        // [ ArgumentList ]
                        else if (laKind == CloseSquareBracket || laKind == (Comma))
                        {
                            var args = new List<IExpression>();
                            args.Add(firstEx);
                            if (laKind == Comma)
                            {
                                Step();
                                args.AddRange(ArgumentList(Scope));
                            }

                            leftExpr = new PostfixExpression_Index()
                            {
                                PostfixForeExpression = leftExpr,
                                Arguments = args.ToArray()
                            };
                            LastParsedObject = leftExpr;
                        }
                    }
                    else // Empty array literal = SliceExpression
                    {
                        leftExpr = new PostfixExpression_Slice()
                        {
                            PostfixForeExpression=leftExpr
                        };
                        LastParsedObject = leftExpr;
                    }

                    Expect(CloseSquareBracket);
                    if(leftExpr is PostfixExpression)
                        ((PostfixExpression)leftExpr).EndLocation = t.EndLocation;
                }
                else break;
            }

            return leftExpr;
        }
Beispiel #12
0
        public AbstractType Visit(PostfixExpression_Index x)
        {
            var foreExpression = EvalForeExpression(x);

            // myArray[0]; myArray[0..5];
            // opIndex/opSlice ?
            if (foreExpression is MemberSymbol)
            {
                foreExpression = DResolver.StripMemberSymbols(foreExpression);
            }

            foreExpression = DResolver.StripMemberSymbols(foreExpression);

            if (foreExpression is AssocArrayType)
            {
                var ar = foreExpression as AssocArrayType;

                /*
                 * myType_Array[0] -- returns TypeResult myType
                 * return the value type of a given array result
                 */
                //TODO: Handle opIndex overloads

                return(new ArrayAccessSymbol(x, ar.ValueType));
            }

            /*
             * int* a = new int[10];
             *
             * a[0] = 12;
             */
            else if (foreExpression is PointerType)
            {
                return((foreExpression as PointerType).Base);
            }
            //return new ArrayAccessSymbol(x,((PointerType)foreExpression).Base);

            else if (foreExpression is DTuple)
            {
                var tt = foreExpression as DTuple;

                if (x.Arguments != null && x.Arguments.Length != 0)
                {
                    var idx = Evaluation.EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                    if (tt.Items == null)
                    {
                        ctxt.LogError(tt.DeclarationOrExpressionBase, "No items in Type tuple");
                    }
                    else if (idx == null || !DTokens.IsBasicType_Integral(idx.BaseTypeToken))
                    {
                        ctxt.LogError(x.Arguments[0], "Index expression must evaluate to integer value");
                    }
                    else if (idx.Value > (decimal)Int32.MaxValue ||
                             (int)idx.Value >= tt.Items.Length || idx.Value < 0m)
                    {
                        ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                    }
                    else
                    {
                        return(AbstractType.Get(tt.Items[(int)idx.Value]));
                    }
                }
            }

            ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            return(null);
        }
        ISemantic E(PostfixExpression_Index x, ISemantic foreExpression)
        {
            if (eval)
            {
                //TODO: Access pointer arrays(?)

                if (foreExpression is ArrayValue) // ArrayValue must be checked first due to inheritance!
                {
                    var av = foreExpression as ArrayValue;

                    // Make $ operand available
                    var arrLen_Backup = ValueProvider.CurrentArrayLength;
                    ValueProvider.CurrentArrayLength = av.Elements.Length;

                    var n = E(x.Arguments[0]) as PrimitiveValue;

                    ValueProvider.CurrentArrayLength = arrLen_Backup;

                    if (n == null)
                        throw new EvaluationException(x.Arguments[0], "Returned no value");

                    int i = 0;
                    try
                    {
                        i = Convert.ToInt32(n.Value);
                    }
                    catch { throw new EvaluationException(x.Arguments[0], "Index expression must be of type int"); }

                    if (i < 0 || i > av.Elements.Length)
                        throw new EvaluationException(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);

                    return av.Elements[i];
                }
                else if (foreExpression is AssociativeArrayValue)
                {
                    var aa = (AssociativeArrayValue)foreExpression;

                    var key = E(x.Arguments[0]);

                    if (key == null)
                        throw new EvaluationException(x.Arguments[0], "Returned no value");

                    ISymbolValue val = null;

                    foreach (var kv in aa.Elements)
                        if (kv.Key.Equals(key))
                            return kv.Value;

                    throw new EvaluationException(x, "Could not find key '" + val + "'");
                }

                throw new EvaluationException(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);
            }
            else
            {
                if (foreExpression is AssocArrayType)
                {
                    var ar = (AssocArrayType)foreExpression;
                    /*
                     * myType_Array[0] -- returns TypeResult myType
                     * return the value type of a given array result
                     */
                    //TODO: Handle opIndex overloads

                    return ar.ValueType;
                }
                /*
                 * int* a = new int[10];
                 *
                 * a[0] = 12;
                 */
                else if (foreExpression is PointerType)
                    return ((PointerType)foreExpression).Base;

                ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            }

            return null;
        }