public void HelloWorld()
        {
            var code      = "sql v1{Hello World}";
            var parseTree = GetParseTree(code);
            var result    = SqlEmiterUtil.CompileNamed(
                SdmapCompilerContext.CreateEmpty(),
                parseTree.namedSql()[0]);

            Assert.True(result.IsSuccess);

            var function = result.Value;
            var output   = function(SdmapCompilerContext.CreateEmpty(), null);

            Assert.Equal("Hello World", output.Value);
        }
        public void SqlInNamespaceTest()
        {
            var sql       = "SELECT * FROM `client_WOReactive`;";
            var code      = "sql v1{" + sql + "}";
            var parseTree = GetParseTree(code);
            var result    = SqlEmiterUtil.CompileNamed(
                SdmapCompilerContext.CreateEmpty(),
                parseTree.namedSql()[0]);

            Assert.True(result.IsSuccess);

            var function = result.Value;
            var output   = function(SdmapCompilerContext.CreateEmpty(), null);

            Assert.Equal(sql, output.Value);
        }
        public void MultiLineTest()
        {
            var sql =
                "SELECT                  \r\n" +
                "   *                    \r\n" +
                "FROM                    \r\n" +
                "   `client_WOReactive`; \r\n";
            var code      = $"sql v1{{{sql}}}";
            var parseTree = GetParseTree(code);
            var result    = SqlEmiterUtil.CompileNamed(
                SdmapCompilerContext.CreateEmpty(),
                parseTree.namedSql()[0]);

            Assert.True(result.IsSuccess);

            var function = result.Value;
            var output   = function(SdmapCompilerContext.CreateEmpty(), null);

            Assert.Equal(sql, output.Value);
        }
Beispiel #4
0
        public override Result VisitNamedSql([NotNull] SdmapParser.NamedSqlContext context)
        {
            var id = context.GetToken(SYNTAX, 0).GetText();

            return(Context.TryAdd(id, SqlEmiterUtil.CreateNamed(context, Context.CurrentNs)));
        }
Beispiel #5
0
        public override Result VisitMacro([NotNull] MacroContext context)
        {
            var 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_1);                                      // 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)
            {
                var arg = contexts[i];

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

                if (arg.nsSyntax() != null)
                {
                    _il.Emit(OpCodes.Ldstr, arg.nsSyntax().GetText());      // .. -> args idx ele
                }
                else if (arg.STRING() != null)
                {
                    var result = StringUtil.Parse(arg.STRING().GetText());  // .. -> args idx ele
                    if (result.IsSuccess)
                    {
                        _il.Emit(OpCodes.Ldstr, result.Value);              // .. -> args idx ele
                    }
                    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);             // .. -> args idx vele
                        _il.Emit(OpCodes.Box, typeof(double));              // .. -> args idx rele
                    }
                    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());  // .. -> args idx int64
                        var ctor = typeof(DateTime).GetTypeInfo().GetConstructor(new[] { typeof(long) });
                        _il.Emit(OpCodes.Newobj, ctor);                     // .. -> args idx date
                        _il.Emit(OpCodes.Box, typeof(DateTime));            // .. -> args idx rele
                    }
                    else
                    {
                        return(result);
                    }
                }
                else if (arg.Bool() != null)
                {
                    _il.Emit(bool.Parse(arg.Bool().GetText()) ?
                             OpCodes.Ldc_I4_1 :
                             OpCodes.Ldc_I4_0);                             // .. -> args idx bool
                    _il.Emit(OpCodes.Box, typeof(bool));                    // .. -> args idx rele
                }
                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);                                // .. -> args idx ctx
                    _il.Emit(OpCodes.Ldstr, id);                              // .. -> args idx ctx id
                    _il.Emit(OpCodes.Ldstr, _context.CurrentNs);              // .. -> args idx ctx id ns
                    _il.Emit(OpCodes.Call, typeof(SqlEmiterUtil).GetTypeInfo()
                             .GetMethod(nameof(SqlEmiterUtil.EmiterFromId))); // .. -> args idx emiter
                }
                else
                {
                    throw new InvalidOperationException();
                }

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

            _il.Emit(OpCodes.Call, typeof(MacroManager).GetTypeInfo()
                     .GetMethod(nameof(MacroManager.Execute)));             // result<str>
            _il.Emit(OpCodes.Dup);                                          // result<str> x 2
            _il.Emit(OpCodes.Call, typeof(Result).GetTypeInfo()
                     .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)
            _il.Emit(OpCodes.Ret);                                          // [exit-returned]

            _il.MarkLabel(ifIsSuccess);                                     // ifIsSuccess:
            _il.Emit(OpCodes.Call, typeof(Result <string>).GetTypeInfo()
                     .GetMethod("get_" + nameof(Result <string> .Value)));  // str
            var strValue = _il.DeclareLocal(typeof(string));

            _il.Emit(OpCodes.Stloc, strValue);                              // [empty]
            _il.Emit(OpCodes.Ldloc_0);                                      // sb
            _il.Emit(OpCodes.Ldloc, strValue);                              // sb str
            _il.Emit(OpCodes.Call, typeof(StringBuilder)
                     .GetTypeInfo().GetMethod(nameof(StringBuilder.Append),
                                              new[] { typeof(string), }));  // sb+str
            _il.Emit(OpCodes.Pop);                                          // [empty]

            return(Result.Ok());
        }
