コード例 #1
0
ファイル: CoreSqlVisitor.cs プロジェクト: yuyixg/sdmap
        public Result Process(CoreSqlContext parseRule, string functionName)
        {
            var method = new DynamicMethod(functionName,
                                           typeof(Result <string>), new[] { typeof(OneCallContext) });

            _il = method.GetILGenerator();

            void returnBlock()
            {
                bool isNamed = NameUtil.IsNamed(functionName);
                // root:
                //     combine deps
                // child-named:
                //     not combine
                // child-unnamed:
                //     combine strings

                Label defaultExit          = _il.DefineLabel();
                Label childNamedNotCombine = _il.DefineLabel();

                _il.Emit(OpCodes.Ldarg_0);                         // ctx
                _il.Emit(OpCodes.Call, OneCallContext.GetIsChild); // isChild
                _il.Emit(isNamed ?
                         OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);     // isNamed
                _il.Emit(OpCodes.And);                             // if (isChild && isNamed)
                _il.Emit(OpCodes.Brtrue_S, childNamedNotCombine);  //     goto notCombine

                _il.MarkLabel(defaultExit);
                {
                    string methodName = isNamed ?
                                        nameof(CoreSqlVisitorHelper.CombineDeps) :
                                        nameof(CoreSqlVisitorHelper.CombineStrings);
                    MethodInfo combineMethod = typeof(CoreSqlVisitorHelper).GetMethod(methodName);
                    _il.Emit(OpCodes.Ldarg_0);                                   // ctx
                    _il.Emit(OpCodes.Call, combineMethod);                       // result<str>
                    _il.Emit(OpCodes.Ret);                                       //
                }
                _il.MarkLabel(childNamedNotCombine);
                {
                    MethodInfo ok = typeof(Result).GetMethods()
                                    .Single(x => x.IsGenericMethod && x.Name == nameof(Result.Ok))
                                    .MakeGenericMethod(typeof(string));
                    _il.Emit(OpCodes.Ldstr, "");                                  // [empty]
                    _il.Emit(OpCodes.Call, ok);                                   // result<empty>
                    _il.Emit(OpCodes.Ret);                                        //
                }

                Function = (EmitFunction)method.CreateDelegate(typeof(EmitFunction));
            };

            if (parseRule == null)
            {
                returnBlock();
                return(Result.Ok());
            }

            _il.DeclareLocal(typeof(List <object>));
            _il.Emit(OpCodes.Ldarg_0);                                                // ctx
            _il.Emit(OpCodes.Call, OneCallContext.GetTempStore);                      // sb
            _il.Emit(OpCodes.Stloc_0);                                                // [empty]

            return(Visit(parseRule)
                   .OnSuccess(() =>                                                   // [must be empty]
            {
                returnBlock();
            }));
        }