protected IEnumerable<CilProduction> DoGetRules(MethodInfo method, CilSymbolRef leftSide)
        {
            var outcome = CilSymbolRef.Create(method.ReturnType);

            if (!object.Equals(outcome, leftSide))
            {
                return Enumerable.Empty<CilProduction>();
            }

            var pattern = new List<CilSymbolRef>();
            int argShift = 0;

            CilSymbolRef thisSymbol = GetThisSymbol();
            if (thisSymbol != null)
            {
                ++argShift;
                pattern.Add(thisSymbol);
            }

            var ruleMask = DoGetRuleMask(method);

            SubstituteRuleMask(method, pattern, ruleMask);

            var rule = new CilProduction(
                outcome:    outcome,
                pattern:    pattern,
                precedence: GetPrecedence(),
                context:    GetContext(method, thisSymbol != null),
                actionBuilder:
                    code =>
                    {
                        if (thisSymbol != null)
                        {
                            code.LdActionArgument(0, method.DeclaringType);
                        }

                        // Pass rule-arguments to the rule-method
                        for (int i = 0; i != method.GetParameters().Length; ++i)
                        {
                            var param = method.GetParameters()[i];
                            int ruleArgIndex = NthEmptySlotIndex(ruleMask, i);
                            if (thisSymbol != null)
                            {
                                ++ruleArgIndex;
                            }

                            code.LdActionArgument(ruleArgIndex, param.ParameterType);
                        }

                        code.Emit(
                            il =>
                            {
                                il.Call(method);

                                if (method.ReturnType == typeof(void))
                                {
                                    il.Ldnull();
                                }
                                else if (method.ReturnType.IsValueType)
                                {
                                    il.Box(il.Types.Import(method.ReturnType));
                                }

                                return il;
                            });

                        return code;
                    });

            return new[] { rule };
        }
Esempio n. 2
0
        protected IEnumerable <CilProduction> DoGetRules(MethodInfo method, CilSymbolRef leftSide)
        {
            var outcome = CilSymbolRef.Create(method.ReturnType);

            if (!object.Equals(outcome, leftSide))
            {
                return(Enumerable.Empty <CilProduction>());
            }

            var pattern  = new List <CilSymbolRef>();
            int argShift = 0;

            CilSymbolRef thisSymbol = GetThisSymbol();

            if (thisSymbol != null)
            {
                ++argShift;
                pattern.Add(thisSymbol);
            }

            var ruleMask = DoGetRuleMask(method);

            SubstituteRuleMask(method, pattern, ruleMask);

            var rule = new CilProduction(
                outcome:    outcome,
                pattern:    pattern,
                precedence: GetPrecedence(),
                context:    GetContext(method, thisSymbol != null),
                actionBuilder:
                code =>
            {
                if (thisSymbol != null)
                {
                    code.LdActionArgument(0, method.DeclaringType);
                }

                // Pass rule-arguments to the rule-method
                for (int i = 0; i != method.GetParameters().Length; ++i)
                {
                    var param        = method.GetParameters()[i];
                    int ruleArgIndex = NthEmptySlotIndex(ruleMask, i);
                    if (thisSymbol != null)
                    {
                        ++ruleArgIndex;
                    }

                    code.LdActionArgument(ruleArgIndex, param.ParameterType);
                }

                code.Emit(
                    il =>
                {
                    il.Call(method);

                    if (method.ReturnType == typeof(void))
                    {
                        il.Ldnull();
                    }
                    else if (method.ReturnType.IsValueType)
                    {
                        il.Box(il.Types.Import(method.ReturnType));
                    }

                    return(il);
                });

                return(code);
            });

            return(new[] { rule });
        }