Beispiel #6
0
        public override Result VisitIf([NotNull] IfContext context)
        {
            var coreSql = context.coreSql();
            var id      = NameUtil.GetFunctionName(coreSql);
            var result  = _context.TryGetEmiter(id, _context.CurrentNs);

            SqlEmiter emiter;

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

            var compileResult = emiter.EnsureCompiled(_context);

            if (compileResult.IsFailure)
            {
                return(compileResult);
            }

            return(new BoolVisitor(_il).Visit(context.boolExpression())
                   .OnSuccess(() =>
            {
                var ifSkip = _il.DefineLabel();
                _il.Emit(OpCodes.Ldc_I4_0);
                _il.Emit(OpCodes.Beq, ifSkip);

                _il.Emit(OpCodes.Ldarg_0);                                // ctx
                _il.Emit(OpCodes.Ldstr, id);                              // ctx id
                _il.Emit(OpCodes.Ldstr, _context.CurrentNs);              // ctx id ns
                _il.Emit(OpCodes.Call, typeof(SqlEmiterUtil).GetTypeInfo()
                         .GetMethod(nameof(SqlEmiterUtil.EmiterFromId))); // emiter
                _il.Emit(OpCodes.Ldarg_0);                                // emiter ctx
                _il.Emit(OpCodes.Ldarg_1);                                // emiter ctx obj
                _il.Emit(OpCodes.Call,                                    // result<str>
                         typeof(IfUtils).GetTypeInfo().GetMethod(nameof(IfUtils.ExecuteEmiter)));

                // convert result<str> to str
                _il.Emit(OpCodes.Dup);                                         // result<str> x 2
                _il.Emit(OpCodes.Call, typeof(Result).GetTypeInfo()
                         .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)
                _il.Emit(OpCodes.Ret);                                         // [exit-returned]

                _il.MarkLabel(ifIsSuccess);                                    // ifIsSuccess:
                _il.Emit(OpCodes.Call, typeof(Result <string>).GetTypeInfo()
                         .GetMethod("get_" + nameof(Result <string> .Value))); // str

                var strLocal = _il.DeclareLocal(typeof(string));
                _il.Emit(OpCodes.Stloc, strLocal);
                _il.Emit(OpCodes.Ldloc_0);
                _il.Emit(OpCodes.Ldloc, strLocal);
                _il.Emit(OpCodes.Call,
                         typeof(StringBuilder).GetTypeInfo().GetMethod(nameof(StringBuilder.Append),
                                                                       new[] { typeof(string), })); // sb+str
                _il.Emit(OpCodes.Pop);
                _il.MarkLabel(ifSkip);
                return Result.Ok();
            }));
        }
Beispiel #7
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());
        }