FunctionEvaluation(MemberSymbol method, AbstractSymbolValueProvider baseValueProvider, Dictionary<DVariable, ISymbolValue> args) { vp = new InterpretationContext(baseValueProvider); foreach (var kv in args) vp[kv.Key] = kv.Value; }
public static ISymbolValue EvaluateValue(VariableValue v, AbstractSymbolValueProvider vp) { if (v.RepresentedType is TemplateParameterSymbol) { var tps = v.RepresentedType as TemplateParameterSymbol; if (tps.ParameterValue != null) { return(tps.ParameterValue); } } var bt = v.Member; var ctxt = vp.ResolutionContext; if (bt != null) { //TODO: This is not tested entirely - but it makes test passing successfully! ctxt.PushNewScope(bt.Definition.Parent as Dom.IBlockNode); ctxt.CurrentContext.IntroduceTemplateParameterTypes(bt); } var val = vp[v.Variable]; if (bt != null) { ctxt.Pop(); } return(val ?? v); }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (vp == null) vp = new StandardValueProvider(null); return new Evaluation(vp).E(x) as ISymbolValue; }
public static PrimitiveValue GetPrimitiveValue(string literalCode,AbstractSymbolValueProvider vp=null) { var v = E(literalCode,vp ?? GetDefaultSymbolVP()); Assert.That(v,Is.TypeOf(typeof(PrimitiveValue))); return (PrimitiveValue)v; }
public static void TestPrimitive(string literal, int btToken, object val, AbstractSymbolValueProvider vp=null) { var pv = GetPrimitiveValue(literal, vp ?? GetDefaultSymbolVP()); Assert.That(pv.BaseTypeToken, Is.EqualTo(btToken)); Assert.That(pv.Value, Is.EqualTo(val)); }
static ISemantic HandleCallDelegateType(AbstractSymbolValueProvider ValueProvider, DelegateType dg, List <AbstractType> methodOverloads, bool returnBaseTypeOnly) { if (returnBaseTypeOnly) { return(ValueProvider != null ? new TypeValue(dg.Base) as ISemantic : dg.Base); } /* * int a = delegate(x) { return x*2; } (12); // a is 24 after execution * auto dg=delegate(x) {return x*3;}; * int b = dg(4); */ if (ValueProvider == null) { methodOverloads.Add(dg); return(null); } else { // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method. //EvalError(dg.DeclarationOrExpressionBase as IExpression, "TODO", dg); ValueProvider.LogError(dg.DeclarationOrExpressionBase, "Ctfe not implemented yet"); return(null); } }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { var oldV = vp[Variable]; if (oldV is ArrayValue) { var av = (ArrayValue)oldV; //TODO: Immutability checks if (av.IsString) { } else { var at = av.RepresentedType as ArrayType; var newElements = new ISymbolValue[av.Elements.Length + (ItemNumber<0 ? 1:0)]; av.Elements.CopyTo(newElements, 0); if (!ResultComparer.IsImplicitlyConvertible(value.RepresentedType, at.ValueType)) throw new EvaluationException(BaseExpression, value.ToCode() + " must be implicitly convertible to the array's value type!", value); // Add.. if (ItemNumber < 0) av.Elements[av.Elements.Length - 1] = value; else // or set the new value av.Elements[ItemNumber] = value; vp[Variable] = new ArrayValue(at, newElements); } } else throw new EvaluationException(BaseExpression, "Type of accessed item must be an array", oldV); }
public CTFEOrValueRefsVisitor(AbstractSymbolValueProvider vp, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments = null) { this.ValueProvider = vp; this.ImplicitlyExecute = ImplicitlyExecute; this.idOrTemplateInstance = idOrTemplateInstance; this.executionArguments = executionArguments; }
Evaluation(AbstractSymbolValueProvider vp) { this.ValueProvider = vp; if(vp!=null) vp.ev = this; this.eval = true; this.ctxt = vp.ResolutionContext; }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { if (vp != null && vp.ev != null) { vp.ev.EvalError(null, "Cannot assign a value to a static property.", new[] { this, value }); } //TODO: What about array.length? }
/// <summary> /// Removes all variable references by resolving them via the given value provider. /// Useful when only the value is of interest, not its container or other things. /// </summary> public static ISymbolValue GetVariableContents(ISymbolValue v, AbstractSymbolValueProvider vp) { while (v is VariableValue) { v = vp[((VariableValue)v).Variable]; } return(v); }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (vp == null) { vp = new StandardValueProvider(null); } return(new Evaluation(vp).E(x) as ISymbolValue); }
public static string EvaluateMixinExpressionContent(AbstractSymbolValueProvider vp,MixinExpression x) { var ev = new Evaluation(vp); ev.resolveConstOnly = true; var v = x.AssignExpression != null ? x.AssignExpression.Accept(ev) as ArrayValue : null; return v != null && v.IsString ? v.StringValue : null; }
public static string EvaluateMixinExpressionContent(AbstractSymbolValueProvider vp, MixinExpression x) { var ev = new Evaluation(vp); ev.resolveConstOnly = true; var v = x.AssignExpression != null?x.AssignExpression.Accept(ev) as ArrayValue : null; return(v != null && v.IsString ? v.StringValue : null); }
public static bool IsEqual(IExpression ex, IExpression ex2, AbstractSymbolValueProvider vp) { var val_x1 = Evaluation.EvaluateValue(ex, vp); var val_x2 = Evaluation.EvaluateValue(ex2, vp); //TEMPORARILY: Remove the string comparison if (val_x1 == null && val_x2 == null) return ex.ToString() == ex2.ToString(); return IsEqual(val_x1, val_x2); }
public static bool IsEqual(IExpression ex, IExpression ex2, AbstractSymbolValueProvider vp) { var val_x1 = Evaluation.EvaluateValue(ex, vp); var val_x2 = Evaluation.EvaluateValue(ex2, vp); //TEMPORARILY: Remove the string comparison if (val_x1 == null && val_x2 == null) return ex.ToString() == ex2.ToString(); return IsEqual(val_x1, val_x2); }
public static void TestBool(string literal, bool v = true, AbstractSymbolValueProvider vp =null) { var pv = GetPrimitiveValue(literal, vp); Assert.AreEqual(DTokens.Bool, pv.BaseTypeToken); if (v) Assert.AreEqual(1M, pv.Value, literal +" must be true"); else Assert.AreEqual(0M, pv.Value, literal + " must be false"); }
public static bool EvalIsExpression(string IsExpressionCode, AbstractSymbolValueProvider vp) { var e = DParser.ParseExpression("is("+IsExpressionCode+")"); var v = Evaluation.EvaluateValue(e, vp); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); var pv = (PrimitiveValue)v; Assert.AreEqual(pv.BaseTypeToken, DTokens.Bool, "Type of 'is(" + IsExpressionCode + ")' result must be bool"); return pv.Value == 1M; }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { var oldV = vp[Variable]; if (oldV is AssociativeArrayValue) { if (Key != null) { var aa = (AssociativeArrayValue)oldV; int itemToReplace = -1; for (int i = 0; i < aa.Elements.Count; i++) { if (SymbolValueComparer.IsEqual(aa.Elements[i].Key, Key)) { itemToReplace = i; break; } } // If we haven't found a matching key, add it to the array var newElements = new KeyValuePair <ISymbolValue, ISymbolValue> [aa.Elements.Count + (itemToReplace == -1 ? 1: 0)]; aa.Elements.CopyTo(newElements, 0); if (itemToReplace != -1) { newElements[itemToReplace] = new KeyValuePair <ISymbolValue, ISymbolValue>(newElements[itemToReplace].Key, value); } else { newElements[newElements.Length - 1] = new KeyValuePair <ISymbolValue, ISymbolValue>(Key, value); } // Finally, make a new associative array containing the new elements vp[Variable] = new AssociativeArrayValue(aa.RepresentedType as AssocArrayType, newElements); } else { if (vp.ev != null) { vp.ev.EvalError(null, "Key expression must not be null", Key); } } } else { if (vp.ev != null) { vp.ev.EvalError(null, "Type of accessed item must be an associative array", oldV); } } }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { var oldV = vp[Variable]; if (oldV is ArrayValue) { var av = (ArrayValue)oldV; //TODO: Immutability checks if (av.IsString) { } else { var at = av.RepresentedType as ArrayType; var newElements = new ISymbolValue[av.Elements.Length + (ItemNumber < 0 ? 1:0)]; av.Elements.CopyTo(newElements, 0); if (!ResultComparer.IsImplicitlyConvertible(value.RepresentedType, at.ValueType)) { if (vp.ev != null) { vp.ev.EvalError(null, value.ToCode() + " must be implicitly convertible to the array's value type!", value); } return; } // Add.. if (ItemNumber < 0) { av.Elements[av.Elements.Length - 1] = value; } else // or set the new value { av.Elements[ItemNumber] = value; } vp[Variable] = new ArrayValue(at, newElements); } } else { if (vp.ev != null) { vp.ev.EvalError(null, "Type of accessed item must be an array", oldV); } } }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (vp == null) { vp = new StandardValueProvider(null); } var ev = new Evaluation(vp); var v = x.Accept(ev); if (v == null && ev.Errors.Count != 0) { return(new ErrorValue(ev.Errors.ToArray())); } return(v); }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (x == null) { return(null); } if (vp == null) { throw new ArgumentNullException("vp"); } ISymbolValue v; if (vp.ResolutionContext != null) { if (vp.ResolutionContext.CancelOperation) { return(new TypeValue(new UnknownType(x))); } /* * if (vp is StandardValueProvider) // only for read-only/immutable expression value states * { * v = vp.ResolutionContext.ValueCache.TryGetType(x); * if (v != null) * return v; * }*/ } var ev = new Evaluation(vp); v = x.Accept(ev); if (v == null && ev.Errors.Count != 0) { return(new ErrorValue(ev.Errors.ToArray())); } /* * if(vp.ResolutionContext != null && vp is StandardValueProvider) * vp.ResolutionContext.ValueCache.Add(v, x); */ return(v); }
public static ISymbolValue EvaluateValue(VariableValue v, AbstractSymbolValueProvider vp) { if (vp.ResolutionContext != null && vp.ResolutionContext.CancelOperation) { return(v); } if (v.RepresentedType is TemplateParameterSymbol) { var tps = v.RepresentedType as TemplateParameterSymbol; if (tps.ParameterValue != null) { return(tps.ParameterValue); } } using (vp.ResolutionContext.Push(v.Member)) return(vp[v.Variable] ?? v); }
/// <summary> /// /// </summary> /// <param name="dm"></param> /// <param name="args"></param> /// <param name="baseValueProvider">Required for evaluating missing default parameters.</param> public static bool AssignCallArgumentsToIC(DMethod dm, ISymbolValue[] args, AbstractSymbolValueProvider baseValueProvider, out Dictionary<DVariable,ISymbolValue> targetArgs) { targetArgs = new Dictionary<DVariable, ISymbolValue>(); var argsRemaining = args != null ? args.Length : 0; int argu = 0; for (int para = 0; para < dm.Parameters.Count; para++) { var par = dm.Parameters[para] as DVariable; if (par.Type is VarArgDecl && argsRemaining > 0) { var va_args = new ISemantic[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) { targetArgs[par] = Evaluation.EvaluateValue(par.Initializer, baseValueProvider); } else return false; } return argsRemaining == 0; }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { throw new EvaluationException(BaseExpression, "Cannot assign a value to a static property.", value); //TODO: What about array.length? }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (vp == null) vp = new StandardValueProvider(null); var ev = new Evaluation(vp); var v = ev.E(x) as ISymbolValue; if(v == null && ev.Errors.Count != 0) return new ErrorValue(ev.Errors.ToArray()); return v; }
public static ISymbolValue E(string expression, AbstractSymbolValueProvider vp=null) { return Evaluation.EvaluateValue(DParser.ParseExpression(expression), vp ?? GetDefaultSymbolVP()); }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { vp[Variable] = value; }
public static ISymbolValue Execute(DMethod method, ISymbolValue[] arguments, AbstractSymbolValueProvider vp) { throw new NotImplementedException("CTFE is not implemented yet."); }
Evaluation(AbstractSymbolValueProvider vp) { this.ValueProvider = vp; vp.ev = this; this.ctxt = vp.ResolutionContext; }
public abstract void Set(AbstractSymbolValueProvider vp, ISymbolValue value);
public static ISymbolValue Execute(MemberSymbol method, ISymbolValue[] arguments, AbstractSymbolValueProvider vp) { return new ErrorValue(new EvaluationException("CTFE is not implemented yet.")); }
/// <summary> /// Removes all variable references by resolving them via the given value provider. /// Useful when only the value is of interest, not its container or other things. /// </summary> public static ISymbolValue GetVariableContents(ISymbolValue v, AbstractSymbolValueProvider vp) { while (v is VariableValue) v = vp[(v as VariableValue).Variable]; return v; }
private Evaluation(AbstractSymbolValueProvider vp) { this.ValueProvider = vp; this.eval = true; this.ctxt = vp.ResolutionContext; }
/// <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 ISymbolValue Execute(MemberSymbol method, Dictionary<DVariable, ISymbolValue> arguments, AbstractSymbolValueProvider vp) { var dm = method.Definition as DMethod; var eval = new FunctionEvaluation(method,vp,arguments); var ctxt = vp.ResolutionContext; ctxt.PushNewScope(dm, dm.Body); try { dm.Body.Accept(eval); } catch (CtfeException ex) { vp.LogError(dm, "Can't execute function at precompile time: " + ex.Message); } var ret = Evaluation.GetVariableContents(eval.returnedValue, eval.vp); ctxt.Pop(); return ret; //return new ErrorValue(new EvaluationException("CTFE is not implemented yet.")); }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { vp[Variable] = value; }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { if(vp != null && vp.ev != null) vp.ev.EvalError(null,"Cannot assign a value to a static property.", new[]{this, value}); //TODO: What about array.length? }
private Evaluation(AbstractSymbolValueProvider vp) { this.ValueProvider = vp; this.eval = true; this.ctxt = vp.ResolutionContext; }
public abstract void Set(AbstractSymbolValueProvider vp, ISymbolValue value);
/// <summary> /// Used when evaluating traits. /// Evaluates the first argument to <param name="t">t</param>, /// takes the second traits argument, tries to evaluate it to a string, and puts it + the first arg into an postfix_access expression /// </summary> internal static PostfixExpression_Access prepareMemberTraitExpression(ResolutionContext ctxt, TraitsExpression te, out AbstractType t, AbstractSymbolValueProvider vp = null) { if (te.Arguments != null && te.Arguments.Length == 2) { var tEx = te.Arguments[0]; t = DResolver.StripMemberSymbols(ResolveTraitArgument(ctxt, tEx)); if (t == null) { ctxt.LogError(te, "First argument didn't resolve to a type"); } else if (te.Arguments[1].AssignExpression != null) { var litEx = te.Arguments[1].AssignExpression; var v = vp != null?Evaluation.EvaluateValue(litEx, vp) : Evaluation.EvaluateValue(litEx, ctxt); if (v is ArrayValue && (v as ArrayValue).IsString) { var av = v as ArrayValue; // Mock up a postfix_access expression to ensure static properties & ufcs methods are checked either return(new PostfixExpression_Access { PostfixForeExpression = tEx.AssignExpression ?? new TypeDeclarationExpression(tEx.Type), AccessExpression = new IdentifierExpression(av.StringValue) { Location = litEx.Location, EndLocation = litEx.EndLocation }, EndLocation = litEx.EndLocation }); } else { ctxt.LogError(litEx, "Second traits argument must evaluate to a string literal"); } } else { ctxt.LogError(te, "Second traits argument must be an expression"); } } t = null; return(null); }
public static ISymbolValue EvaluateValue(VariableValue v, AbstractSymbolValueProvider vp) { if(v.RepresentedType is TemplateParameterSymbol) { var tps = v.RepresentedType as TemplateParameterSymbol; if(tps.ParameterValue != null) return tps.ParameterValue; } var bt = v.Member; var ctxt = vp.ResolutionContext; bool pop=false; if(bt != null) { //TODO: This is not tested entirely - but it makes test passing successfully! pop = true; ctxt.PushNewScope (bt.Definition.Parent as Dom.IBlockNode); ctxt.CurrentContext.IntroduceTemplateParameterTypes(bt); } var val = vp[v.Variable]; if(bt != null) { if (pop) ctxt.Pop (); vp.ResolutionContext.CurrentContext.RemoveParamTypesFromPreferredLocals(bt); } return val ?? v; }
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 override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { var oldV = vp[Variable]; if (oldV is AssociativeArrayValue) { if (Key != null) { var aa = (AssociativeArrayValue)oldV; int itemToReplace = -1; for (int i = 0; i < aa.Elements.Count; i++) if (SymbolValueComparer.IsEqual(aa.Elements[i].Key, Key)) { itemToReplace = i; break; } // If we haven't found a matching key, add it to the array var newElements = new KeyValuePair<ISymbolValue, ISymbolValue>[aa.Elements.Count + (itemToReplace == -1 ? 1 : 0)]; aa.Elements.CopyTo(newElements, 0); if (itemToReplace != -1) newElements[itemToReplace] = new KeyValuePair<ISymbolValue, ISymbolValue>(newElements[itemToReplace].Key, value); else newElements[newElements.Length - 1] = new KeyValuePair<ISymbolValue, ISymbolValue>(Key, value); // Finally, make a new associative array containing the new elements vp[Variable] = new AssociativeArrayValue(aa.RepresentedType as AssocArrayType, newElements); } else{ if(vp.ev !=null) vp.ev.EvalError(null,"Key expression must not be null", Key); } } else{ if(vp.ev != null) vp.ev.EvalError(null,"Type of accessed item must be an associative array", oldV); } }
public static ISymbolValue TryEvalPropertyValue(AbstractSymbolValueProvider vp, ISemantic baseSymbol, int propName) { var props = Properties[PropOwnerType.Generic]; StaticPropertyInfo prop; if (props.TryGetValue(propName, out prop) || (Properties.TryGetValue(GetOwnerType(baseSymbol), out props) && props.TryGetValue(propName, out prop))) { if (prop.ValueGetter != null) return prop.ValueGetter(vp, baseSymbol); } return null; }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { throw new EvaluationException(BaseExpression, "Cannot assign a value to a static property.", value); //TODO: What about array.length? }