public void IsExpressionAlias() { var ctxt = ResolutionTests.CreateCtxt("A", @"module A; static if(is(const(int)* U == const(U)*)) U var; U derp; "); IExpression x; AbstractType t; DSymbol ds; x = DParser.ParseExpression("var"); (x as IdentifierExpression).Location = new CodeLocation(2, 3); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); ds = t as DSymbol; Assert.That(t, Is.TypeOf(typeof(MemberSymbol))); Assert.That(ds.Base, Is.TypeOf(typeof(TemplateParameterSymbol))); ds = ds.Base as DSymbol; Assert.That(ds.Base, Is.TypeOf(typeof(PrimitiveType))); Assert.That((ds.Base as PrimitiveType).Modifier, Is.EqualTo(0)); ctxt.CurrentContext.DeducedTemplateParameters.Clear(); var dv = ctxt.ParseCache[0]["A"]["derp"].First() as DVariable; t = TypeDeclarationResolver.HandleNodeMatch(dv, ctxt); Assert.That(t, Is.TypeOf(typeof(MemberSymbol))); Assert.That((t as MemberSymbol).Base, Is.Null); }
static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt) { if (ept.Definition.Initializer == null && ept.Definition.Type == null) { ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!"); return(null); } // Introduce the deduced params to the current resolution context ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept); // Get actual overloads AbstractType deducedType = null; var def = ept.Definition; deducedType = new MemberSymbol(def, def.Type != null ? TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) : ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt); deducedType.Tag = ept.Tag; // Currently requried for proper UFCS resolution - sustain ept's Tag // Undo context-related changes ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept); return(deducedType); }
public void BasicResolution() { var ctxt = ResolutionTests.CreateCtxt("modA", @"module modA; void writeln(T...)(T t) {} int[] foo(string a) {} int foo(int a) {} string globStr; int globI; "); IExpression x; AbstractType t; x = DParser.ParseExpression("globStr.foo()"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(ArrayType))); x = DParser.ParseExpression("globI.foo()"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("globStr.writeln()"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); Assert.That((t as PrimitiveType).TypeToken, Is.EqualTo(DTokens.Void)); }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ed = Editor; ctxt = ResolutionContext.Create(Editor, false); AbstractType t = null; CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator, ctxt, () => { ctxt.Push(Editor); if (AccessExpression is IExpression) { t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt); } else if (AccessExpression is ITypeDeclaration) { t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt); } }); if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } t.Accept(this); }
/// <summary> /// /// </summary> /// <param name="dm"></param> /// <param name="args"></param> /// <param name="baseValueProvider">Required for evaluating missing default parameters.</param> public static bool AssignCallArgumentsToIC <T>(MemberSymbol mr, T[] args, AbstractSymbolValueProvider baseValueProvider, out Dictionary <DVariable, T> targetArgs, ResolutionContext ctxt = null) where T : class, ISemantic { var dm = mr.Definition as DMethod; int para = 0; ISemantic firstArg; if (TypeResolution.UFCSResolver.IsUfcsResult(mr, out firstArg)) { para++; } targetArgs = new Dictionary <DVariable, T>(); var argsRemaining = args != null ? args.Length : 0; int argu = 0; for (; para < dm.Parameters.Count; para++) { var par = dm.Parameters[para] as DVariable; if (par.Type is VarArgDecl && argsRemaining > 0) { var va_args = new T[argsRemaining]; args.CopyTo(va_args, argu); argsRemaining = 0; //TODO: Assign a value tuple to par if (++para < dm.Parameters.Count) { return(false); } } if (argsRemaining > 0) { targetArgs[par] = args[argu++]; argsRemaining--; } else if (par.Initializer != null) { if (typeof(T) == typeof(AbstractType)) { targetArgs[par] = ExpressionTypeEvaluation.EvaluateType(par.Initializer, ctxt) as T; } else if (typeof(T) == typeof(ISymbolValue)) { targetArgs[par] = Evaluation.EvaluateValue(par.Initializer, baseValueProvider) as T; } } else { return(false); } } return(argsRemaining == 0); }
public void IsExpressionAlias_InMethod() { var ctxt = ResolutionTests.CreateCtxt("A", @"module A; void main(){ pre; static if(is(const(int)* U == const(U)*)) { U var; } post; } "); IExpression x; AbstractType t; DSymbol ds; var main = ctxt.ParseCache[0]["A"]["main"].First() as DMethod; ctxt.PushNewScope(main, main.Body.SubStatements.First()); t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U") { Location = main.Body.SubStatements.First().Location }, ctxt); Assert.That(t, Is.Null); ctxt.Pop(); ctxt.PushNewScope(main, main.Body.SubStatements.ElementAt(2)); t = TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration("U") { Location = main.Body.SubStatements.ElementAt(2).Location }, ctxt); Assert.That(t, Is.Null); ctxt.Pop(); x = DParser.ParseExpression("var"); IStatement stmt; DResolver.SearchBlockAt(main, (x as IdentifierExpression).Location = new CodeLocation(3, 7), out stmt); ctxt.PushNewScope(main, stmt); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); ds = t as DSymbol; Assert.That(t, Is.TypeOf(typeof(MemberSymbol))); Assert.That(ds.Base, Is.TypeOf(typeof(TemplateParameterSymbol))); ds = ds.Base as DSymbol; Assert.That(ds.Base, Is.TypeOf(typeof(PrimitiveType))); Assert.That((ds.Base as PrimitiveType).Modifier, Is.EqualTo(0)); }
public override void Visit(TemplateInstanceExpression id) { if (id.TemplateIdHash == searchHash) { ctxt.CurrentContext.Set(id.Location); if (TryAdd(ExpressionTypeEvaluation.EvaluateType(id, ctxt, false), id)) { return; } } }
public override void Visit(IdentifierExpression id) { if (id.IsIdentifier && id.ValueStringHash == searchHash) { ctxt.CurrentContext.Set(id.Location); if (TryAdd(ExpressionTypeEvaluation.EvaluateType(id, ctxt, false), id)) { return; } } }
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) 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 void EponymousTemplates() { var ctxt = ResolutionTests.CreateDefCtxt(@"module B; alias Tuple(T...) = T; alias Tup = Tuple!(int, float, string); enum isIntOrFloat(F) = is(F == int) || is(F == float); "); IExpression x; ISymbolValue v; AbstractType t; x = DParser.ParseExpression("isIntOrFloat!(Tup[0])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); DToken tk; var td = DParser.ParseBasicType("Tuple!(int, float, string)", out tk); //t = TypeDeclarationResolver.ResolveSingle (td, ctxt); //Assert.That (t, Is.TypeOf(typeof(MemberSymbol))); //Assert.That ((t as MemberSymbol).Base, Is.TypeOf(typeof(DTuple))); x = DParser.ParseExpression("Tup[0]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[1]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[2]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(ArrayType))); x = DParser.ParseExpression("isIntOrFloat!int"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); x = DParser.ParseExpression("isIntOrFloat!float"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); x = DParser.ParseExpression("isIntOrFloat!string"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m)); }
bool HandleDecl(VectorDeclaration v, AbstractType r) { if (r.DeclarationOrExpressionBase is VectorDeclaration) { var v_res = ExpressionTypeEvaluation.EvaluateType(v.Id, ctxt); var r_res = ExpressionTypeEvaluation.EvaluateType(((VectorDeclaration)r.DeclarationOrExpressionBase).Id, ctxt); if (v_res == null || r_res == null) { return(false); } else { return(ResultComparer.IsImplicitlyConvertible(r_res, v_res)); } } return(false); }
public AbstractType Visit(DVariable variable) { AbstractType bt; if (CanResolveBase(variable)) { var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt); if (bts != null && bts.Length != 0) { bt = bts[0]; } // For auto variables, use the initializer to get its type else if (variable.Initializer != null) { bt = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(variable.Initializer, ctxt)); } else { bt = null; } // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) { bt = GetForeachIteratorType(variable); } if (bt == null) { ctxt.CheckForSingleResult(bts, variable.Type as ISyntaxRegion ?? variable.Initializer); } } else { bt = null; } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type return(variable.IsAlias ? new AliasedType(variable, bt, typeBase) : new MemberSymbol(variable, bt, typeBase)); }
public override void Visit(TemplateInstanceExpression tix) { var resolvedSymbol = TryPopPFAStack(); if (tix.TemplateIdHash == searchHash) { if (resolvedSymbol == null) { resolvedSymbol = ExpressionTypeEvaluation.EvaluateType(tix, ctxt) as DSymbol; } if (resolvedSymbol != null && resolvedSymbol.Definition == symbol) { l.Add(tix); return; } } base.Visit(tix); }
public override void Visit(IdentifierExpression id) { var resolvedSymbol = TryPopPFAStack(); if (id.IsIdentifier && id.ValueStringHash == searchHash) { if (resolvedSymbol == null) { resolvedSymbol = ExpressionTypeEvaluation.EvaluateType(id, ctxt) as DSymbol; } if (resolvedSymbol != null && resolvedSymbol.Definition == symbol) { l.Add(id); return; } } base.Visit(id); }
public static AbstractType Resolve(TypeOfDeclaration typeOf, ResolutionContext ctxt) { // typeof(return) if (typeOf.Expression is TokenExpression && (typeOf.Expression as TokenExpression).Token == DTokens.Return) { var m = HandleNodeMatch(ctxt.ScopedBlock, ctxt, null, typeOf); if (m != null) { return(m); } } // typeOf(myInt) => int else if (typeOf.Expression != null) { var wantedTypes = ExpressionTypeEvaluation.EvaluateType(typeOf.Expression, ctxt); return(DResolver.StripMemberSymbols(wantedTypes)); } return(null); }
public void AliasedTypeTuple() { var ctxt = ResolutionTests.CreateDefCtxt(@"module A; template Tuple(T...) { alias Tuple = T; } alias Tup = Tuple!(int, float, string); template isIntOrFloat(T) { static if (is(T == int) || is(T == float)) enum isIntOrFloat = true; else enum isIntOrFloat = false; } "); IExpression x; ISymbolValue v; AbstractType t; x = DParser.ParseExpression("Tup[2]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(ArrayType))); x = DParser.ParseExpression("isIntOrFloat!(Tup[2])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m)); x = DParser.ParseExpression("Tup[0]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[1]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("isIntOrFloat!(Tup[0])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ed = Editor; ctxt = ResolutionContext.Create(Editor.ParseCache, new ConditionalCompilationFlags(Editor), ScopedBlock, ScopedStatement); ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly; AbstractType t; if (AccessExpression is IExpression) { t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt); } else if (AccessExpression is ITypeDeclaration) { t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt); } else { return; } t = DResolver.StripAliasSymbol(t); if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } isVariableInstance = false; if (t.DeclarationOrExpressionBase is ITypeDeclaration) { isVariableInstance |= (t.DeclarationOrExpressionBase as ITypeDeclaration).ExpressesVariableAccess; } t.Accept(this); }
public static AbstractType ResolveType(IEditorData editor, ResolutionContext ctxt = null) { var o = GetScopedCodeObject(editor); if (ctxt == null) { ctxt = ResolutionContext.Create(editor, false); } AbstractType ret = null; CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () => { ctxt.Push(editor); var optionBackup = ctxt.CurrentContext.ContextDependentOptions; ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly; if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt); } else if (o is INode) { ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt); } ctxt.CurrentContext.ContextDependentOptions = optionBackup; }); return(ret); }
/// <summary> /// string[] s; /// /// foreach(i;s) /// { /// // i is of type 'string' /// writeln(i); /// } /// </summary> public AbstractType GetForeachIteratorType(DVariable i) { var r = new List <AbstractType>(); var curStmt = ctxt.ScopedStatement; bool init = true; // Walk up statement hierarchy -- note that foreach loops can be nested while (curStmt != null) { if (init) { init = false; } else { curStmt = curStmt.Parent; } if (curStmt is ForeachStatement) { var fe = (ForeachStatement)curStmt; if (fe.ForeachTypeList == null) { continue; } // If the searched variable is declared in the header int iteratorIndex = -1; for (int j = 0; j < fe.ForeachTypeList.Length; j++) { if (fe.ForeachTypeList[j] == i) { iteratorIndex = j; break; } } if (iteratorIndex == -1) { continue; } bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1; // foreach(var k, var v; 0 .. 9) if (keyIsSearched && fe.IsRangeStatement) { // -- it's static type int, of course(?) return(new PrimitiveType(DTokens.Int)); } var aggregateType = ExpressionTypeEvaluation.EvaluateType(fe.Aggregate, ctxt); aggregateType = DResolver.StripMemberSymbols(aggregateType); if (aggregateType == null) { return(null); } // The most common way to do a foreach if (aggregateType is AssocArrayType) { var ar = (AssocArrayType)aggregateType; return(keyIsSearched ? ar.KeyType : ar.ValueType); } else if (aggregateType is UserDefinedType) { var tr = (UserDefinedType)aggregateType; if (keyIsSearched || !(tr.Definition is IBlockNode)) { continue; } bool foundIterPropertyMatch = false; #region Foreach over Structs and Classes with Ranges // Enlist all 'back'/'front' members var t_l = new List <AbstractType>(); foreach (var n in (IBlockNode)tr.Definition) { if (fe.IsReverse ? n.Name == "back" : n.Name == "front") { t_l.Add(HandleNodeMatch(n, ctxt)); } } // Remove aliases var iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropType in iterPropertyTypes) { if (iterPropType is MemberSymbol) { foundIterPropertyMatch = true; var itp = (MemberSymbol)iterPropType; // Only take non-parameterized methods if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0) { continue; } // Handle its base type [return type] as iterator type if (itp.Base != null) { r.Add(itp.Base); } foundIterPropertyMatch = true; } } if (foundIterPropertyMatch) { continue; } #endregion #region Foreach over Structs and Classes with opApply t_l.Clear(); r.Clear(); foreach (var n in (IBlockNode)tr.Definition) { if (n is DMethod && (fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply")) { t_l.Add(HandleNodeMatch(n, ctxt)); } } iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropertyType in iterPropertyTypes) { if (iterPropertyType is MemberSymbol) { var mr = (MemberSymbol)iterPropertyType; var dm = mr.Definition as DMethod; if (dm == null || dm.Parameters.Count != 1) { continue; } var dg = dm.Parameters[0].Type as DelegateDeclaration; if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length) { continue; } var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt); if (paramType != null && paramType.Length > 0) { r.Add(paramType[0]); } } } #endregion } if (r.Count > 1) { ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type")); } return(r.Count != 0 ? r[0] : null); } } return(null); }
public static AbstractType GetMethodReturnType(DMethod method, ResolutionContext ctxt) { if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) == ResolutionOptions.DontResolveBaseTypes) { return(null); } /* * If a method's type equals null, assume that it's an 'auto' function.. * 1) Search for a return statement * 2) Resolve the returned expression * 3) Use that one as the method's type */ bool pushMethodScope = ctxt.ScopedBlock != method; if (method.Type != null) { if (pushMethodScope) { ctxt.PushNewScope(method); } //FIXME: Is it legal to explicitly return a nested type? var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt); if (pushMethodScope) { ctxt.Pop(); } ctxt.CheckForSingleResult(returnType, method.Type); if (returnType != null && returnType.Length > 0) { return(returnType[0]); } } else if (method.Body != null) { ReturnStatement returnStmt = null; var list = new List <IStatement> { method.Body }; var list2 = new List <IStatement>(); bool foundMatch = false; while (!foundMatch && list.Count > 0) { foreach (var stmt in list) { if (stmt is ReturnStatement) { returnStmt = stmt as ReturnStatement; var te = returnStmt.ReturnExpression as TokenExpression; if (te == null || te.Token != DTokens.Null) { foundMatch = true; break; } } var statementContainingStatement = stmt as StatementContainingStatement; if (statementContainingStatement != null) { list2.AddRange(statementContainingStatement.SubStatements); } } list = list2; list2 = new List <IStatement>(); } if (returnStmt != null && returnStmt.ReturnExpression != null) { if (pushMethodScope) { var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters; ctxt.PushNewScope(method, returnStmt); if (dedTypes.Count != 0) { foreach (var kv in dedTypes) { ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value; } } } var t = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(returnStmt.ReturnExpression, ctxt)); if (pushMethodScope) { ctxt.Pop(); } return(t); } return(new PrimitiveType(DTokens.Void)); } return(null); }
public static AbstractType ResolveTypeLoosely(IEditorData editor, out NodeResolutionAttempt resolutionAttempt, ResolutionContext ctxt = null) { var o = GetScopedCodeObject(editor); if (ctxt == null) { ctxt = ResolutionContext.Create(editor, false); } AbstractType ret = null; NodeResolutionAttempt resAttempt = NodeResolutionAttempt.Normal; CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () => { ctxt.Push(editor); var optionBackup = ctxt.CurrentContext.ContextDependentOptions; ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly | ResolutionOptions.DontResolveAliases; if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt); } else if (o is INode) { ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt, null, o); } else { ret = null; } if (ret == null) { resAttempt = NodeResolutionAttempt.NoParameterOrTemplateDeduction; if (o is PostfixExpression_MethodCall) { o = (o as PostfixExpression_MethodCall).PostfixForeExpression; } ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.DontResolveAliases; if (o is IdentifierExpression) { ret = AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(o as IdentifierExpression, ctxt, deduceParameters: false), o); } else if (o is ITypeDeclaration) { ret = TypeDeclarationResolver.ResolveSingle(o as ITypeDeclaration, ctxt); } else if (o is IExpression) { ret = ExpressionTypeEvaluation.EvaluateType(o as IExpression, ctxt, false); } } if (ret == null) { resAttempt = NodeResolutionAttempt.RawSymbolLookup; var overloads = TypeDeclarationResolver.HandleNodeMatches(LookupIdRawly(editor, o as ISyntaxRegion), ctxt, null, o); ret = AmbiguousType.Get(overloads, o); } ctxt.CurrentContext.ContextDependentOptions = optionBackup; }); resolutionAttempt = resAttempt; if (ret != null) { ret.DeclarationOrExpressionBase = o; } return(ret); }
bool HandleDecl(TemplateTypeParameter parameter, TemplateInstanceExpression tix, AbstractType r) { /* * TODO: Scan down r for having at least one templateinstanceexpression as declaration base. * If a tix was found, check if the definition of the respective result base level * and the un-aliased identifier of the 'tix' parameter match. * Attention: if the alias represents an undeduced type (i.e. a type bundle of equally named type nodes), * it is only important that the definition is inside this bundle. * Therefore, it's needed to manually resolve the identifier, and look out for aliases or such unprecise aliases..confusing as s**t! * * If the param tix id is part of the template param list, the behaviour is currently undefined! - so instantly return false, I'll leave it as TODO/FIXME */ var paramTix_TemplateMatchPossibilities = ResolveTemplateInstanceId(tix); TemplateIntermediateType tixBasedArgumentType = null; var r_ = r as DSymbol; while (r_ != null) { if (r_.DeclarationOrExpressionBase is TemplateInstanceExpression) { var tit = r_ as TemplateIntermediateType; if (tit != null && CheckForTixIdentifierEquality(paramTix_TemplateMatchPossibilities, tit.Definition)) { tixBasedArgumentType = tit; break; } } r_ = r_.Base as DSymbol; } /* * This part is very tricky: * I still dunno what is allowed over here-- * * class Foo(T:Bar!E[],E) {} * ... * Foo!(Bar!string[]) f; -- E will be 'string' then * * class DerivateBar : Bar!string[] {} -- new Foo!DerivateBar() is also allowed, but now DerivateBar * obviously is not a template instance expression - it's a normal identifier only. */ if (tixBasedArgumentType != null) { var argEnum_given = ((TemplateInstanceExpression)tixBasedArgumentType.DeclarationOrExpressionBase).Arguments.GetEnumerator(); foreach (var p in tix.Arguments) { if (!argEnum_given.MoveNext() || argEnum_given.Current == null) { return(false); } // Convert p to type declaration var param_Expected = ConvertToTypeDeclarationRoughly(p); if (param_Expected == null) { return(false); } var result_Given = ExpressionTypeEvaluation.EvaluateType(argEnum_given.Current as IExpression, ctxt); if (result_Given == null || !HandleDecl(parameter, param_Expected, result_Given)) { return(false); } } // Too many params passed.. if (argEnum_given.MoveNext()) { return(false); } return(true); } return(false); }
public void ParsePerformance1() { //var pc = ParsePhobos(false); var pcl = ResolutionTests.CreateCache(@"module modA; import std.stdio, std.array; class lol{ static int Object; int inc(int i, int k) { return i+k; } void derp() {} const void lolBar(this T)() { auto l=123.inc!int(); lol.Object; writeln(typeid(T)); Object=1; } } void main() { immutable(char)[] arr; destroy(arr); for(int i=0;i<10;i++) writeln(i); return; auto st=new STest(); auto tt = new ModClass!int(); writeln(st.a); static assert(st.a==34); int i = delegate int() { return 123; }(); //int j= 234++; writeln(i); writeln(di,123,123); lol o = new lol(); o.derp(); } "); //pcl.Add(pc); var sw = new Stopwatch(); var main = pcl[0]["modA"]["main"].First() as DMethod; Assert.AreEqual(0, (pcl[0]["modA"] as DModule).ParseErrors.Count); var s = main.Body.SubStatements.Last() as IExpressionContainingStatement; var ctxt = ResolutionContext.Create(pcl, null, main, s.Location); //ctxt.ContextIndependentOptions |= ResolutionOptions.StopAfterFirstOverloads | ResolutionOptions.DontResolveBaseClasses | ResolutionOptions.DontResolveBaseTypes; var x = s.SubExpressions[0]; //pc.UfcsCache.Update(pcl); sw.Restart(); var t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); sw.Stop(); Trace.WriteLine("Took " + sw.Elapsed.TotalMilliseconds + "ms to resolve " + x); }
void HandleIndexSliceExpression(PostfixExpression x) { res.IsMethodArguments = true; res.ParsedExpression = x; var overloads = new List <AbstractType>(); if (x.PostfixForeExpression == null) { return; } var b = ExpressionTypeEvaluation.EvaluateType(x.PostfixForeExpression, ctxt); var bases = AmbiguousType.TryDissolve(b); var ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpSliceIdHash, bases, ctxt, x, false); if (ov != null) { overloads.AddRange(ov); } ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpIndexIdHash, bases, ctxt, x, false); if (ov != null) { overloads.AddRange(ov); } if (overloads.Count == 0) { b = DResolver.StripMemberSymbols(b); var toTypeDecl = new DTypeToTypeDeclVisitor(); var aa = b as AssocArrayType; if (aa != null) { var retType = aa.ValueType != null?aa.ValueType.Accept(toTypeDecl) : null; var dm = new DMethod { Name = "opIndex", Type = retType }; dm.Parameters.Add(new DVariable { Name = "index", Type = aa.KeyType != null ? aa.KeyType.Accept(toTypeDecl) : null }); overloads.Add(new MemberSymbol(dm, aa.ValueType, x)); if ((aa is ArrayType) && !(aa as ArrayType).IsStaticArray) { dm = new DMethod { Name = "opSlice", Type = retType }; overloads.Add(new MemberSymbol(dm, aa.ValueType, x)); } } else if (b is PointerType) { b = (b as PointerType).Base; var dm = new DMethod { Name = "opIndex", Type = b != null?b.Accept(toTypeDecl) : null }; dm.Parameters.Add(new DVariable { Name = "index", Type = new IdentifierDeclaration("size_t") }); overloads.Add(new MemberSymbol(dm, b, x)); } } res.ResolvedTypesOrMethods = overloads.ToArray(); }
public void Traits() { var pcl = ResolutionTests.CreateCache(@"module A; int i; string s; abstract class C { int foo(); } class NC { int foo(); } C c; int[] dynArr; int[5] statArr; auto assocArr = ['c' : 23, 'b' : 84]; struct S { void bar() { } void bar(int i) {} void bar(string s) {} static int statInt; } class D { void bar() { } abstract void absBar(); static void statFoo() {} final void finBar() {}; private int privInt; package int packInt; } class E : D{ final override void absBar() { } final void bar() {} } interface I { void bar(); } template Tmpl(){ void bar(); } ", @"module std.someStd;"); var ctxt = ResolutionTests.CreateDefCtxt(pcl, pcl[0]["A"], null); BoolTrait(ctxt, "isArithmetic, int"); BoolTrait(ctxt, "isArithmetic, i, i+1, int"); BoolTrait(ctxt, "isArithmetic", false); BoolTrait(ctxt, "isArithmetic, int*", false); BoolTrait(ctxt, "isArithmetic, s, 123", false); BoolTrait(ctxt, "isArithmetic, 123, s", false); BoolTrait(ctxt, "isAbstractClass, C, c"); BoolTrait(ctxt, "isAbstractClass, C"); BoolTrait(ctxt, "isAbstractClass, int", false); BoolTrait(ctxt, "isAbstractClass, NC", false); BoolTrait(ctxt, "isAbstractClass", false); BoolTrait(ctxt, "isAssociativeArray, assocArr"); BoolTrait(ctxt, "isAssociativeArray, dynArr", false); BoolTrait(ctxt, "isStaticArray, statArr"); BoolTrait(ctxt, "isStaticArray, dynArr", false); BoolTrait(ctxt, "isVirtualMethod, D.bar"); BoolTrait(ctxt, "isVirtualMethod, D.absBar"); BoolTrait(ctxt, "isVirtualMethod, I.bar"); BoolTrait(ctxt, "isVirtualMethod, Tmpl!().bar"); //BoolTrait(ctxt, "isVirtualMethod, E.bar"); //BoolTrait(ctxt, "isVirtualMethod, E.absBar"); BoolTrait(ctxt, "isVirtualMethod, S.bar", false); BoolTrait(ctxt, "isVirtualMethod, D.statFoo", false); BoolTrait(ctxt, "isVirtualMethod, D.finBar", false); BoolTrait(ctxt, "isVirtualFunction, D.bar"); BoolTrait(ctxt, "isVirtualFunction, D.absBar"); BoolTrait(ctxt, "isVirtualFunction, I.bar"); BoolTrait(ctxt, "isVirtualFunction, Tmpl!().bar"); //BoolTrait(ctxt, "isVirtualFunction, E.bar"); //BoolTrait(ctxt, "isVirtualFunction, E.absBar"); BoolTrait(ctxt, "isVirtualFunction, S.bar", false); BoolTrait(ctxt, "isVirtualFunction, D.statFoo", false); BoolTrait(ctxt, "isVirtualFunction, D.finBar"); BoolTrait(ctxt, "hasMember, C, \"foo\""); BoolTrait(ctxt, "hasMember, c, \"foo\""); BoolTrait(ctxt, "hasMember, C, \"noFoo\"", false); BoolTrait(ctxt, "hasMember, int, \"sizeof\""); var x = DParser.ParseExpression(@"__traits(identifier, C.aso.derp)"); var v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(ArrayValue))); var av = v as ArrayValue; Assert.That(av.IsString, Is.True); Assert.That(av.StringValue, Is.EqualTo("C.aso.derp")); x = DParser.ParseExpression("__traits(getMember, c, \"foo\")"); var t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(MemberSymbol))); x = DParser.ParseExpression("__traits(getOverloads, S, \"bar\")"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(TypeValue))); Assert.That((v as TypeValue).RepresentedType, Is.TypeOf(typeof(DTuple))); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(DTuple))); x = DParser.ParseExpression("__traits(getProtection, D.privInt)"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(ArrayValue))); av = v as ArrayValue; Assert.That(av.IsString, Is.True); Assert.That(av.StringValue, Is.EqualTo("private")); x = DParser.ParseExpression("__traits(getProtection, D)"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(ArrayValue))); av = v as ArrayValue; Assert.That(av.IsString, Is.True); Assert.That(av.StringValue, Is.EqualTo("public")); x = DParser.ParseExpression("__traits(getProtection, D.packInt)"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(ArrayValue))); av = v as ArrayValue; Assert.That(av.IsString, Is.True); Assert.That(av.StringValue, Is.EqualTo("package")); BoolTrait(ctxt, "isSame, int, int"); BoolTrait(ctxt, "isSame, int, double", false); BoolTrait(ctxt, "isSame, C, D", false); BoolTrait(ctxt, "isSame, D, D"); BoolTrait(ctxt, "compiles", false); BoolTrait(ctxt, "compiles, asd.herp", false); BoolTrait(ctxt, "compiles, i"); BoolTrait(ctxt, "compiles, i + 1"); //BoolTrait(ctxt, "compiles, &i + 1", false); //TODO: Check if both operand types match..is this still efficient? BoolTrait(ctxt, "compiles, typeof(1)"); BoolTrait(ctxt, "compiles, S.nonExistingItem", false); //TODO: Make the resolver not resolve non-static items implicitly (i.e. without explicit resolution option) BoolTrait(ctxt, "compiles, S.statInt"); BoolTrait(ctxt, "compiles, 1,2,3,int,long,std"); BoolTrait(ctxt, "compiles, 1,2,3,int,long,3[1]", false); BoolTrait(ctxt, "compiles, 3[1]", false); BoolTrait(ctxt, "compiles, immutable(S44)(3, &i)", false); }