public void Visit(PostfixExpression_Index x) { HandleIndexSliceExpression(x); if (x.Arguments != null) { res.CurrentlyTypedArgumentIndex = x.Arguments.Length; } }
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); }
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; }
public ArrayAccessSymbol(PostfixExpression_Index indexExpr, AbstractType arrayValueType) : base(arrayValueType, indexExpr) { }
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; }
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; } }
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; }
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; }
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; }