internal static bool TryResolveOverload( DynamicMetaObjectBinder binder, Types.TotemType type, CallInfo callInfo, string name, IEnumerable<Tuple<MethodInfo, Types.TotemType.DynamicFlags>> methodSetups, DynamicMetaObject target, IList<DynamicMetaObject> args, out DynamicMetaObject result, int nonCountingArgs = 0, NarrowingLevel minLevel = NarrowingLevel.None, NarrowingLevel maxLevel = NarrowingLevel.All) { CodeContext context; Expression contextExpression; if (args.Count == callInfo.ArgumentCount + 1 + nonCountingArgs) { context = (CodeContext)args[0].Value; contextExpression = args[0].Expression; args = ArrayUtils.RemoveFirst(args); } else { contextExpression = AstUtils.Constant(type.Context.SharedContext); } Debug.Assert(args.Count == callInfo.ArgumentCount + nonCountingArgs); TotemOverloadResolverFactory fact = new TotemOverloadResolverFactory(type.Context.Binder, contextExpression); var runs = methodSetups.GroupBy(mi => mi.Item2).Select(g => new { g.Key, Values = g.Select(gr => gr.Item1) }); BindingRestrictions restrictions = target != null ? target.Restrictions : BindingRestrictions.Empty; foreach (var arg in args) restrictions = restrictions.Merge(arg.Restrictions); foreach (var run in runs) { BindingRestrictions runRestrictions = restrictions; var key = run.Key; var extraArgs = GetExtraArgs(key, type, target); var methods = run.Values.Cast<MethodBase>().ToArray(); List<DynamicMetaObject> arguments = new List<DynamicMetaObject>(args.Count + 5); // good margin for ekstras List<Argument> argInfo = new List<Argument>(); foreach (var extraArg in extraArgs) { arguments.Add(extraArg); runRestrictions = runRestrictions.Merge(extraArg.Restrictions); argInfo.Add(Argument.Simple); } arguments.AddRange(args); int normalArgCount = callInfo.ArgumentCount - callInfo.ArgumentNames.Count; List<Expression> normalArgs = new List<Expression>(); for (var i2 = 0; i2 < normalArgCount + nonCountingArgs; i2++) argInfo.Add(Argument.Simple); for (var i2 = 0; i2 < callInfo.ArgumentNames.Count; i2++) argInfo.Add(new Argument(callInfo.ArgumentNames[i2])); var overloadResolver = fact.CreateOverloadResolver(arguments, new CallSignature(argInfo.ToArray()), CallTypes.None); var bindingTarget = overloadResolver.ResolveOverload(name, methods, minLevel, maxLevel); if (bindingTarget.Success) { Expression call = bindingTarget.MakeExpression(); if (bindingTarget.ReturnType == typeof(void)) { call = Expression.Block( call, IronTotem.Parsing.Ast.ConstantExpression.Undefined ); } runRestrictions = runRestrictions.Merge(bindingTarget.RestrictedArguments.GetAllRestrictions()); result = new DynamicMetaObject( call, runRestrictions ); return true; } } result = TypeError( binder, "No matching overload found" ); return false; }
public TotemContext(ScriptDomainManager manager, IDictionary<string, object> options) : base(manager) { _options = new TotemOptions(options); _builtinModulesDict = CreateBuiltinTable(); TotemDictionary defaultScope = new TotemDictionary(); ModuleContext moduleContext = new ModuleContext(defaultScope, this); _defaultContext = moduleContext.GlobalContext; TotemBinder binder = new TotemBinder(this, _defaultContext); _sharedOverloadResolverFactory = new TotemOverloadResolverFactory(binder, Expression.Constant(_defaultContext)); _binder = binder; if (DefaultContext._default == null) { DefaultContext.InitializeDefaults(_defaultContext); } RecursionLimit = _options.RecursionLimit; InitializeBuiltins(); }