private CsExpressionBuilder AddChildExpression(CsExpressionBuilder expression) { expression.Parent = expression.Parent ?? this.Parent; this.Children.Add(expression); return(expression); }
public CsExpressionBuilder CreateChildExpression() { var result = new CsExpressionBuilder(); return(AddChildExpression(result)); }
public static string GenerateFrameEngine(string nameSpace, string className, Action <CsScopedExpression, OpCodeMetaModel> binder = null, Func <string[]> usings = null) { if (usings == null) { usings = () => new[] { "System", "System.Collections.Generic", "System.IO", "System.Linq", "System.Reflection", "System.Reflection.Emit", "System.Text" }; } var builder = new CsExpressionBuilder().CreateScope(); builder.AddUsings(usings()); builder.AddPreBodyExpression("\r\n"); builder.AddNamespaceDeclaration(nameSpace); builder.AddPreBodyExpression("{\r\n"); builder.AddPostBodyExpression("}\r\n"); var classBuilder = builder.CreateChildExpression().CreateScope(); classBuilder.AddPreBodyExpression($"public class {className} : {nameof(IILEngine)}\r\n"); classBuilder.AddPreBodyExpression("{\r\n"); classBuilder.AddPostBodyExpression("}\r\n"); var classFieldsBuilder = classBuilder.CreateChildExpression().CreateScope(); classFieldsBuilder.AddPreBodyExpression($"{nameof(ILStackFrameFlowControlTarget)} flowControlTarget;\r\n"); classFieldsBuilder.AddPreBodyExpression($"{nameof(IILStackFrame)} frame;\r\n"); classFieldsBuilder.AddPreBodyExpression($"public {nameof(ILStackFrameFlowControlTarget)} FlowControlTarget {{ get => flowControlTarget; set => flowControlTarget = value; }}\r\n"); classFieldsBuilder.AddPreBodyExpression($"public {nameof(IILStackFrame)} StackFrame {{ get => frame; set => frame = value; }}\r\n"); classFieldsBuilder.AddPreBodyExpression($"public bool BreakOnDebug {{ get; set; }} = false;\r\n"); classFieldsBuilder.AddPreBodyExpression($"public bool ThrowOnException {{ get; set; }} = false;\r\n"); classFieldsBuilder.AddPreBodyExpression($"\r\n"); var methodBuilder = classBuilder.CreateChildExpression().CreateScope(); methodBuilder.AddPreBodyExpression($"public void ExecuteFrame({nameof(IILStackFrame)} frame)\r\n"); methodBuilder.AddPreBodyExpression("{\r\n"); methodBuilder.AddPostBodyExpression("}\r\n"); var methodBody = methodBuilder.CreateChildExpression().CreateScope(); methodBody.AddPreBodyExpression("this.frame = frame;\r\n"); methodBody.AddPreBodyExpression($"this.flowControlTarget = {nameof(ILStackFrameFlowControlTarget)}.{nameof(ILStackFrameFlowControlTarget.Inc)};\r\n"); methodBody.AddPreBodyExpression($"frame.{nameof(IILStackFrame.Reset)}();\r\n"); methodBody.AddPreBodyExpression("goto Inc;\r\n"); methodBody.AddPreBodyExpression("\r\n"); methodBody.AddPreBodyExpression("ReadNext:\r\n"); methodBody.AddPreBodyExpression($"frame.{nameof(IILStackFrame.ReadNext)}();\r\n"); methodBody.AddPreBodyExpression("\r\n"); methodBody.AddPreBodyExpression("short opCodeValue = frame.Code.Value;\r\n"); methodBody.AddPreBodyExpression("ExecuteOpCode(opCodeValue);\r\n"); methodBody.AddPreBodyExpression("\r\n"); methodBody.AddPreBodyExpression("switch(flowControlTarget)\r\n"); methodBody.AddPreBodyExpression("{\r\n"); methodBody.AddPostBodyExpression("}\r\n"); var methodSwitch = methodBody.CreateChildExpression(); var caseReadNext = methodSwitch.CreateScope(); caseReadNext.AddPreBodyExpression($"case {nameof(ILStackFrameFlowControlTarget)}.{nameof(ILStackFrameFlowControlTarget.ReadNext)}:\r\n"); caseReadNext.CreateScopedChild().AddPreBodyExpression("goto ReadNext;\r\n"); methodSwitch.CreateScope().AddPreBodyExpression($"case {nameof(ILStackFrameFlowControlTarget)}.{nameof(ILStackFrameFlowControlTarget.Inc)}:\r\n") .CreateScopedChild().AddPreBodyExpression("goto Inc;\r\n"); methodSwitch.CreateScope().AddPreBodyExpression($"case {nameof(ILStackFrameFlowControlTarget)}.{nameof(ILStackFrameFlowControlTarget.Ret)}:\r\n") .CreateScopedChild().AddPreBodyExpression("goto Ret;\r\n"); methodSwitch.CreateScope().AddPreBodyExpression($"case {nameof(ILStackFrameFlowControlTarget)}.{nameof(ILStackFrameFlowControlTarget.MoveNext)}:\r\n") .CreateScopedChild().AddPreBodyExpression("goto MoveNext;\r\n"); methodBody.AddPostBodyExpression("\r\n"); methodBody.AddPostBodyExpression("Inc:\r\n"); methodBody.AddPostBodyExpression($"frame.{nameof(IILStackFrame.Inc)}();\r\n"); methodBody.AddPostBodyExpression("\r\n"); methodBody.AddPostBodyExpression("MoveNext:\r\n"); methodBody.AddPostBodyExpression($"if (frame.{nameof(IILStackFrame.MoveNext)}()) goto ReadNext;\r\n"); methodBody.AddPostBodyExpression("\r\n"); methodBody.AddPostBodyExpression("Ret:\r\n"); methodBody.AddPostBodyExpression($"if (frame.{nameof(IILStackFrame.Exception)} != null && ThrowOnException) throw (frame.{nameof(IILStackFrame.Exception)});\r\n"); methodBody.AddPostBodyExpression($"frame.{nameof(IILStackFrame.ReturnResult)} = (frame.{nameof(IILStackFrame.Stack)}.Count > 0 && frame.{nameof(IILStackFrame.Exception)} == null) ? frame.{nameof(IILStackFrame.Stack)}.Pop() : null;\r\n"); var executeMethodBuilder = classBuilder.CreateChildExpression().CreateScope(); executeMethodBuilder.AddPreBodyExpression($"public void ExecuteOpCode(short opCodeValue)\r\n"); executeMethodBuilder.AddPreBodyExpression("{\r\n"); executeMethodBuilder.AddPostBodyExpression("}\r\n"); var notImplementedBuilder = classBuilder.CreateChildExpression().CreateScope(); notImplementedBuilder.AddPreBodyExpression($"public void NotImplemented()\r\n"); notImplementedBuilder.AddPreBodyExpression("{\r\n"); notImplementedBuilder.AddPostBodyExpression("}\r\n"); var notImplementedBody = notImplementedBuilder.CreateChildExpression().CreateScope(); notImplementedBody.AddPreBodyExpression($"frame.{nameof(IILStackFrame.Exception)} = new OpCodeNotImplementedException(frame.{nameof(IILStackFrame.Code)}.Value);\r\n"); notImplementedBody.AddPostBodyExpression("flowControlTarget = IlStackFrameFlowControlTarget.Ret;\r\n"); var executeMethodBody = executeMethodBuilder.CreateChildExpression().CreateScope(); executeMethodBody.AddPreBodyExpression("switch (opCodeValue)\r\n"); executeMethodBody.AddPreBodyExpression("{\r\n"); executeMethodBody.AddPostBodyExpression("}\r\n"); var models = OpCodeMetaModel.OpCodeMetas; if (binder == null) { Action <CsScopedExpression, OpCodeMetaModel> defaultBinder = (scope, model) => BindOpCodeHandler(scope, model); binder = defaultBinder; } foreach (var model in models) { var methodCase = executeMethodBody.CreateChildExpression().CreateScope(); methodCase.AddPreBodyExpression($"case unchecked((short)ILOpCodeValues.{model.ClrName}):\r\n"); var handleOpCodeExpression = methodCase.CreateChildExpression().CreateScope(); binder(handleOpCodeExpression, model); } var defaultCase = executeMethodBody.CreateChildExpression().CreateScope(); defaultCase.AddPreBodyExpression($"default:\r\n"); var handledefaultCaseExpression = defaultCase.CreateChildExpression().CreateScope(); handledefaultCaseExpression.AddPreBodyExpression($"NotImplemented();\r\n"); handledefaultCaseExpression.AddPreBodyExpression($"break;\r\n"); //handledefaultCaseExpression.AddPreBodyExpression($"goto Ret;\r\n"); var result = builder.ToString(); return(result); }