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()); }
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()); }