public static IExpression TryConvertTypeDeclaration(ITypeDeclaration td, bool ignoreInnerDeclaration = false) { if (td.InnerDeclaration == null || ignoreInnerDeclaration) { if (td is IdentifierDeclaration) { var id = td as IdentifierDeclaration; if (id.Id == null) return null; return new IdentifierExpression(id.Id) { Location = id.Location, EndLocation = id.EndLocation }; } if (td is TemplateInstanceExpression) return td as IExpression; return null; } var pfa = new PostfixExpression_Access{ PostfixForeExpression = TryConvertTypeDeclaration(td.InnerDeclaration), AccessExpression = TryConvertTypeDeclaration(td, true) }; if (pfa.PostfixForeExpression == null) return null; return pfa; }
List <IExpression> DoPrimaryIdCheck(PostfixExpression_Access acc) { var r = new List <IExpression>(); while (acc != null) { if (DoPrimaryIdCheck(ExtractId(acc))) { r.Add(acc); } // Scan down the access expression for other, deeper expressions if (acc.PostfixForeExpression is PostfixExpression_Access) { acc = (PostfixExpression_Access)acc.PostfixForeExpression; } else { if (DoPrimaryIdCheck(ExtractId(acc.PostfixForeExpression))) { r.Add(acc.PostfixForeExpression); } break; } } return(r); }
public static IExpression TryConvertTypeDeclaration(ITypeDeclaration td, bool ignoreInnerDeclaration = false) { if (td.InnerDeclaration == null || ignoreInnerDeclaration) { if (td is IdentifierDeclaration) { var id = td as IdentifierDeclaration; if (id.Id == null) { return(null); } return(new IdentifierExpression(id.Id) { Location = id.Location, EndLocation = id.EndLocation }); } if (td is TemplateInstanceExpression) { return(td as IExpression); } return(null); } var pfa = new PostfixExpression_Access { PostfixForeExpression = TryConvertTypeDeclaration(td.InnerDeclaration), AccessExpression = TryConvertTypeDeclaration(td, true) }; if (pfa.PostfixForeExpression == null) { return(null); } return(pfa); }
AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolutionContext ctxt) { AbstractType pfType = null; if (acc.PostfixForeExpression is PostfixExpression_Access) { pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt); } else { pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt)); if (acc.PostfixForeExpression is IdentifierExpression || acc.PostfixForeExpression is TemplateInstanceExpression || acc.PostfixForeExpression is PostfixExpression_Access) { HandleResult(acc.PostfixForeExpression, pfType); } } var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, pfType); ctxt.CheckForSingleResult(accessedMembers, acc); if (accessedMembers != null && accessedMembers.Length != 0) { HandleResult(acc, accessedMembers[0]); return(accessedMembers[0]); } return(null); }
public static List <AbstractType> TryResolveUFCS( ISemantic firstArgument, PostfixExpression_Access acc, ResolutionContext ctxt) { if (firstArgument == null || acc == null || ctxt == null) { return(new List <AbstractType>()); } int name; if (acc.AccessExpression is IdentifierExpression) { name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash; } else if (acc.AccessExpression is TemplateInstanceExpression) { name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash; } else { return(new List <AbstractType> ()); } return(TryResolveUFCS(firstArgument, name, acc.PostfixForeExpression.Location, ctxt, acc)); }
public ISymbolValue Visit(PostfixExpression_Access ex) { var r = EvalPostfixAccessExpression(this, ctxt, ex, null, true, ValueProvider: ValueProvider); ctxt.CheckForSingleResult(r, ex); return(r != null && r.Length != 0 ? r[0] : null); }
public AbstractType Visit(PostfixExpression_Access ex) { var r = Evaluation.EvalPostfixAccessExpression(this, ctxt, ex); ctxt.CheckForSingleResult(r, ex); return(r != null && r.Length != 0 ? r[0] : null); }
public static MemberSymbol[] TryResolveUFCS( ISemantic firstArgument, PostfixExpression_Access acc, ResolutionContext ctxt) { if (ctxt == null) return null; int name=0; if (acc.AccessExpression is IdentifierExpression) name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash; else if (acc.AccessExpression is TemplateInstanceExpression) name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash; else return null; var methodMatches = new List<MemberSymbol>(); if(ctxt.ParseCache!=null) foreach (var pc in ctxt.ParseCache) { var tempResults=pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name); if (tempResults != null) foreach (var m in tempResults) { ctxt.PushNewScope(m); if (m.TemplateParameters != null && m.TemplateParameters.Length != 0) { var ov = TemplateInstanceHandler.DeduceParamsAndFilterOverloads( new[] { new MemberSymbol(m, null, acc) }, new[] { firstArgument }, true, ctxt); if (ov == null || ov.Length == 0) continue; var ms = (DSymbol)ov[0]; ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms); } var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, null, acc) as MemberSymbol; if (mr!=null) { mr.FirstArgument = firstArgument; mr.DeducedTypes = ctxt.CurrentContext.DeducedTemplateParameters.ToReadonly(); mr.IsUFCSResult = true; methodMatches.Add(mr); } ctxt.Pop(); } } return methodMatches.Count == 0 ? null : methodMatches.ToArray(); }
public override void Visit(PostfixExpression_Access acc) { var resolvedSymbol = TryPopPFAStack(); if ((acc.AccessExpression is IdentifierExpression && (acc.AccessExpression as IdentifierExpression).ValueStringHash != searchHash) || (acc.AccessExpression is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { acc.PostfixForeExpression.Accept(this); return; } else if (acc.AccessExpression is NewExpression) { var nex = acc.AccessExpression as NewExpression; if ((nex.Type is IdentifierDeclaration && ((IdentifierDeclaration)nex.Type).IdHash != searchHash) || (nex.Type is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { acc.PostfixForeExpression.Accept(this); return; } // Are there other types to test for? } else { // Are there other types to test for? } var s = resolvedSymbol ?? Evaluation.EvaluateType(acc, ctxt) as DerivedDataType; if (s is DSymbol) { if (((DSymbol)s).Definition == symbol) { l.Add(acc.AccessExpression); } } else if (s == null || !(s.Base is DSymbol)) { acc.PostfixForeExpression.Accept(this); return; } // Scan down for other possible symbols if (s.Base is DSymbol) { postfixForeExprAccessStack.Push(s.Base as DSymbol); } acc.PostfixForeExpression.Accept(this); }
public override void Visit(PostfixExpression_Access x) { if (x.AccessExpression != null && x.AccessExpression.Location <= caret && x.AccessExpression.EndLocation >= caret) { IdNearCaret = x; } else { base.Visit(x); } }
public override void Visit(PostfixExpression_Access acc) { acc.PostfixForeExpression.Accept(this); if ((acc.AccessExpression is IdentifierExpression && (acc.AccessExpression as IdentifierExpression).ValueStringHash != searchHash) || (acc.AccessExpression is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { return; } else if (acc.AccessExpression is NewExpression) { var nex = acc.AccessExpression as NewExpression; if ((nex.Type is IdentifierDeclaration && ((IdentifierDeclaration)nex.Type).IdHash != searchHash) || (nex.Type is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { return; } // Are there other types to test for? } else { // Are there other types to test for? } ctxt.CurrentContext.Set(acc.Location); var ov = ExpressionTypeEvaluation.GetAccessedOverloads(acc, ctxt, null, false); if (ov == null) { return; } foreach (var o in ov) { if (TryAdd(o, acc.AccessExpression)) { return; } } }
public static List<AbstractType> TryResolveUFCS( ISemantic firstArgument, PostfixExpression_Access acc, ResolutionContext ctxt) { if (firstArgument == null || acc == null || ctxt == null) return new List<AbstractType>(); int name; if (acc.AccessExpression is IdentifierExpression) name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash; else if (acc.AccessExpression is TemplateInstanceExpression) name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash; else return new List<AbstractType> (); return TryResolveUFCS (firstArgument, name, acc.PostfixForeExpression.Location, ctxt, acc); }
public override void Visit(PostfixExpression_Access x) { if (IsIncompleteExpression(x.AccessExpression)) { halt = true; if (x.PostfixForeExpression is TokenExpression && (x.PostfixForeExpression as TokenExpression).Token == DTokens.Dot) { // Handle module-scoped things: // When typing a dot without anything following, trigger completion and show types, methods and vars that are located in the module & import scope prv = new CtrlSpaceCompletionProvider(cdgen, scopedBlock, MemberFilter.Methods | MemberFilter.Types | MemberFilter.Variables | MemberFilter.TypeParameters); } else { prv = new MemberCompletionProvider(cdgen, x.PostfixForeExpression, scopedBlock); } } else { base.Visit(x); } }
public static MemberSymbol[] TryResolveUFCS( ISemantic firstArgument, PostfixExpression_Access acc, ResolverContextStack ctxt) { if (ctxt == null) return null; var name=""; if (acc.AccessExpression is IdentifierExpression) name = ((IdentifierExpression)acc.AccessExpression).Value as string; else if (acc.AccessExpression is TemplateInstanceExpression) name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdentifier.Id; else return null; var methodMatches = new List<MemberSymbol>(); if(ctxt.ParseCache!=null) foreach (var pc in ctxt.ParseCache) { var tempResults=pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name); if (tempResults != null) foreach (var m in tempResults) { var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, TypeDeclarationResolver.Convert(firstArgument), acc) as MemberSymbol; if (mr!=null) { mr.IsUFCSResult = true; methodMatches.Add(mr); } } } return methodMatches.Count == 0 ? null : methodMatches.ToArray(); }
IExpression NonVoidInitializer(IBlockNode Scope = null) { TrackerVariables.IsParsingInitializer = true; #region ArrayInitializer if (laKind == OpenSquareBracket) { Step(); // ArrayMemberInitializations var ae = new ArrayInitializer() { Location=t.Location}; LastParsedObject = ae; var inits=new List<ArrayMemberInitializer>(); bool IsInit = true; while (IsInit || laKind == (Comma)) { if (!IsInit) Step(); IsInit = false; // Allow empty post-comma expression IF the following token finishes the initializer expression // int[] a=[1,2,3,4,]; if (laKind == CloseSquareBracket) break; // ArrayMemberInitialization var ami = new ArrayMemberInitializer() { Left = NonVoidInitializer(Scope) }; LastParsedObject = ami; bool HasBeenAssExpr = !(t.Kind == (CloseSquareBracket) || t.Kind == (CloseCurlyBrace)); // AssignExpression : NonVoidInitializer if (HasBeenAssExpr && laKind == (Colon)) { Step(); ami.Specialization = NonVoidInitializer(Scope); } inits.Add(ami); } ae.ArrayMemberInitializations = inits.ToArray(); Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; // auto i=[1,2,3].idup; // in this case, this entire thing is meant to be an AssignExpression but not a dedicated initializer.. if (laKind == Dot) { Step(); var ae2 = new PostfixExpression_Access(); LastParsedObject = ae2; ae2.PostfixForeExpression = ae; ae2.TemplateOrIdentifier = Type(); //TODO: Is it really a type!? ae2.EndLocation = t.EndLocation; if (!IsEOF) TrackerVariables.IsParsingInitializer = false; return ae2; } if (!IsEOF) TrackerVariables.IsParsingInitializer = false; return ae; } #endregion // StructInitializer if (laKind == OpenCurlyBrace) { // StructMemberInitializations var ae = new StructInitializer() { Location = la.Location }; LastParsedObject = ae; var inits = new List<StructMemberInitializer>(); bool IsInit = true; while (IsInit || laKind == (Comma)) { Step(); IsInit = false; // Allow empty post-comma expression IF the following token finishes the initializer expression // int[] a=[1,2,3,4,]; if (laKind == CloseCurlyBrace) break; // Identifier : NonVoidInitializer var sinit = new StructMemberInitializer(); LastParsedObject = sinit; if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); sinit.MemberName = t.Value; Step(); } sinit.Specialization = NonVoidInitializer(Scope); inits.Add(sinit); } ae.StructMemberInitializers = inits.ToArray(); Expect(CloseCurlyBrace); ae.EndLocation = t.EndLocation; if (!IsEOF) TrackerVariables.IsParsingInitializer = false; return ae; } else { var expr= AssignExpression(Scope); if (!IsEOF) TrackerVariables.IsParsingInitializer = false; return expr; } }
IExpression PrimaryExpression(IBlockNode Scope=null) { bool isModuleScoped = false; // For minimizing possible overhead, skip 'useless' tokens like an initial dot <<< TODO if (isModuleScoped= laKind == Dot) Step(); if (laKind == __FILE__ || laKind == __LINE__) { Step(); object id = null; if (t.Kind == __FILE__ && doc != null) id = doc.FileName; else if(t.Kind==__LINE__) id = t.line; return new IdentifierExpression(id) { Location=t.Location, EndLocation=t.EndLocation }; } // Dollar (== Array length expression) if (laKind == Dollar) { Step(); return new TokenExpression(laKind) { Location = t.Location, EndLocation = t.EndLocation }; } // TemplateInstance if (laKind == (Identifier) && Lexer.CurrentPeekToken.Kind == (Not) && (Peek().Kind != Is && Lexer.CurrentPeekToken.Kind != In) /* Very important: The 'template' could be a '!is'/'!in' expression - With two tokens each! */) return TemplateInstance(); // Identifier if (laKind == (Identifier)) { Step(); return new IdentifierExpression(t.Value) { Location = t.Location, EndLocation = t.EndLocation }; } // SpecialTokens (this,super,null,true,false,$) // $ has been handled before if (laKind == (This) || laKind == (Super) || laKind == (Null) || laKind == (True) || laKind == (False)) { Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; } #region Literal if (laKind == Literal) { Step(); var startLoc = t.Location; // Concatenate multiple string literals here if (t.LiteralFormat == LiteralFormat.StringLiteral || t.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { var a = t.LiteralValue as string; while (la.LiteralFormat == LiteralFormat.StringLiteral || la.LiteralFormat == LiteralFormat.VerbatimStringLiteral) { Step(); a += t.LiteralValue as string; } return new IdentifierExpression(a, t.LiteralFormat) { Location = startLoc, EndLocation = t.EndLocation }; } //else if (t.LiteralFormat == LiteralFormat.CharLiteral)return new IdentifierExpression(t.LiteralValue) { LiteralFormat=t.LiteralFormat,Location = startLoc, EndLocation = t.EndLocation }; return new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = startLoc, EndLocation = t.EndLocation }; } #endregion #region ArrayLiteral | AssocArrayLiteral if (laKind == (OpenSquareBracket)) { Step(); var startLoc = t.Location; // Empty array literal if (laKind == CloseSquareBracket) { Step(); return new ArrayLiteralExpression() {Location=startLoc, EndLocation = t.EndLocation }; } var firstExpression = AssignExpression(); // Associtative array if (laKind == Colon) { Step(); var ae = new AssocArrayExpression() { Location=startLoc}; LastParsedObject = ae; var firstValueExpression = AssignExpression(); ae.KeyValuePairs.Add(firstExpression, firstValueExpression); while (laKind == Comma) { Step(); var keyExpr = AssignExpression(); Expect(Colon); var valueExpr = AssignExpression(); ae.KeyValuePairs.Add(keyExpr, valueExpr); } Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; return ae; } else // Normal array literal { var ae = new ArrayLiteralExpression() { Location=startLoc}; LastParsedObject = ae; var expressions = new List<IExpression>(); expressions.Add(firstExpression); while (laKind == Comma) { Step(); if (laKind == CloseSquareBracket) // And again, empty expressions are allowed break; expressions.Add(AssignExpression()); } ae.Expressions = expressions; Expect(CloseSquareBracket); ae.EndLocation = t.EndLocation; return ae; } } #endregion #region FunctionLiteral if (laKind == Delegate || laKind == Function || laKind == OpenCurlyBrace || (laKind == OpenParenthesis && IsFunctionLiteral())) { var fl = new FunctionLiteral() { Location=la.Location}; LastParsedObject = fl; fl.AnonymousMethod.StartLocation = la.Location; if (laKind == Delegate || laKind == Function) { Step(); fl.LiteralToken = t.Kind; } // file.d:1248 /* listdir (".", delegate bool (DirEntry * de) { auto s = std.string.format("%s : c %s, w %s, a %s", de.name, toUTCString (de.creationTime), toUTCString (de.lastWriteTime), toUTCString (de.lastAccessTime)); return true; } ); */ if (laKind != OpenCurlyBrace) // foo( 1, {bar();} ); -> is a legal delegate { if (!MemberFunctionAttribute[laKind] && Lexer.CurrentPeekToken.Kind == OpenParenthesis) fl.AnonymousMethod.Type = BasicType(); else if (laKind != OpenParenthesis && laKind != OpenCurlyBrace) fl.AnonymousMethod.Type = Type(); if (laKind == OpenParenthesis) fl.AnonymousMethod.Parameters = Parameters(fl.AnonymousMethod); } FunctionBody(fl.AnonymousMethod); fl.EndLocation = t.EndLocation; if (Scope != null) Scope.Add(fl.AnonymousMethod); return fl; } #endregion #region AssertExpression if (laKind == (Assert)) { Step(); var startLoc = t.Location; Expect(OpenParenthesis); var ce = new AssertExpression() { Location=startLoc}; LastParsedObject = ce; var exprs = new List<IExpression>(); exprs.Add(AssignExpression()); if (laKind == (Comma)) { Step(); exprs.Add(AssignExpression()); } ce.AssignExpressions = exprs.ToArray(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion #region MixinExpression | ImportExpression if (laKind == Mixin) { Step(); var e = new MixinExpression() { Location=t.Location}; LastParsedObject = e; Expect(OpenParenthesis); e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); e.EndLocation = t.EndLocation; return e; } if (laKind == Import) { Step(); var e = new ImportExpression() { Location=t.Location}; LastParsedObject = e; Expect(OpenParenthesis); e.AssignExpression = AssignExpression(); Expect(CloseParenthesis); e.EndLocation = t.EndLocation; return e; } #endregion if (laKind == (Typeof)) { var startLoc = la.Location; return new TypeDeclarationExpression(TypeOf()) {Location=startLoc,EndLocation=t.EndLocation}; } // TypeidExpression if (laKind == (Typeid)) { Step(); var ce = new TypeidExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); AllowWeakTypeParsing = true; ce.Type = Type(); AllowWeakTypeParsing = false; if (ce.Type==null) ce.Expression = AssignExpression(); Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #region IsExpression if (laKind == Is) { Step(); var ce = new IsExpression() { Location=t.Location}; LastParsedObject = ce; Expect(OpenParenthesis); var LookAheadBackup = la; AllowWeakTypeParsing = true; ce.TestedType = Type(); AllowWeakTypeParsing = false; if (ce.TestedType!=null && laKind == Identifier && (Lexer.CurrentPeekToken.Kind == CloseParenthesis || Lexer.CurrentPeekToken.Kind == Equal || Lexer.CurrentPeekToken.Kind == Colon)) { Step(); ce.TypeAliasIdentifier = strVal; } else // D Language specs mistake: In an IsExpression there also can be expressions! if(ce.TestedType==null || !(laKind==CloseParenthesis || laKind==Equal||laKind==Colon)) { // Reset lookahead token to prior position la = LookAheadBackup; // Reset wrongly parsed type declaration ce.TestedType = null; ce.TestedExpression = ConditionalExpression(); } if(ce.TestedExpression==null && ce.TestedType==null) SynErr(laKind,"In an IsExpression, either a type or an expression is required!"); if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } if (laKind == Colon || laKind == Equal) { Step(); ce.EqualityTest = t.Kind == Equal; } else if (laKind == CloseParenthesis) { Step(); ce.EndLocation = t.EndLocation; return ce; } /* TypeSpecialization: Type struct union class interface enum function delegate super const immutable inout shared return */ if (ClassLike[laKind] || laKind==Typedef || // typedef is possible although it's not yet documented in the syntax docs laKind==Enum || laKind==Delegate || laKind==Function || laKind==Super || laKind==Return) { Step(); ce.TypeSpecializationToken = t.Kind; } else ce.TypeSpecialization = Type(); if (laKind == Comma) { Step(); ce.TemplateParameterList = TemplateParameterList(false); } Expect(CloseParenthesis); ce.EndLocation = t.EndLocation; return ce; } #endregion // ( Expression ) if (laKind == OpenParenthesis) { Step(); var ret = new SurroundingParenthesesExpression() {Location=t.Location }; LastParsedObject = ret; ret.Expression = Expression(); Expect(CloseParenthesis); ret.EndLocation = t.EndLocation; return ret; } // TraitsExpression if (laKind == (__traits)) return TraitsExpression(); #region BasicType . Identifier if (laKind == (Const) || laKind == (Immutable) || laKind == (Shared) || laKind == (InOut) || BasicTypes[laKind]) { Step(); var startLoc = t.Location; IExpression left = null; if (!BasicTypes[t.Kind]) { int tk = t.Kind; // Put an artificial parenthesis around the following type declaration if (laKind != OpenParenthesis) { var mttd = new MemberFunctionAttributeDecl(tk); LastParsedObject = mttd; mttd.InnerType = Type(); left = new TypeDeclarationExpression(mttd) { Location = startLoc, EndLocation = t.EndLocation }; } else { Expect(OpenParenthesis); var mttd = new MemberFunctionAttributeDecl(tk); LastParsedObject = mttd; mttd.InnerType = Type(); Expect(CloseParenthesis); left = new TypeDeclarationExpression(mttd) { Location = startLoc, EndLocation = t.EndLocation }; } } else left = new TokenExpression(t.Kind) {Location=startLoc,EndLocation=t.EndLocation }; if (laKind == (Dot) && Peek(1).Kind==Identifier) { Step(); Step(); var meaex = new PostfixExpression_Access() { PostfixForeExpression=left, TemplateOrIdentifier=new IdentifierDeclaration(t.Value),EndLocation=t.EndLocation }; return meaex; } return left; } #endregion // TODO? Expressions can of course be empty... //return null; SynErr(Identifier); Step(); return new TokenExpression(t.Kind) { Location = t.Location, EndLocation = t.EndLocation }; }
public void Visit(PostfixExpression_Access x) { }
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; }
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; } }
/// <summary> /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b). /// if <param name="EvalAndFilterOverloads"></param> is false. /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned /// which stores the return value of the property function b that is executed without arguments. /// Also handles UFCS - so if filtering is wanted, the function becom /// </summary> ISemantic[] E(PostfixExpression_Access acc, ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true) { if (acc == null) return null; var baseExpression = resultBase ?? E(acc.PostfixForeExpression); if (acc.AccessExpression is NewExpression) { /* * This can be both a normal new-Expression as well as an anonymous class declaration! */ //TODO! return null; } AbstractType[] overloads; var optBackup = ctxt.CurrentContext.ContextDependentOptions; if (acc.AccessExpression is TemplateInstanceExpression) { if (!ResolveImmediateBaseType) ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; var tix = (TemplateInstanceExpression)acc.AccessExpression; // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments! overloads = GetOverloads(tix, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads); if (!ResolveImmediateBaseType) ctxt.CurrentContext.ContextDependentOptions = optBackup; } else if (acc.AccessExpression is IdentifierExpression) { var id = acc.AccessExpression as IdentifierExpression; if (eval && EvalAndFilterOverloads && resultBase != null) { var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, resultBase, id.ValueStringHash); if (staticPropResult != null) return new[]{staticPropResult}; } if (!ResolveImmediateBaseType) ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; overloads = GetOverloads(id, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads); if (!ResolveImmediateBaseType) ctxt.CurrentContext.ContextDependentOptions = optBackup; } else { if (eval){ EvalError(acc, "Invalid access expression"); return null; } ctxt.LogError(acc, "Invalid post-dot expression"); return null; } /* * Try to get ufcs functions at first! * * void foo(int i) {} * * class A * { * void foo(int i, int a) {} * * void bar(){ * 123.foo(23); // Not allowed! * // Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels, * // it would return the local foo() only, not the global one..which would be an error then! * } * * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones? * } */ if(overloads == null || EvalAndFilterOverloads) { var oo = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[]; if(oo != null) { int overloadsLength = overloads == null ? 0 : overloads.Length; var newArr = new AbstractType[overloadsLength + oo.Length]; if(overloadsLength != 0) overloads.CopyTo(newArr,0); oo.CopyTo(newArr, overloadsLength); overloads = newArr; } } // If evaluation active and the access expression is stand-alone, return a single item only. if (EvalAndFilterOverloads && eval) return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) }; return overloads; }
public AbstractType Visit(PostfixExpression_Access ex) { return(TryPretendMethodExecution(AmbiguousType.Get(Evaluation.EvalPostfixAccessExpression(this, ctxt, ex)))); }
public static AbstractType[] GetAccessedOverloads(PostfixExpression_Access acc, ResolutionContext ctxt, ISemantic resultBase = null, bool DeducePostfixTemplateParams = true) { return(TypeDeclarationResolver.Convert(new Evaluation(ctxt).E(acc, resultBase, DeducePostfixTemplateParams))); }
AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolutionContext ctxt) { AbstractType pfType = null; if (acc.PostfixForeExpression is PostfixExpression_Access) pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt); else { pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt)); if (acc.PostfixForeExpression is IdentifierExpression || acc.PostfixForeExpression is TemplateInstanceExpression || acc.PostfixForeExpression is PostfixExpression_Access) HandleResult(acc.PostfixForeExpression, pfType); } var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, pfType); ctxt.CheckForSingleResult(accessedMembers, acc); if (accessedMembers != null && accessedMembers.Length != 0) { HandleResult(acc, accessedMembers[0]); return accessedMembers[0]; } return null; }
/// <summary> /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b). /// if <param name="EvalAndFilterOverloads"></param> is false. /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned /// which stores the return value of the property function b that is executed without arguments. /// Also handles UFCS - so if filtering is wanted, the function becom /// </summary> ISemantic[] E(PostfixExpression_Access acc, out bool IsUFCS, ISemantic resultBase = null, bool EvalAndFilterOverloads = true) { IsUFCS = false; if (acc == null) return null; var baseExpression = resultBase ?? E(acc.PostfixForeExpression); if (acc.AccessExpression is NewExpression) { /* * This can be both a normal new-Expression as well as an anonymous class declaration! */ //TODO! return null; } /* * Try to get ufcs functions at first! * * void foo(int i) {} * * class A * { * void foo(int i, int a) {} * * void bar(){ * 123.foo(23); // Not allowed! * // Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels, * // it would return the local foo() only, not the global one..which would be an error then! * } * * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones? * } */ var overloads = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[]; if (overloads == null) { if (acc.AccessExpression is TemplateInstanceExpression) { var tix = (TemplateInstanceExpression)acc.AccessExpression; // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments! overloads = GetOverloads(tix, resultBase == null ? null : new[] { AbstractType.Get(resultBase) }, EvalAndFilterOverloads); } else if (acc.AccessExpression is IdentifierExpression) { var id = ((IdentifierExpression)acc.AccessExpression).Value as string; overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression); // Might be a static property if (overloads == null) { var staticTypeProperty = StaticPropertyResolver.TryResolveStaticProperties(AbstractType.Get(baseExpression), id, ctxt); if (staticTypeProperty != null) return new[] { staticTypeProperty }; } } else { if (eval) throw new EvaluationException(acc, "Invalid access expression"); ctxt.LogError(acc, "Invalid post-dot expression"); return null; } } else IsUFCS = true; // If evaluation active and the access expression is stand-alone, return a single item only. if (EvalAndFilterOverloads && eval) return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) }; return overloads; }
public override void Visit(PostfixExpression_Access x) { // q.AddRange(DoPrimaryIdCheck(x)); base.Visit(x); }
public override void Visit(PostfixExpression_Access x) { // q.AddRange(DoPrimaryIdCheck(x)); base.Visit (x); }
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 override void Visit (PostfixExpression_Access acc) { acc.PostfixForeExpression.Accept(this); var id = acc.AccessExpression is NewExpression ? (acc.AccessExpression as NewExpression).Type as IntermediateIdType : acc.AccessExpression as IntermediateIdType; //TODO: Other types? Have additional facilities to extract an ID out of some expression? if (id != null && id.IdHash != searchHash) return; ctxt.CurrentContext.Set (acc.Location); var ov = ExpressionTypeEvaluation.GetAccessedOverloads (acc, ctxt, null, false); if (ov == null) return; foreach (var o in ov) if (TryAdd (o, acc.AccessExpression)) return; }
/// <summary> /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b). /// if <param name="EvalAndFilterOverloads"></param> is false. /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned /// which stores the return value of the property function b that is executed without arguments. /// Also handles UFCS - so if filtering is wanted, the function becom /// </summary> ISemantic[] E(PostfixExpression_Access acc, ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true) { if (acc == null) { return(null); } var baseExpression = resultBase ?? E(acc.PostfixForeExpression); if (acc.AccessExpression is NewExpression) { /* * This can be both a normal new-Expression as well as an anonymous class declaration! */ //TODO! return(null); } AbstractType[] overloads; var optBackup = ctxt.CurrentContext.ContextDependentOptions; if (acc.AccessExpression is TemplateInstanceExpression) { if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; } var tix = (TemplateInstanceExpression)acc.AccessExpression; // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments! overloads = GetOverloads(tix, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads); if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions = optBackup; } } else if (acc.AccessExpression is IdentifierExpression) { var id = acc.AccessExpression as IdentifierExpression; if (eval && EvalAndFilterOverloads && resultBase != null) { var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, resultBase, id.ValueStringHash); if (staticPropResult != null) { return new[] { staticPropResult } } ; } if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; } overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id.ValueStringHash, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression); if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions = optBackup; } } else { if (eval) { EvalError(acc, "Invalid access expression"); return(null); } ctxt.LogError(acc, "Invalid post-dot expression"); return(null); } /* * Try to get ufcs functions at first! * * void foo(int i) {} * * class A * { * void foo(int i, int a) {} * * void bar(){ * 123.foo(23); // Not allowed! * // Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels, * // it would return the local foo() only, not the global one..which would be an error then! * } * * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones? * } */ if (overloads == null || EvalAndFilterOverloads) { var oo = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[]; if (oo != null) { int overloadsLength = overloads == null ? 0 : overloads.Length; var newArr = new AbstractType[overloadsLength + oo.Length]; if (overloadsLength != 0) { overloads.CopyTo(newArr, 0); } oo.CopyTo(newArr, overloadsLength); overloads = newArr; } } // If evaluation active and the access expression is stand-alone, return a single item only. if (EvalAndFilterOverloads && eval) { return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) } } ; return(overloads); } 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); } ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression) { if (!eval) { return(foreExpression); // Still of the array's type. } if (!(foreExpression is ArrayValue)) { EvalError(x.PostfixForeExpression, "Must be an array"); return(null); } var ar = (ArrayValue)foreExpression; var sl = (PostfixExpression_Slice)x; // If the [ ] form is used, the slice is of the entire array. if (sl.FromExpression == null && sl.ToExpression == null) { return(foreExpression); } // Make $ operand available var arrLen_Backup = ValueProvider.CurrentArrayLength; ValueProvider.CurrentArrayLength = ar.Elements.Length; var bound_lower = E(sl.FromExpression) as PrimitiveValue; var bound_upper = E(sl.ToExpression) as PrimitiveValue; ValueProvider.CurrentArrayLength = arrLen_Backup; if (bound_lower == null || bound_upper == null) { EvalError(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type"); return(null); } int lower = -1, upper = -1; try { lower = Convert.ToInt32(bound_lower.Value); upper = Convert.ToInt32(bound_upper.Value); } catch { EvalError(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type"); return(null); } if (lower < 0) { EvalError(sl.FromExpression, "Lower boundary must be greater than 0"); return(null); } if (lower >= ar.Elements.Length) { EvalError(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length); return(null); } if (upper < lower) { EvalError(sl.ToExpression, "Upper boundary must be greater than " + lower); return(null); } if (upper >= ar.Elements.Length) { EvalError(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length); return(null); } var rawArraySlice = new ISymbolValue[upper - lower]; int j = 0; for (int i = lower; i < upper; i++) { rawArraySlice[j++] = ar.Elements[i]; } return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice)); } ISemantic E(PostfixExpression_Increment x, ISemantic foreExpression) { // myInt++ is still of type 'int' if (!eval) { return(foreExpression); } if (resolveConstOnly) { EvalError(new NoConstException(x)); } // Must be implemented anyway regarding ctfe return(null); } ISemantic E(PostfixExpression_Decrement x, ISemantic foreExpression) { if (!eval) { return(foreExpression); } if (resolveConstOnly) { EvalError(new NoConstException(x)); } // Must be implemented anyway regarding ctfe return(null); } } }
public static AbstractType[] GetAccessedOverloads(PostfixExpression_Access acc, ResolutionContext ctxt, ISemantic resultBase = null, bool DeducePostfixTemplateParams = true) { return(Evaluation.EvalPostfixAccessExpression <AbstractType>(new ExpressionTypeEvaluation(ctxt), ctxt, acc, resultBase, DeducePostfixTemplateParams)); }
public override void Visit(PostfixExpression_Access x) { if (IsIncompleteExpression(x.AccessExpression)) { halt = true; if (x.PostfixForeExpression is DTokenDeclaration && (x.PostfixForeExpression as DTokenDeclaration).Token == DTokens.Dot) { // Handle module-scoped things: // When typing a dot without anything following, trigger completion and show types, methods and vars that are located in the module & import scope prv = new CtrlSpaceCompletionProvider (cdgen, scopedBlock, null, MemberFilter.Methods | MemberFilter.Types | MemberFilter.Variables | MemberFilter.TypeParameters ); } else prv = new MemberCompletionProvider (cdgen, x.PostfixForeExpression, scopedBlock, scopedStatement); } else base.Visit (x); }
/// <summary> /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b). /// if <param name="EvalAndFilterOverloads"></param> is false. /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned /// which stores the return value of the property function b that is executed without arguments. /// Also handles UFCS - so if filtering is wanted, the function becom /// </summary> public static R[] EvalPostfixAccessExpression <R>(ExpressionVisitor <R> vis, ResolutionContext ctxt, PostfixExpression_Access acc, ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true, AbstractSymbolValueProvider ValueProvider = null) where R : class, ISemantic { if (acc == null) { return(null); } var baseExpression = resultBase ?? (acc.PostfixForeExpression != null ? acc.PostfixForeExpression.Accept(vis) as ISemantic : null); if (acc.AccessExpression is NewExpression) { /* * This can be both a normal new-Expression as well as an anonymous class declaration! */ //TODO! return(null); } AbstractType[] overloads; var optBackup = ctxt.CurrentContext.ContextDependentOptions; if (acc.AccessExpression is TemplateInstanceExpression) { if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; } var tix = (TemplateInstanceExpression)acc.AccessExpression; // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments! overloads = ExpressionTypeEvaluation.GetOverloads(tix, ctxt, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads); if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions = optBackup; } } else if (acc.AccessExpression is IdentifierExpression) { var id = acc.AccessExpression as IdentifierExpression; if (ValueProvider != null && EvalAndFilterOverloads && baseExpression != null) { var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, baseExpression, id.ValueStringHash); if (staticPropResult != null) { return new[] { (R)staticPropResult } } ; } if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes; } overloads = ExpressionTypeEvaluation.GetOverloads(id, ctxt, AmbiguousType.TryDissolve(AbstractType.Get(baseExpression)), EvalAndFilterOverloads); if (!ResolveImmediateBaseType) { ctxt.CurrentContext.ContextDependentOptions = optBackup; } } else { /* * if (eval){ * EvalError(acc, "Invalid access expression"); * return null; * }*/ ctxt.LogError(acc, "Invalid post-dot expression"); return(null); } // If evaluation active and the access expression is stand-alone, return a single item only. if (EvalAndFilterOverloads && ValueProvider != null) { return new[] { (R) new Evaluation(ValueProvider).TryDoCTFEOrGetValueRefs(AmbiguousType.Get(overloads, acc.AccessExpression), acc.AccessExpression) } } ; return(overloads as R[]); } ISymbolValue EvalForeExpression(PostfixExpression ex) { return(ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null); }
public static AbstractType[] GetAccessedOverloads(PostfixExpression_Access acc, ResolutionContext ctxt, ISemantic resultBase = null, bool DeducePostfixTemplateParams = true) { return TypeDeclarationResolver.Convert(new Evaluation(ctxt).E(acc, resultBase, DeducePostfixTemplateParams)); }
IExpression HexFloat() { bool neg = false; sb.Clear(); if (r.Peek() == 'N') { r.Read(); if (r.Peek() == 'A') { sb.Append('A'); r.Read(); if (r.Peek() == 'N') { r.Read(); return(new PostfixExpression_Access { AccessExpression = new IdentifierExpression("nan"), PostfixForeExpression = new TokenExpression(DTokens.Float) }); } } neg = true; } if (r.Peek() == 'I') { r.Read(); // Skip I r.Read(); // Skip N r.Read(); // Skip F var inf = new PostfixExpression_Access { AccessExpression = new IdentifierExpression("infinity"), PostfixForeExpression = new TokenExpression(DTokens.Float) }; if (neg) { return new UnaryExpression_Sub { UnaryExpression = inf } } ; return(inf); } var n = HexDigits(false); if (neg) { n *= -1; } if (r.Peek() == 'P') { r.Read(); var exp = Exponent(); n *= (decimal)Math.Pow(10, exp); } return(new IdentifierExpression(n, LiteralFormat.Scalar | ((Math.Truncate(n) == n) ? 0 : LiteralFormat.FloatingPoint), LiteralSubformat.Double)); } string LName(int len = -1) { if (len < 0) { len = (int)Number(); } if (len == 0) { return(string.Empty); } var chs = new char[len]; for (int i = 0; i < len; i++) { chs[i] = (char)r.Read(); } return(new String(chs)); } bool PeekIsDecNumber { get{ var d = (char)r.Peek(); return(Lexer.IsLegalDigit(d, 10) && d != '_'); } } int Exponent() { if ((char)r.Peek() == 'N') { r.Read(); return(-(int)Number()); } return((int)Number()); } decimal HexDigits(bool clearSb = true) { if (clearSb) { sb.Clear(); } while (Lexer.IsHex((char)r.Peek())) { sb.Append((char)r.Read()); } return(Lexer.ParseFloatValue(sb, 16)); } decimal Number(bool clearSb = true) { if (clearSb) { sb.Clear(); } while (PeekIsDecNumber) { sb.Append((char)r.Read()); } return(Lexer.ParseFloatValue(sb, 10)); } #endregion }
public override void Visit(PostfixExpression_Access acc) { var resolvedSymbol = TryPopPFAStack (); if ((acc.AccessExpression is IdentifierExpression && (acc.AccessExpression as IdentifierExpression).ValueStringHash != searchHash) || (acc.AccessExpression is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { acc.PostfixForeExpression.Accept (this); return; } else if (acc.AccessExpression is NewExpression) { var nex = acc.AccessExpression as NewExpression; if ((nex.Type is IdentifierDeclaration && ((IdentifierDeclaration)nex.Type).IdHash != searchHash) || (nex.Type is TemplateInstanceExpression && ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash != searchHash)) { acc.PostfixForeExpression.Accept (this); return; } // Are there other types to test for? } else { // Are there other types to test for? } var s = resolvedSymbol ?? ExpressionTypeEvaluation.EvaluateType(acc, ctxt, false) as DerivedDataType; if (s is DSymbol) { if (((DSymbol)s).Definition == symbol) l.Add (acc.AccessExpression); } else if (s == null || !(s.Base is DSymbol)) { acc.PostfixForeExpression.Accept (this); return; } // Scan down for other possible symbols if(s.Base is DSymbol) postfixForeExprAccessStack.Push (s.Base as DSymbol); acc.PostfixForeExpression.Accept (this); }
List<IExpression> DoPrimaryIdCheck(PostfixExpression_Access acc) { var r = new List<IExpression>(); while(acc != null){ if (DoPrimaryIdCheck(ExtractId(acc))) r.Add(acc); // Scan down the access expression for other, deeper expressions if (acc.PostfixForeExpression is PostfixExpression_Access) acc = (PostfixExpression_Access)acc.PostfixForeExpression; else { if (DoPrimaryIdCheck(ExtractId(acc.PostfixForeExpression))) r.Add(acc.PostfixForeExpression); break; } } return r; }
IExpression HexFloat() { bool neg = false; sb.Clear(); if(r.Peek() == 'N') { r.Read(); if(r.Peek() == 'A') { sb.Append('A'); r.Read(); if(r.Peek() == 'N') { r.Read(); return new PostfixExpression_Access{ AccessExpression = new IdentifierExpression("nan"), PostfixForeExpression = new TokenExpression(DTokens.Float) }; } } neg = true; } if(r.Peek() == 'I') { r.Read(); // Skip I r.Read(); // Skip N r.Read(); // Skip F var inf = new PostfixExpression_Access{ AccessExpression = new IdentifierExpression("infinity"), PostfixForeExpression = new TokenExpression(DTokens.Float) }; if(neg) return new UnaryExpression_Sub{ UnaryExpression = inf }; return inf; } var n = HexDigits(false); if(neg) n *= -1; if(r.Peek() == 'P') { r.Read(); var exp = Exponent(); n *= (decimal)Math.Pow(10, exp); } return new IdentifierExpression(n, LiteralFormat.Scalar | ((Math.Truncate(n) == n) ? 0 : LiteralFormat.FloatingPoint), LiteralSubformat.Double); }
public static MemberSymbol[] TryResolveUFCS( ISemantic firstArgument, PostfixExpression_Access acc, ResolutionContext ctxt) { if (ctxt == null) { return(null); } int name = 0; if (acc.AccessExpression is IdentifierExpression) { name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash; } else if (acc.AccessExpression is TemplateInstanceExpression) { name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash; } else { return(null); } var methodMatches = new List <MemberSymbol>(); if (ctxt.ParseCache != null) { foreach (var pc in ctxt.ParseCache) { var tempResults = pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name); if (tempResults != null) { foreach (var m in tempResults) { ctxt.PushNewScope(m); if (m.TemplateParameters != null && m.TemplateParameters.Length != 0) { var ov = TemplateInstanceHandler.DeduceParamsAndFilterOverloads( new[] { new MemberSymbol(m, null, acc) }, new[] { firstArgument }, true, ctxt); if (ov == null || ov.Length == 0) { continue; } var ms = (DSymbol)ov[0]; ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms); } var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, null, acc) as MemberSymbol; if (mr != null) { mr.FirstArgument = firstArgument; mr.DeducedTypes = ctxt.CurrentContext.DeducedTemplateParameters.ToReadonly(); mr.IsUFCSResult = true; methodMatches.Add(mr); } ctxt.Pop(); } } } } return(methodMatches.Count == 0 ? null : methodMatches.ToArray()); }