public ISymbolValue Visit(TemplateInstanceExpression tix) { var ImplicitlyExecute = this.ImplicitlyExecute; this.ImplicitlyExecute = true; return(TryDoCTFEOrGetValueRefs(AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(tix, ctxt), tix), tix, ImplicitlyExecute)); }
public AbstractType TryGetDType(IDBacktraceSymbol s) { if (!s.HasParent) { TryUpdateStackFrameInfo(); if (ctxt == null) { return(null); } return(AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(new IdentifierExpression(s.Name), ctxt, null))); } return(null); }
public AbstractType Visit(PostfixExpression_Slice x) { var foreExpression = EvalForeExpression(x); // myArray[0]; myArray[0..5]; if (foreExpression is MemberSymbol) { foreExpression = DResolver.StripMemberSymbols(foreExpression); } var udt = foreExpression as UserDefinedType; if (udt == null) { return(foreExpression); } AbstractType[] sliceArgs; if (x.FromExpression == null && x.ToExpression == null) { sliceArgs = null; } else { sliceArgs = new AbstractType[2]; if (x.FromExpression != null) { sliceArgs[0] = x.FromExpression.Accept(this); } if (x.ToExpression != null) { sliceArgs[1] = x.ToExpression.Accept(this); } } ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt); var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(OpSliceIdHash, AmbiguousType.TryDissolve(foreExpression), ctxt, x, false); overloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(overloads, sliceArgs, true, ctxt); ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt); return(TryPretendMethodExecution(AmbiguousType.Get(overloads, x), x, sliceArgs) ?? foreExpression); }
/// <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 EvalMethodCall(AbstractType[] baseExpression, ISymbolValue baseValue, TemplateInstanceExpression tix, ResolutionContext ctxt, PostfixExpression_MethodCall call, out List <ISemantic> callArguments, out ISymbolValue delegateValue, bool returnBaseTypeOnly, AbstractSymbolValueProvider ValueProvider = null) { //TODO: Refactor this crap! delegateValue = null; callArguments = null; var methodOverloads = new List <AbstractType>(); #region Search possible methods, opCalls or delegates that could be called bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit IEnumerable <AbstractType> scanResults = baseExpression; var nextResults = new List <AbstractType>(); while (scanResults != null) { foreach (var b in scanResults) { if (b is AmbiguousType) { nextResults.AddRange((b as AmbiguousType).Overloads); } else if (b is TemplateParameterSymbol) { nextResults.Add((b as TemplateParameterSymbol).Base); } else if (b is MemberSymbol) { var mr = (MemberSymbol)b; if (mr.Definition is DMethod) { methodOverloads.Add(mr); continue; } else if (mr.Definition is DVariable) { // If we've got a variable here, get its base type/value reference if (ValueProvider != null) { var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue; if (dgVal != null) { nextResults.Add(dgVal.Definition); continue; } else { ValueProvider.LogError(call, "Variable must be a delegate, not anything else"); return(null); } } else { var bt = mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt); // Must be of type delegate if (bt is DelegateType) { var ret = HandleCallDelegateType(ValueProvider, bt as DelegateType, methodOverloads, returnBaseTypeOnly); if (ret is ISymbolValue) { delegateValue = ret as ISymbolValue; return(null); } else if (ret is AbstractType) { return(ret as AbstractType); } } else { /* * If mr.Node is not a method, so e.g. if it's a variable * pointing to a delegate * * class Foo * { * string opCall() { return "asdf"; } * } * * Foo f=new Foo(); * f(); -- calls opCall, opCall is not static */ nextResults.Add(bt); requireStaticItems = false; } //TODO: Can other types work as function/are callable? } } } else if (b is DelegateType) { var ret = HandleCallDelegateType(ValueProvider, b as DelegateType, methodOverloads, returnBaseTypeOnly); if (ret is ISymbolValue) { delegateValue = ret as ISymbolValue; return(null); } else if (ret is AbstractType) { return(ret as AbstractType); } } else if (b is ClassType || b is StructType) { var tit = (TemplateIntermediateType)b; /* * auto a = MyStruct(); -- opCall-Overloads can be used */ var classDef = tit.Definition; if (classDef == null) { continue; } foreach (var i in ExpressionTypeEvaluation.GetOpCalls(tit, requireStaticItems)) { methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol); } /* * Every struct can contain a default ctor: * * struct S { int a; bool b; } * * auto s = S(1,true); -- ok * auto s2= new S(2,false); -- error, no constructor found! */ if (b is StructType && methodOverloads.Count == 0) { //TODO: Deduce parameters return(b); } } /* * If the overload is a template, it quite exclusively means that we'll handle a method that is the only * child inside a template + that is named as the template. */ else if (b is TemplateType) { methodOverloads.Add(b); } else if (b is PrimitiveType) // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal. { methodOverloads.Add(b); } } scanResults = nextResults.Count == 0 ? null : nextResults.ToArray(); nextResults.Clear(); } #endregion if (methodOverloads.Count == 0) { return(null); } // Get all arguments' types callArguments = new List <ISemantic>(); if (call.Arguments != null) { if (ValueProvider != null) { foreach (var arg in call.Arguments) { callArguments.Add(arg != null ? Evaluation.EvaluateValue(arg, ValueProvider) : null); } } else { foreach (var arg in call.Arguments) { callArguments.Add(arg != null ? ExpressionTypeEvaluation.EvaluateType(arg, ctxt) : null); } } } #region If explicit template type args were given, try to associate them with each overload if (tix != null) { var args = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt); var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt); methodOverloads.Clear(); if (deducedOverloads != null) { methodOverloads.AddRange(deducedOverloads); } } #endregion #region Filter by parameter-argument comparison var argTypeFilteredOverloads = new List <AbstractType>(); bool hasHandledUfcsResultBefore = false; AbstractType untemplatedMethodResult = null; foreach (var ov in methodOverloads) { if (ov is MemberSymbol) { HandleDMethodOverload(ctxt, ValueProvider != null, baseValue, callArguments, returnBaseTypeOnly, argTypeFilteredOverloads, ref hasHandledUfcsResultBefore, ov as MemberSymbol, ref untemplatedMethodResult); } else if (ov is DelegateType) { var dg = ov as DelegateType; var bt = dg.Base ?? TypeDeclarationResolver.GetMethodReturnType(dg, ctxt); //TODO: Param-Arg check if (returnBaseTypeOnly) { argTypeFilteredOverloads.Add(bt); } else { if (dg.Base == null) { if (dg.IsFunctionLiteral) { dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters); } else { dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as DelegateDeclaration, dg.Parameters); } } argTypeFilteredOverloads.Add(new DelegateCallSymbol(dg, call)); } } else if (ov is PrimitiveType) // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal. { if (ValueProvider != null) { if (callArguments == null || callArguments.Count != 1) { ValueProvider.LogError(call, "Uniform construction syntax expects exactly one argument"); } else { var pv = callArguments[0] as PrimitiveValue; if (pv == null) { ValueProvider.LogError(call, "Uniform construction syntax expects one built-in scalar value as first argument"); } else { delegateValue = new PrimitiveValue(pv.Value, ov as PrimitiveType, pv.ImaginaryPart); } } } argTypeFilteredOverloads.Add(ov); } } // Prefer untemplated methods over templated ones if (untemplatedMethodResult != null) { return(untemplatedMethodResult); } #endregion return(AmbiguousType.Get(argTypeFilteredOverloads, tix)); }
public AbstractType Visit(IdentifierExpression id) { if (id.IsIdentifier) { return(TryPretendMethodExecution(AmbiguousType.Get(GetOverloads(id, ctxt), id))); } byte tt; switch (id.Format) { case Parser.LiteralFormat.CharLiteral: var tk = id.Subformat == LiteralSubformat.Utf32 ? DTokens.Dchar : id.Subformat == LiteralSubformat.Utf16 ? DTokens.Wchar : DTokens.Char; return(new PrimitiveType(tk, 0, id) { NonStaticAccess = true }); case LiteralFormat.FloatingPoint | LiteralFormat.Scalar: var im = id.Subformat.HasFlag(LiteralSubformat.Imaginary); tt = im ? DTokens.Idouble : DTokens.Double; if (id.Subformat.HasFlag(LiteralSubformat.Float)) { tt = im ? DTokens.Ifloat : DTokens.Float; } else if (id.Subformat.HasFlag(LiteralSubformat.Real)) { tt = im ? DTokens.Ireal : DTokens.Real; } return(new PrimitiveType(tt, 0, id) { NonStaticAccess = true }); case LiteralFormat.Scalar: var unsigned = id.Subformat.HasFlag(LiteralSubformat.Unsigned); if (id.Subformat.HasFlag(LiteralSubformat.Long)) { tt = unsigned ? DTokens.Ulong : DTokens.Long; } else { tt = unsigned ? DTokens.Uint : DTokens.Int; } return(new PrimitiveType(tt, 0, id) { NonStaticAccess = true }); case Parser.LiteralFormat.StringLiteral: case Parser.LiteralFormat.VerbatimStringLiteral: var str = GetStringType(id.Subformat); str.NonStaticAccess = true; return(str); default: return(null); } }
public AbstractType Visit(TemplateInstanceExpression tix) { return(TryPretendMethodExecution(AmbiguousType.Get(GetOverloads(tix, ctxt), tix))); }
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 AbstractType Visit(PostfixExpression_Access ex) { return(TryPretendMethodExecution(AmbiguousType.Get(Evaluation.EvalPostfixAccessExpression(this, ctxt, ex)))); }
public AbstractType Visit(NewExpression nex) { // http://www.d-programming-language.org/expression.html#NewExpression AbstractType[] possibleTypes; if (nex.Type is IdentifierDeclaration) { possibleTypes = TypeDeclarationResolver.Resolve((IdentifierDeclaration)nex.Type, ctxt, filterForTemplateArgs: false); } else { possibleTypes = TypeDeclarationResolver.Resolve(nex.Type, ctxt); } var ctors = new Dictionary <DMethod, TemplateIntermediateType>(); if (possibleTypes == null) { return(null); } foreach (var t in possibleTypes) { var ct = t as TemplateIntermediateType; if (ct != null && !ct.Definition.ContainsAttribute(DTokens.Abstract)) { foreach (var ctor in GetConstructors(ct)) { // Omit all ctors that won't return the adequate if (ct.Modifier != 0) { if (!ctor.ContainsAttribute(ct.Modifier, DTokens.Pure)) { continue; } } else if (ctor.Attributes != null && ctor.Attributes.Count != 0) { bool skip = false; foreach (var attr in ctor.Attributes) { var mod = attr as Modifier; if (mod != null) { switch (mod.Token) { case DTokens.Const: case DTokens.Immutable: case DTokens.Shared: case DTokens.Nothrow: // ? // not DTokens.Pure due to some mystical reasons skip = true; break; } if (skip) { break; } } } if (skip) { continue; } } ctors.Add(ctor, ct); } } else if (t is AssocArrayType) { t.NonStaticAccess = true; return(AmbiguousType.Get(possibleTypes)); } } if (ctors.Count == 0) { return(new UnknownType(nex)); } // HACK: Return the base types immediately if (TryReturnMethodReturnType) { var ret = ctors.First().Value; // AmbiguousType.Get(ctors.Values); if (ret != null) { ret.NonStaticAccess = true; } return(ret); } MemberSymbol finalCtor = null; //TODO: Determine argument types and filter out ctor overloads. var kvFirst = ctors.First(); finalCtor = new MemberSymbol(kvFirst.Key, kvFirst.Value, nex); if (finalCtor != null) { return(TryPretendMethodExecution(finalCtor, nex)); } var resolvedCtors = new List <AbstractType>(); foreach (var kv in ctors) { resolvedCtors.Add(new MemberSymbol(kv.Key, kv.Value, nex)); } return(TryPretendMethodExecution(AmbiguousType.Get(resolvedCtors, nex), nex)); }
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); }