Beispiel #1
0
        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 Expression ThrowParameterTypeError(string errorPrefix, MethodTable methodTable)
        {
            var parameterTypeError = typeof(BindingError).GetMethod("ParameterTypeError", BindingFlags.Public | BindingFlags.Static);
            var errorString        = Expression.Call(parameterTypeError, Expression.Constant(errorPrefix), Expression.Constant(methodTable));

            return(Expression.Throw(Expression.New(RuntimeExceptionConstructor, errorString)));
        }
Beispiel #4
0
        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));
            });
        }
Beispiel #5
0
        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)));
            });
        }
Beispiel #6
0
        public static string ParameterTypeError(string prefix, MethodTable methodTable)
        {
            var sb = new StringBuilder();

            sb.Append(prefix);
            sb.AppendLine("argument types do not match any available functions");

            var methods = methodTable.Methods
                          .SelectMany(l => l)
                          .Concat(methodTable.ParamsMethods)
                          .Distinct();

            foreach (var method in methods)
            {
                sb.Append("- ");
                sb.AppendLine(method.ToString());
            }

            return(sb.ToString());
        }
Beispiel #7
0
        private static object[] BuildParameterArray(
            string errorPrefix,
            MethodTable methodTable,
            MondState state,
            MondValue instance,
            MondValue[] args,
            out MethodBase methodBase,
            out ReturnConverter returnConversion)
        {
            Method method = null;

            if (args.Length < methodTable.Methods.Count)
            {
                method = FindMatch(methodTable.Methods[args.Length], args);
            }

            if (method == null)
            {
                method = FindMatch(methodTable.ParamsMethods, args);
            }

            if (method != null)
            {
                methodBase       = method.Info;
                returnConversion = method.ReturnConversion;

                var parameters = method.Parameters;
                var result     = new object[parameters.Count];

                var j = 0;
                for (var i = 0; i < result.Length; i++)
                {
                    var param = parameters[i];

                    switch (param.Type)
                    {
                    case ParameterType.Value:
                        if (j < args.Length)
                        {
                            result[i] = param.Conversion(args[j++]);
                        }
                        else
                        {
                            result[i] = param.Info.DefaultValue;
                        }
                        break;

                    case ParameterType.Params:
                        result[i] = Slice(args, method.MondParameterCount);
                        break;

                    case ParameterType.Instance:
                        result[i] = instance;
                        break;

                    case ParameterType.State:
                        result[i] = state;
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }

                return(result);
            }

            throw new MondBindingException(BindingError.ParameterTypeError(errorPrefix, methodTable));
        }
Beispiel #8
0
 private static object[] BuildParameterArray(
     string errorPrefix,
     MethodTable methodTable,
     MondState state,
     in MondValue instance,