Пример #1
0
        private Result EmitMacroResult(MacroContext context, bool topLevel)
        {
            string macroName = context.GetToken(SYNTAX, 0).GetText();

            _il.Emit(OpCodes.Ldarg_0);                                      // ctx
            _il.Emit(OpCodes.Ldstr, macroName);                             // ctx name
            _il.Emit(OpCodes.Ldstr, _context.CurrentNs);                    // ctx name ns
            _il.Emit(OpCodes.Ldarg_0);                                      // ctx name ns ctx
            _il.Emit(OpCodes.Call, OneCallContext.GetObj);                  // ctx name ns self

            var contexts = context.GetRuleContexts <MacroParameterContext>();

            _il.Emit(OpCodes.Ldc_I4, contexts.Length);                      // ctx name ns self
            _il.Emit(OpCodes.Newarr, typeof(object));                       // ctx name ns self args
            for (var i = 0; i < contexts.Length; ++i)
            {
                MacroParameterContext arg = contexts[i];

                _il.Emit(OpCodes.Dup);                                      // .. -> args
                _il.Emit(OpCodes.Ldc_I4, i);                                // .. -> args idx

                var result = EmitGetMacroParameter(arg);                    // .. -> args idx val
                if (!result.IsSuccess)
                {
                    return(result);
                }

                _il.Emit(OpCodes.Stelem_Ref);                               // ctx name ns self args
            }

            _il.Emit(OpCodes.Call, typeof(MacroManager)
                     .GetMethod(nameof(MacroManager.Execute)));             // result<str>
            _il.Emit(OpCodes.Dup);                                          // result<str> x 2
            _il.Emit(OpCodes.Call, typeof(Result)
                     .GetMethod("get_" + nameof(Result.IsSuccess)));        // result<str> bool
            _il.Emit(OpCodes.Ldc_I4_1);                                     // result<str> bool true
            var ifIsSuccess = _il.DefineLabel();

            _il.Emit(OpCodes.Beq, ifIsSuccess);                             // result<str> (jmp if equal)
            if (topLevel)
            {
                _il.Emit(OpCodes.Ret);                                         // [exit-returned]
                _il.MarkLabel(ifIsSuccess);                                    // ifIsSuccess:
                _il.Emit(OpCodes.Call, typeof(Result <string>)
                         .GetMethod("get_" + nameof(Result <string> .Value))); // str
            }
            else
            {
                var exit = _il.DefineLabel();
                _il.Emit(OpCodes.Br_S, exit);
                _il.MarkLabel(ifIsSuccess);                                    // ifIsSuccess:
                _il.Emit(OpCodes.Call, typeof(Result <string>)
                         .GetMethod("get_" + nameof(Result <string> .Value))); // str
                _il.MarkLabel(exit);
            }

            return(Result.Ok());
        }
Пример #2
0
        private Result EmitGetMacroParameter(MacroParameterContext arg)
        {
            if (arg.nsSyntax() != null)
            {
                _il.Emit(OpCodes.Ldstr, arg.nsSyntax().GetText());      // val
            }
            else if (arg.STRING() != null)
            {
                var result = StringUtil.Parse(arg.STRING().GetText());
                if (result.IsSuccess)
                {
                    _il.Emit(OpCodes.Ldstr, result.Value);              // val
                }
                else
                {
                    return(result);
                }
            }
            else if (arg.NUMBER() != null)
            {
                var result = NumberUtil.Parse(arg.NUMBER().GetText());
                if (result.IsSuccess)
                {
                    _il.Emit(OpCodes.Ldc_R8, result.Value);             // num
                    _il.Emit(OpCodes.Box, typeof(double));              // box<num>
                }
                else
                {
                    return(result);
                }
            }
            else if (arg.DATE() != null)
            {
                var result = DateUtil.Parse(arg.DATE().GetText());
                if (result.IsSuccess)
                {
                    _il.Emit(OpCodes.Ldc_I8, result.Value.ToBinary());  // num
                    var ctor = typeof(DateTime).GetConstructor(new[] { typeof(long) });
                    _il.Emit(OpCodes.Newobj, ctor);                     // date
                    _il.Emit(OpCodes.Box, typeof(DateTime));            // box<date>
                }
                else
                {
                    return(result);
                }
            }
            else if (arg.Bool() != null)
            {
                _il.Emit(bool.Parse(arg.Bool().GetText()) ?
                         OpCodes.Ldc_I4_1 :
                         OpCodes.Ldc_I4_0);                             // bool
                _il.Emit(OpCodes.Box, typeof(bool));                    // box<bool>
            }
            else if (arg.unnamedSql() != null)
            {
                var parseTree = arg.unnamedSql();
                var id        = NameUtil.GetFunctionName(parseTree);
                var result    = _context.TryGetEmiter(id, _context.CurrentNs);

                SqlEmiter emiter;
                if (result.IsSuccess)
                {
                    emiter = result.Value;
                }
                else
                {
                    emiter = SqlEmiterUtil.CreateUnnamed(parseTree, _context.CurrentNs);
                    var ok = _context.TryAdd(id, emiter);
                    if (ok.IsFailure)
                    {
                        return(ok);
                    }
                }

                var compileResult = emiter.EnsureCompiled(_context);
                if (compileResult.IsFailure)
                {
                    return(compileResult);
                }

                _il.Emit(OpCodes.Ldarg_0);                                // ctx
                _il.Emit(OpCodes.Call, OneCallContext.GetCompiler);       // compiler
                _il.Emit(OpCodes.Ldstr, id);                              // compiler id
                _il.Emit(OpCodes.Ldstr, _context.CurrentNs);              // compiler id ns
                _il.Emit(OpCodes.Call, typeof(SqlEmiterUtil)
                         .GetMethod(nameof(SqlEmiterUtil.EmiterFromId))); // emiter
            }
            else if (arg.macro() != null)
            {
                var result = EmitMacroResult(arg.macro(), topLevel: false);
                if (!result.IsSuccess)
                {
                    return(result);
                }
            }
            else
            {
                return(Result.Fail($"Unknown macro."));
            }

            return(Result.Ok());
        }