private static Result <EmitFunction> CompileCore( SdmapCompilerContext context, CoreSqlContext coreSql) { var fullName = NameUtil.GetFunctionName(coreSql); return(CoreSqlVisitor.CompileCore( coreSql, context, fullName)); }
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()); }
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(); })); }
private Result WriteMacroParameters(MacroParameterContext[] parameterCtxs) { for (var i = 0; i < parameterCtxs.Length; ++i) { var parameter = parameterCtxs[i]; if (parameter.nsSyntax() != null) { _writer.Write( SqlTextUtil.ToCSharpString(parameter.nsSyntax().GetText())); } else if (parameter.STRING() != null) { var result = StringUtil.Parse(parameter.STRING().GetText()); if (result.IsFailure) { return(result); } _writer.Write(SqlTextUtil.ToCSharpString(result.Value)); } else if (parameter.NUMBER() != null) { // sdmap number are compatible with C# double _writer.Write(parameter.NUMBER().GetText()); } else if (parameter.DATE() != null) { var result = DateUtil.Parse(parameter.DATE().GetText()); if (result.IsFailure) { return(result); } var date = result.Value; _writer.Write( $"new DateTime({date.Year}, {date.Month}, {date.Day})"); } else if (parameter.Bool() != null) { // sdmap bool are compatible with C# bool _writer.Write(parameter.Bool().GetText()); } else if (parameter.unnamedSql() != null) { var parseTree = parameter.unnamedSql(); var id = NameUtil.GetFunctionName(parseTree); if (!_unnamedSqls.ContainsKey(id)) { _unnamedSqls[id] = (writer) => { return(Visit(parseTree.coreSql())); }; } _writer.Write($"{id}()"); } // every parameter should follow by a "," separator, // except last parameter. if (i < parameterCtxs.Length - 1) { _writer.Write(", "); } } _writer.WriteLine(");"); return(Result.Ok()); }
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()); }