public int GetCurrentParameterIndex(CodeLocation where) { /* * if(args.ParsedExpression is PostfixExpression_MethodCall) * { * var mc = args.ParsedExpression as PostfixExpression_MethodCall; * * if(mc.ArgumentCount == 0) * return 0; * for(int i = 0; i < mc.ArgumentCount; i++) * { * if(where <= mc.Arguments[i].EndLocation) * return i+1; * } * }*/ var idx = args.CurrentlyTypedArgumentIndex; var ms = CurrentResult as MemberSymbol; ISemantic _u; if (ms != null && UFCSResolver.IsUfcsResult(ms, out _u)) { idx++; } return(idx); }
void GenUfcsAndStaticProperties(AbstractType t) { if (isVariableInstance && CompletionOptions.Instance.ShowUFCSItems) { foreach (var ufcsItem in UFCSResolver.TryResolveUFCS(t, 0, ed.CaretLocation, ctxt)) { CompletionDataGenerator.Add((ufcsItem as DSymbol).Definition); } } StaticProperties.ListProperties(CompletionDataGenerator, MemberFilter, t, isVariableInstance); }
void GenUfcsAndStaticProperties(AbstractType t) { if (t.NonStaticAccess && CompletionOptions.Instance.ShowUFCSItems) { CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () => { foreach (var ufcsItem in UFCSResolver.TryResolveUFCS(t, 0, ed.CaretLocation, ctxt)) { CompletionDataGenerator.Add((ufcsItem as DSymbol).Definition); } }); } StaticProperties.ListProperties(CompletionDataGenerator, ctxt, MemberFilter, t, t.NonStaticAccess); }
static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore, MemberSymbol ms, ref AbstractType untemplatedMethod) { var dm = ms.Definition as DMethod; if (dm == null) { return; } ISemantic firstUfcsArg; bool isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg); // In the case of an ufcs, insert the first argument into the CallArguments list if (isUfcs && !hasHandledUfcsResultBefore) { callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg); hasHandledUfcsResultBefore = true; } else if (!isUfcs && hasHandledUfcsResultBefore) // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again { callArguments.RemoveAt(0); hasHandledUfcsResultBefore = false; } if (dm.Parameters.Count == 0 && callArguments.Count > 0) { return; } var deducedTypeDict = new DeducedTypeDictionary(ms); var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt); var back = ctxt.ScopedBlock; using (ctxt.Push(ms)) { if (ctxt.ScopedBlock != back) { ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict; } bool add = true; int currentArg = 0; if (dm.Parameters.Count > 0 || callArguments.Count > 0) { bool hadDTuples = false; for (int i = 0; i < dm.Parameters.Count; i++) { var paramType = dm.Parameters[i].Type; // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way.. if (paramType is IdentifierDeclaration && (hadDTuples |= TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))) { continue; } else if (currentArg < callArguments.Count) { if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++]))) { break; } } else { // If there are more parameters than arguments given, check if the param has default values add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null; // Assume that all further method parameters do have default values - and don't check further parameters break; } } // Too few args if (!hadDTuples && currentArg < callArguments.Count) { add = false; } } if (!add) { return; } // If type params were unassigned, try to take the defaults if (dm.TemplateParameters != null) { foreach (var tpar in dm.TemplateParameters) { if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null)) { return; } } } if (deducedTypeDict.AllParamatersSatisfied) { ms.DeducedTypes = deducedTypeDict.ToReadonly(); var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base; if (eval || !returnBaseTypeOnly) { bt = new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) { Tag = ms.Tag } } ; if (dm.TemplateParameters == null || dm.TemplateParameters.Length == 0) { untemplatedMethod = bt; //ISSUE: Have another state that indicates an ambiguous non-templated method matching. } argTypeFilteredOverloads.Add(bt); } } }
/// <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); } } }