public virtual StandardRule <T> MakeRule() { CallAction callAction = CallAction.Make(Action.Signature); // TODO: First try to make a rule for get-member and see if we get back a constant method to call //GetMemberAction getAction = GetMemberAction.Make(Action.Name); //StandardRule<T> getRule = Binder.GetRule<T>(Context, getAction, new object[] { _args[0] }); // otherwise, make a generic rule with embedded dynamic sites StandardRule <T> rule = new StandardRule <T>(); rule.SetTest(Ast.True()); Expression getExpr = Ast.Action.GetMember(Action.Name, typeof(object), rule.Parameters[0]); Expression[] callArgs = new Expression[rule.ParameterCount]; callArgs[0] = getExpr; for (int i = 1; i < callArgs.Length; i++) { callArgs[i] = rule.Parameters[i]; } //TODO support non-object return types Expression callExpr = Ast.Action.Call(callAction, typeof(object), callArgs); rule.SetTarget(Ast.Return(callExpr)); return(rule); }
/// <summary> /// Given a CallAction and its arguments gets the number by which the parameter count should /// be adjusted due to the params array to get the logical number of parameters. /// </summary> protected static int GetParamsArgumentCountAdjust(CallAction action, object[] args) { int paramsCount = 0; int listArgIndex = action.Signature.IndexOf(ArgumentKind.List); if (listArgIndex > -1) { paramsCount--; IList <object> paramArgs = args[listArgIndex + 1] as IList <object>; if (paramArgs != null) { paramsCount += paramArgs.Count; } } return(paramsCount); }
public static Type[] GetArgumentTypes(CallAction action, object[] args) { List <Type> res = new List <Type>(); for (int i = 1; i < args.Length; i++) { switch (action.Signature.GetArgumentKind(i - 1)) { case ArgumentKind.Simple: case ArgumentKind.Instance: case ArgumentKind.Named: res.Add(CompilerHelpers.GetType(args[i])); continue; case ArgumentKind.List: IList <object> list = args[i] as IList <object>; if (list == null) { return(null); } for (int j = 0; j < list.Count; j++) { res.Add(CompilerHelpers.GetType(list[j])); } break; case ArgumentKind.Dictionary: // caller needs to process these... break; default: throw new NotImplementedException(); } } return(res.ToArray()); }
public static CallAction Call(int argumentCount) { return(CallAction.Make(argumentCount)); }
public virtual Statement MakeInvalidParametersError(MethodBinder binder, DynamicAction action, CallType callType, IList <MethodBase> targets, StandardRule rule, object [] args) { int minArgs = Int32.MaxValue; int maxArgs = Int32.MinValue; int maxDflt = Int32.MinValue; int argsProvided = args.Length - 1; // -1 to remove the object we're calling bool hasArgList = false, hasNamedArgument = false; Dictionary <string, bool> namedArgs = new Dictionary <string, bool>(); CallAction ca = action as CallAction; if (ca != null) { hasNamedArgument = ca.Signature.HasNamedArgument(); int dictArgIndex = ca.Signature.IndexOf(ArgumentKind.Dictionary); if (dictArgIndex > -1) { argsProvided--; IAttributesCollection iac = args[dictArgIndex + 1] as IAttributesCollection; if (iac != null) { foreach (KeyValuePair <object, object> kvp in iac) { namedArgs[(string)kvp.Key] = false; } } } argsProvided += GetParamsArgumentCountAdjust(ca, args); foreach (SymbolId si in ca.Signature.GetArgumentNames()) { namedArgs[SymbolTable.IdToString(si)] = false; } } else { maxArgs = minArgs = rule.Parameters.Length; maxDflt = 0; } foreach (MethodBase mb in targets) { if (callType == CallType.ImplicitInstance && CompilerHelpers.IsStatic(mb)) { continue; } ParameterInfo[] pis = mb.GetParameters(); int cnt = pis.Length; int dflt = 0; if (!CompilerHelpers.IsStatic(mb) && callType == CallType.None) { cnt++; } foreach (ParameterInfo pi in pis) { if (pi.ParameterType == typeof(CodeContext)) { cnt--; } else if (CompilerHelpers.IsParamArray(pi)) { cnt--; hasArgList = true; } else if (CompilerHelpers.IsParamDictionary(pi)) { cnt--; } else if (!CompilerHelpers.IsMandatoryParameter(pi)) { dflt++; cnt--; } namedArgs[pi.Name] = true; } minArgs = System.Math.Min(cnt, minArgs); maxArgs = System.Math.Max(cnt, maxArgs); maxDflt = System.Math.Max(dflt, maxDflt); } foreach (KeyValuePair <string, bool> kvp in namedArgs) { if (kvp.Value == false) { // unbound named argument. return(rule.MakeError( Ast.Ast.Call( typeof(RuntimeHelpers).GetMethod("TypeErrorForExtraKeywordArgument"), Ast.Ast.Constant(binder._name, typeof(string)), Ast.Ast.Constant(kvp.Key, typeof(string)) ) )); } } return(rule.MakeError( Ast.Ast.Call( typeof(RuntimeHelpers).GetMethod("TypeErrorForIncorrectArgumentCount", new Type[] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool) }), Ast.Ast.Constant(binder._name, typeof(string)), // name Ast.Ast.Constant(minArgs), // min formal normal arg cnt Ast.Ast.Constant(maxArgs), // max formal normal arg cnt Ast.Ast.Constant(maxDflt), // default cnt Ast.Ast.Constant(argsProvided), // args provided Ast.Ast.Constant(hasArgList), // hasArgList Ast.Ast.Constant(hasNamedArgument) // kwargs provided ) )); }