private static MondInstanceFunction BindInstanceImpl(string className, MethodTable method, string nameOverride = null, bool fakeInstance = false) { var errorPrefix = BindingError.ErrorPrefix(className, nameOverride ?? method.Name); if (!fakeInstance) { return((state, instance, args) => { MethodBase function; ReturnConverter returnConversion; var parameters = BuildParameterArray(errorPrefix, method, state, instance, args, out function, out returnConversion); var classInstance = instance.UserData; if (ReferenceEquals(classInstance, null)) { throw new MondRuntimeException(errorPrefix + BindingError.RequiresInstance); } return returnConversion(errorPrefix, state, Call(() => function.Invoke(classInstance, parameters))); }); } return((state, instance, args) => { MethodBase function; ReturnConverter returnConversion; var parameters = BuildParameterArray(errorPrefix, method, state, instance, args, out function, out returnConversion); return returnConversion(errorPrefix, state, Call(() => function.Invoke(null, parameters))); }); }
private static TFunc BindImpl <TFunc, TReturn>( string moduleName, MethodTable methodTable, bool instanceFunction, BindCallFactory callFactory) { var errorPrefix = BindingError.ErrorPrefix(moduleName, methodTable.Name); var parameters = new List <ParameterExpression> { Expression.Parameter(typeof(MondState), "state"), Expression.Parameter(typeof(MondValue[]), "arguments") }; if (instanceFunction) { parameters.Insert(1, Expression.Parameter(typeof(MondValue), "instance")); } var argumentsParam = parameters[instanceFunction ? 2 : 1]; var statements = new List <Expression>(); var returnLabel = Expression.Label(typeof(TReturn)); var argumentsLength = Expression.PropertyOrField(argumentsParam, "Length"); for (var i = 0; i < methodTable.Methods.Count; i++) { var dispatches = BuildDispatchExpression(errorPrefix, methodTable.Methods[i], i, parameters, instanceFunction, returnLabel, callFactory); if (dispatches.Count == 0) { continue; } var requiredArgCount = Expression.Constant(i); var argLengthEqual = Expression.Equal(argumentsLength, requiredArgCount); var argBranch = Expression.IfThen(argLengthEqual, Expression.Block(dispatches)); statements.Add(argBranch); } foreach (var group in methodTable.ParamsMethods.GroupBy(p => p.RequiredMondParameterCount)) { var dispatches = BuildDispatchExpression(errorPrefix, group, int.MaxValue, parameters, instanceFunction, returnLabel, callFactory); var requiredArgCount = Expression.Constant(group.Key); var argLengthAtLeast = Expression.GreaterThanOrEqual(argumentsLength, requiredArgCount); var argBranch = Expression.IfThen(argLengthAtLeast, Expression.Block(dispatches)); statements.Add(argBranch); } statements.Add(ThrowParameterTypeError(errorPrefix, methodTable)); statements.Add(Expression.Label(returnLabel, Expression.Default(typeof(TReturn)))); var block = Expression.Block(statements); return(Expression.Lambda <TFunc>(block, parameters).Compile()); }
private static MondConstructor BindConstructorImpl(string moduleName, MethodTable method) { var errorPrefix = BindingError.ErrorPrefix(moduleName, "#ctor"); return((state, instance, args) => { MethodBase constructor; ReturnConverter returnConversion; var parameters = BuildParameterArray(errorPrefix, method, state, instance, args, out constructor, out returnConversion); return Call(() => ((ConstructorInfo)constructor).Invoke(parameters)); }); }
private static MondFunction BindImpl(string moduleName, MethodTable method, string nameOverride = null) { var errorPrefix = BindingError.ErrorPrefix(moduleName, nameOverride ?? method.Name); return((state, args) => { MethodBase function; ReturnConverter returnConversion; var parameters = BuildParameterArray(errorPrefix, method, state, null, args, out function, out returnConversion); return returnConversion(errorPrefix, state, Call(() => function.Invoke(null, parameters))); }); }