public void Class() { var parser = new Parser(new Scanner("../../sources/for_unit_tests/class.exs")); parser.DoPostParseProcessing = true; parser.Parse(); var ast = parser.TopmostAst; var options = new ExpressoCompilerOptions{ LibraryPaths = new List<string>{""}, OutputPath = "../../test_executable", BuildType = BuildType.Debug | BuildType.Executable }; var emitter = new CSharpEmitter(parser, options); ast.AcceptWalker(emitter, null); var asm = emitter.AssemblyBuilder; var main_method = asm.GetModule("main.exe") .GetType("ExsMain") .GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Static); Assert.AreEqual(main_method.Name, "Main"); Assert.IsTrue(main_method.IsStatic); Assert.AreEqual(typeof(int), main_method.ReturnType); Assert.AreEqual(0, main_method.GetParameters().Length); //Assert.IsTrue(main_method.GetParameters().SequenceEqual(new []{typeof(string[])})); Console.Out.WriteLine("テスト実行"); Console.Out.WriteLine(main_method.ToString()); //main_method.Invoke(null, new object[]{}); }
public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx) { newEmitter.SetCollectionContainer("List<TItem>"); const string rootName = "ModelRoot"; newEmitter.SetRuntimeName("glTF", rootName); newEmitter.SetRuntimeName("glTF Property", "ExtraProperties"); newEmitter.SetRuntimeName("glTF Child of Root Property", "LogicalChildOfRoot"); newEmitter.SetRuntimeName("Sampler", "TextureSampler"); newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType"); newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType"); newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType"); newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PropertyPath"); newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode"); newEmitter.SetRuntimeName("orthographic-perspective", "CameraType"); newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode"); newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType"); newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode"); newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationFilter"); newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode"); newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapFilter"); var meshClass = ctx.FindClass("Mesh"); if (meshClass != null) { newEmitter.SetCollectionContainer(meshClass.UseField("primitives"), "ChildrenCollection<TItem,Mesh>"); } var animationClass = ctx.FindClass("Animation"); if (animationClass != null) { newEmitter.SetCollectionContainer(animationClass.UseField("channels"), "ChildrenCollection<TItem,Animation>"); newEmitter.SetCollectionContainer(animationClass.UseField("samplers"), "ChildrenCollection<TItem,Animation>"); } var classes = ctx.Classes.ToArray(); var fields = classes .SelectMany(item => item.Fields) .ToArray(); foreach (var f in fields) { if (f.FieldType is ArrayType atype) { if (atype.ItemType is ClassType ctype) { if (ctype.BaseClass != null && ctype.BaseClass.PersistentName == "glTF Child of Root Property") { newEmitter.SetCollectionContainer(f, $"ChildrenCollection<TItem,{rootName}>"); } } } } }
/// <summary> /// Generates types for sequence fields /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="def">The sequence definition</param> private void _generateSequenceFields(CSharpEmitter emitter, SequenceDefinition def) { foreach (var field in def.Fields) { var effectiveFieldName = _sequenceFieldEffectiveNameForType(field); _generateDefinition(emitter, null, effectiveFieldName, field.Type); } }
/// <summary> /// Generates the option types for a choice /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="def">The choice definition</param> private void _generateChoiceOptions(CSharpEmitter emitter, string name, ChoiceDefinition def) { _generateChoiceOptionWrappers(emitter, name, def); foreach (var field in def.Fields) { _generateChoiceOption(emitter, name, field); } }
/// <summary> /// Compiles and assemble into an assembly object. /// </summary> /// <returns>An assembly object.</returns> /// <param name="filePath">Path to the file which will be compiled.</param> /// <param name="options">Compiler options to use for the compilation.</param> public static Assembly CompileToAssembly(string filePath, ExpressoCompilerOptions options) { var parser = new Parser(new Scanner(filePath)); parser.DoPostParseProcessing = true; parser.Parse(); var ast = parser.TopmostAst; var emitter = new CSharpEmitter(parser, options); ast.AcceptWalker(emitter, new CSharpEmitterContext()); return emitter.AssemblyBuilder; }
/// <summary> /// Generates an array type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The primitive definition</param> /// <param name="root">True if this is the root type, false otherwise</param> private void _generatePrimitiveType(CSharpEmitter emitter, string typeName, string fieldName, PrimitiveDefinition def, bool root) { if (root) { typeName = _getDefinitionName(typeName, fieldName, def); var elementTypeName = _getDefinitionName(null, null, def); using (var wrapper = _generateWrapperType(emitter, typeName, elementTypeName)) { } } }
/// <summary> /// Generates a bit string type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The bitstring definition</param> private void _generateBitString(CSharpEmitter emitter, string typeName, string fieldName, BitStringDefinition def) { typeName = _getDefinitionName(typeName, fieldName, def); using (var s = emitter.Struct(typeName)) { using (var bits = emitter.Enum("Bits", "byte")) { for (int i = 0; i < def.Bits.Length; i++) { var bit = def.Bits[i]; bits.EnumValue(_transformFieldName(bit.Name), bit.Index, i == def.Bits.Length - 1); } } s.WriteLine(); s.WriteLine("private BitString56 _bitstring;"); s.WriteLine(); s.WriteLineRaw("public byte Length { get { return _bitstring.Length; } }"); s.WriteLine(); s.WriteLine("public bool this[Bits bit] {{ get {{ return _bitstring[(int)bit]; }} }}"); s.WriteLine(); using (var cons = s.Constructor(typeName, new Parameter[] { new Parameter("BitString56", "bitstring") })) { cons.WriteLine("this._bitstring = bitstring;"); } s.WriteLine(); s.WriteLine("public {0} WithLength(byte length) {{ return new {0}(_bitstring.WithLength(length)); }}", typeName); s.WriteLine(); s.WriteLine("public {0} WithBit(Bits bit, bool set = true) {{ return new {0}(_bitstring.WithBit((int)bit, set)); }}", typeName); s.WriteLine(); s.StaticReadonlyField("Schema", "ISchema", "PrimitiveSchema.BitString56Schema"); s.WriteLine(); using (var load = s.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") })) { load.WriteLine("var temp = Value<BitString56>.Load(stream);"); load.WriteLine("return new {0}(temp);", typeName); } s.WriteLine(); using (var save = s.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") })) { save.WriteLine("Value<BitString56>.Save(sink, value._bitstring);"); } } }
/// <summary> /// Generates the tags enumeration for a choice /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="def">The choice definition</param> private void _generateChoiceTags(CSharpEmitter emitter, ChoiceDefinition def) { emitter.WriteLine(); using (var tagEmitter = emitter.Enum("Tags", "byte")) { for (int i = 0; i < def.Fields.Length; i++) { var field = def.Fields[i]; var fieldName2 = _transformFieldName(field.Name); tagEmitter.EnumValue(fieldName2, i, i == def.Fields.Length - 1); } } }
/// <summary> /// Generates an enumeration type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The enumeration definition</param> private void _generateEnumeration(CSharpEmitter emitter, string typeName, string fieldName, EnumerationDefinition def) { typeName = _getDefinitionName(typeName, fieldName, def); using (var e = emitter.Enum(typeName)) { for (int i = 0; i < def.Options.Length; i++) { var opt = def.Options[i]; var optName = _transformFieldName(opt.Name); e.EnumValue(optName, opt.Value, i == def.Options.Length - 1); } } }
/// <summary> /// Generates code for a named type /// </summary> /// <param name="type">The type to generate for</param> public void Generate(NamedType type) { string name = _transformTypeName(type.Name); string path = Path.Combine(_directory, name + ".cs"); using(var emitter = new CSharpEmitter(path)) { emitter.EmitUsing("System"); emitter.EmitUsing("BACnet.Types"); emitter.EmitUsing("BACnet.Types.Schemas"); emitter.WriteLine(); using(var ns = emitter.Namespace(_namespace)) { _generateDefinition(ns, name, null, type.Definition, true, null); } } }
/// <summary> /// If necessary, generates a wrapper for each non-sequence, non-choice option /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="choiceName">The name of the choice type</param> /// <param name="def">The choice definition</param> private void _generateChoiceOptionWrappers(CSharpEmitter emitter, string choiceName, ChoiceDefinition def) { foreach (var field in def.Fields) { bool needsWrapper = def.Fields.Any(f => _choiceOptionNeedsWrapper(f)); var fieldName = _transformFieldName(field.Name); var typeName = _getDefinitionName(null, fieldName, field.Type); if (needsWrapper) { emitter.WriteLine(); using (var wrapper = _generateWrapperType(emitter, fieldName + "Wrapper", typeName, choiceName, fieldName)) { } } } }
/// <summary> /// Generates code for a named type /// </summary> /// <param name="type">The type to generate for</param> public void Generate(NamedType type) { string name = _transformTypeName(type.Name); string path = Path.Combine(_directory, name + ".cs"); using (var emitter = new CSharpEmitter(path)) { emitter.EmitUsing("System"); emitter.EmitUsing("BACnet.Types"); emitter.EmitUsing("BACnet.Types.Schemas"); emitter.WriteLine(); using (var ns = emitter.Namespace(_namespace)) { _generateDefinition(ns, name, null, type.Definition, true, null); } } }
public static void EmitCodeFromSchema(string dstFile, SchemaType.Context ctx, IReadOnlyList <SchemaProcessor> extensions) { var newEmitter = new CSharpEmitter(); newEmitter.DeclareContext(ctx); foreach (var ext in extensions) { ext.PrepareTypes(newEmitter, ctx); } var textOut = newEmitter.EmitContext(ctx); var dstDir = _FindTargetDirectory(Constants.TargetProjectDirectory); var dstPath = System.IO.Path.Combine(dstDir, $"{dstFile}.cs"); System.IO.File.WriteAllText(dstPath, textOut); }
/// <summary> /// Generates an option type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The option definition</param> /// <param name="root">True if this is the root type, false otherwise</param> private void _generateOptionType(CSharpEmitter emitter, string typeName, string fieldName, OptionDefinition def, bool root) { if (root) { typeName = _getDefinitionName(typeName, fieldName, def); var elementTypeName = _getDefinitionName(null, "element", def); using (var wrapper = _generateWrapperType(emitter, typeName, elementTypeName)) { if (root) { _generateDefinition(wrapper, null, "element", def.ElementType); } } } if (!root) { _generateDefinition(emitter, null, fieldName, def.ElementType); } }
/// <summary> /// Generates a wrapper type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="name">The name of the wrapper type</param> /// <param name="wrappedType">The name of the type to wrap</param> /// <returns>The emitter for the type body</returns> private CSharpEmitter _generateWrapperType(CSharpEmitter emitter, string name, string wrappedType, string choiceBase = null, string tag = null) { var typeEmitter = choiceBase == null?emitter.Class(name) : emitter.Class(name, false, new string[] { choiceBase });; if (tag != null) { typeEmitter.OverrideProperty("Tag", "Tags", "return Tags." + tag + ";"); typeEmitter.WriteLine(); } typeEmitter.Property("Item", wrappedType, Access.Public); typeEmitter.WriteLine(); using (var cons = typeEmitter.Constructor(name, new Parameter[] { new Parameter(wrappedType, "item") })) { cons.WriteLine("this.Item = item;"); } typeEmitter.WriteLine(); typeEmitter.StaticReadonlyField("Schema", "ISchema", "Value<" + wrappedType + ">.Schema", @new: !string.IsNullOrEmpty(choiceBase)); typeEmitter.WriteLine(); using (var load = typeEmitter.StaticMethod("Load", name, new Parameter[] { new Parameter("IValueStream", "stream") }, @new: !string.IsNullOrEmpty(choiceBase))) { load.WriteLine("var temp = Value<" + wrappedType + ">.Load(stream);"); load.WriteLine("return new " + name + "(temp);"); } typeEmitter.WriteLine(); using (var save = typeEmitter.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(name, "value") })) { save.WriteLine("Value<" + wrappedType + ">.Save(sink, value.Item);"); } typeEmitter.WriteLine(); return(typeEmitter); }
/// <summary> /// Generates a definition /// </summary> /// <param name="name">The name of the type</param> /// <param name="def">The definition</param> private void _generateDefinition(CSharpEmitter emitter, string name, string fieldName, TypeDefinition def, bool root = false, string tag = null, string choiceBase = null) { switch (def.Type) { case DefinitionType.Enumeration: _generateEnumeration(emitter, name, fieldName, (EnumerationDefinition)def); break; case DefinitionType.BitString: _generateBitString(emitter, name, fieldName, (BitStringDefinition)def); break; case DefinitionType.Sequence: _generateSequence(emitter, name, fieldName, (SequenceDefinition)def, root, tag, choiceBase); break; case DefinitionType.Choice: _generateChoice(emitter, name, fieldName, (ChoiceDefinition)def, root); break; case DefinitionType.Array: _generateArrayType(emitter, name, fieldName, (ArrayDefinition)def, root); break; case DefinitionType.Option: _generateOptionType(emitter, name, fieldName, (OptionDefinition)def, root); break; case DefinitionType.Name: _generateNameType(emitter, name, fieldName, (NameDefinition)def, root); break; case DefinitionType.Primitive: _generatePrimitiveType(emitter, name, fieldName, (PrimitiveDefinition)def, root); break; } }
private static void ProcessSchema(string dstFile, SchemaType.Context ctx) { var newEmitter = new CSharpEmitter(); newEmitter.DeclareContext(ctx); newEmitter.SetCollectionContainer("List<TItem>"); const string rootName = "ModelRoot"; newEmitter.SetRuntimeName("glTF", rootName); newEmitter.SetRuntimeName("glTF Property", "ExtraProperties"); newEmitter.SetRuntimeName("glTF Child of Root Property", "LogicalChildOfRoot"); newEmitter.SetRuntimeName("Sampler", "TextureSampler"); newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType"); newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType"); newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType"); newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PropertyPath"); newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode"); newEmitter.SetRuntimeName("orthographic-perspective", "CameraType"); newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode"); newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType"); newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode"); newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationFilter"); newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode"); newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapFilter"); newEmitter.SetRuntimeName("KHR_materials_pbrSpecularGlossiness glTF extension", "MaterialPBRSpecularGlossiness"); newEmitter.SetRuntimeName("KHR_materials_unlit glTF extension", "MaterialUnlit"); newEmitter.SetRuntimeName("KHR_materials_clearcoat glTF extension", "MaterialClearCoat"); newEmitter.SetRuntimeName("KHR_materials_transmission glTF extension", "MaterialTransmission"); newEmitter.SetRuntimeName("KHR_xmp glTF extension", "XMPPacketsCollection"); newEmitter.SetRuntimeName("KHR_xmp node extension", "XMPPacketReference"); newEmitter.SetRuntimeName("light", "PunctualLight"); newEmitter.SetRuntimeName("light/spot", "PunctualLightSpot"); newEmitter.SetRuntimeName("KHR_texture_transform textureInfo extension", "TextureTransform"); newEmitter.SetRuntimeName("MSFT_texture_dds extension", "TextureDDS"); newEmitter.SetRuntimeName("EXT_texture_webp glTF extension", "TextureWEBP"); newEmitter.SetRuntimeName("KHR_texture_basisu glTF extension", "TextureKTX2"); var classes = ctx.Classes.ToArray(); var fields = classes.SelectMany(item => item.Fields).ToArray(); var meshClass = ctx.FindClass("Mesh"); if (meshClass != null) { newEmitter.SetCollectionContainer(meshClass.UseField("primitives"), "ChildrenCollection<TItem,Mesh>"); } var animationClass = ctx.FindClass("Animation"); if (animationClass != null) { newEmitter.SetCollectionContainer(animationClass.UseField("channels"), "ChildrenCollection<TItem,Animation>"); newEmitter.SetCollectionContainer(animationClass.UseField("samplers"), "ChildrenCollection<TItem,Animation>"); } foreach (var f in fields) { if (f.FieldType is ArrayType atype) { if (atype.ItemType is ClassType ctype) { if (ctype.BaseClass != null && ctype.BaseClass.PersistentName == "glTF Child of Root Property") { newEmitter.SetCollectionContainer(f, $"ChildrenCollection<TItem,{rootName}>"); } } } } var textOut = newEmitter.EmitContext(ctx); var dstDir = _FindTargetDirectory(Constants.TargetProjectDirectory); var dstPath = System.IO.Path.Combine(dstDir, $"{dstFile}.cs"); System.IO.File.WriteAllText(dstPath, textOut); }
/// <summary> /// Generates a choice option /// </summary> /// <param name="field">The field to generate the option for</param> private void _generateChoiceOption(CSharpEmitter emitter, string choiceName, FieldDefinition field) { var tag = _transformFieldName(field.Name); _generateDefinition(emitter, null, field.Name, field.Type, false, tag, choiceName); }
/// <summary> /// Generates a sequence type /// </summary> /// <param name="typeName">The name of the type</param> /// <param name="def">The sequence definition</param> private void _generateSequence(CSharpEmitter emitter, string typeName, string fieldName, SequenceDefinition def, bool root = false, string tag = null, string choiceBase = null) { string[] bases = choiceBase == null ? new string[0] { } : new string[] { choiceBase }; typeName = _getDefinitionName(typeName, fieldName, def); using (var cls = emitter.Class(typeName, false, bases)) { if (tag != null) { cls.OverrideProperty("Tag", "Tags", "return Tags." + tag + ";"); cls.WriteLine(); } foreach (var field in def.Fields) { var fieldName2 = _transformFieldName(field.Name); var typeName2 = _sequenceFieldTypeName(field); cls.Property(fieldName2, typeName2); cls.WriteLine(); } var cparams = def.Fields.Select(f => new Parameter( _sequenceFieldTypeName(f), _fieldNameToTempName(f.Name))) .ToArray(); using (var cons = cls.Constructor(typeName, cparams, Access.Public)) { foreach (var field in def.Fields) { cons.WriteLine("this.{0} = {1};", _transformFieldName(field.Name), _fieldNameToTempName(field.Name)); } } cls.WriteLine(); var schemaStr = "new SequenceSchema(false, " + Environment.NewLine + string.Join("," + Environment.NewLine, def.Fields.Select(f => cls.IndentString(1) + "new FieldSchema(\"" + _transformFieldName(f.Name) + "\", " + f.Tag + ", Value<" + _sequenceFieldTypeName(f) + ">.Schema)").ToArray()) + ")"; cls.StaticReadonlyField("Schema", "ISchema", schemaStr, @new: !string.IsNullOrEmpty(choiceBase)); cls.WriteLine(); using (var load = cls.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") }, @new: !string.IsNullOrEmpty(choiceBase))) { load.WriteLine("stream.EnterSequence();"); foreach (var field in def.Fields) { load.WriteLine("var {0} = Value<{1}>.Load(stream);", _fieldNameToTempName(field.Name), _sequenceFieldTypeName(field)); } load.WriteLine("stream.LeaveSequence();"); load.WriteLine("return new " + typeName + "(" + string.Join(", ", def.Fields.Select(f => _fieldNameToTempName(f.Name)).ToArray()) + ");"); } cls.WriteLine(); using (var save = cls.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") })) { save.WriteLine("sink.EnterSequence();"); foreach (var field in def.Fields) { save.WriteLine("Value<{0}>.Save(sink, value.{1});", _sequenceFieldTypeName(field), _transformFieldName(field.Name)); } save.WriteLine("sink.LeaveSequence();"); } if (root) { _generateSequenceFields(cls, def); } } if (!root) { _generateSequenceFields(emitter, def); } }
/// <summary> /// Generates a wrapper type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="name">The name of the wrapper type</param> /// <param name="wrappedType">The name of the type to wrap</param> /// <returns>The emitter for the type body</returns> private CSharpEmitter _generateWrapperType(CSharpEmitter emitter, string name, string wrappedType, string choiceBase = null, string tag = null) { var typeEmitter = choiceBase == null ? emitter.Class(name) : emitter.Class(name, false, new string[] { choiceBase });; if(tag != null) { typeEmitter.OverrideProperty("Tag", "Tags", "return Tags." + tag + ";"); typeEmitter.WriteLine(); } typeEmitter.Property("Item", wrappedType, Access.Public); typeEmitter.WriteLine(); using (var cons = typeEmitter.Constructor(name, new Parameter[] { new Parameter(wrappedType, "item") })) { cons.WriteLine("this.Item = item;"); } typeEmitter.WriteLine(); typeEmitter.StaticReadonlyField("Schema", "ISchema", "Value<" + wrappedType + ">.Schema", @new:!string.IsNullOrEmpty(choiceBase)); typeEmitter.WriteLine(); using (var load = typeEmitter.StaticMethod("Load", name, new Parameter[] { new Parameter("IValueStream", "stream") }, @new: !string.IsNullOrEmpty(choiceBase))) { load.WriteLine("var temp = Value<" + wrappedType + ">.Load(stream);"); load.WriteLine("return new " + name + "(temp);"); } typeEmitter.WriteLine(); using (var save = typeEmitter.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(name, "value") })) { save.WriteLine("Value<" + wrappedType + ">.Save(sink, value.Item);"); } typeEmitter.WriteLine(); return typeEmitter; }
/// <summary> /// Generates a choice type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The choice definition</param> private void _generateChoice(CSharpEmitter emitter, string typeName, string fieldName, ChoiceDefinition def, bool root = false) { typeName = _getDefinitionName(typeName, fieldName, def); if (!root) { _generateChoiceTags(emitter, def); emitter.WriteLine(); } using (var cls = emitter.Class(typeName, true)) { cls.AbstractProperty("Tag", "Tags", Access.Public); foreach (var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); var valueTypeName = _getDefinitionName(null, field.Name, field.Type); cls.WriteLine(); cls.Property("Is" + tag, "bool", "return this.Tag == Tags." + tag + ";"); cls.WriteLine(); cls.Property("As" + tag, valueTypeName, _choiceOptionNeedsWrapper(field) ? "return ((" + optionTypeName + ")this).Item;" : "return (" + optionTypeName + ")this;"); cls.WriteLine(); Parameter[] parameters = _getChoiceOptionForwardedParameters(field); using (var method = cls.StaticMethod("New" + tag, typeName, parameters)) { var paramsArr = parameters.Select(p => p.Name).ToArray(); var paramsStr = string.Join(", ", paramsArr); method.WriteLine("return new " + optionTypeName + "(" + paramsStr + ");"); } } cls.WriteLine(); var schemaStr = "new ChoiceSchema(false, " + Environment.NewLine + string.Join("," + Environment.NewLine, def.Fields.Select(f => cls.IndentString(1) + "new FieldSchema(\"" + _transformFieldName(f.Name) + "\", " + f.Tag + ", Value<" + _getDefinitionName(null, f.Name, f.Type) + ">.Schema)").ToArray()) + ")"; cls.StaticReadonlyField("Schema", "ISchema", schemaStr); cls.WriteLine(); using (var load = cls.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") })) { load.WriteLine("{0} ret = null;", typeName); load.WriteLine("Tags tag = (Tags)stream.EnterChoice();"); using (var sw = load.Switch("tag")) { foreach (var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); sw.Case("Tags." + tag); sw.WriteLine("ret = Value<{0}>.Load(stream);", optionTypeName); sw.Break(); } sw.Default(); sw.WriteLine("throw new Exception();"); sw.Indent--; } load.WriteLine("stream.LeaveChoice();"); load.WriteLine("return ret;"); } cls.WriteLine(); using (var save = cls.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") })) { save.WriteLine("sink.EnterChoice((byte)value.Tag);"); using (var sw = save.Switch("value.Tag")) { foreach (var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); sw.Case("Tags." + tag); sw.WriteLine("Value<{0}>.Save(sink, ({0})value);", optionTypeName); sw.Break(); } sw.Default(); sw.WriteLine("throw new Exception();"); sw.Indent--; } save.WriteLine("sink.LeaveChoice();"); } if (root) { _generateChoiceTags(cls, def); _generateChoiceOptions(cls, typeName, def); } } if (!root) { _generateChoiceOptions(emitter, typeName, def); } }
/// <summary> /// Generates a choice type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The choice definition</param> private void _generateChoice(CSharpEmitter emitter, string typeName, string fieldName, ChoiceDefinition def, bool root = false) { typeName = _getDefinitionName(typeName, fieldName, def); if (!root) { _generateChoiceTags(emitter, def); emitter.WriteLine(); } using(var cls = emitter.Class(typeName, true)) { cls.AbstractProperty("Tag", "Tags", Access.Public); foreach(var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); var valueTypeName = _getDefinitionName(null, field.Name, field.Type); cls.WriteLine(); cls.Property("Is" + tag, "bool", "return this.Tag == Tags." + tag + ";"); cls.WriteLine(); cls.Property("As" + tag, valueTypeName, _choiceOptionNeedsWrapper(field) ? "return ((" + optionTypeName + ")this).Item;" : "return (" + optionTypeName + ")this;"); cls.WriteLine(); Parameter[] parameters = _getChoiceOptionForwardedParameters(field); using(var method = cls.StaticMethod("New" + tag, typeName, parameters)) { var paramsArr = parameters.Select(p => p.Name).ToArray(); var paramsStr = string.Join(", ", paramsArr); method.WriteLine("return new " + optionTypeName + "(" + paramsStr + ");"); } } cls.WriteLine(); var schemaStr = "new ChoiceSchema(false, " + Environment.NewLine + string.Join("," + Environment.NewLine, def.Fields.Select(f => cls.IndentString(1) + "new FieldSchema(\"" + _transformFieldName(f.Name) + "\", " + f.Tag + ", Value<" + _getDefinitionName(null, f.Name, f.Type) + ">.Schema)").ToArray()) + ")"; cls.StaticReadonlyField("Schema", "ISchema", schemaStr); cls.WriteLine(); using (var load = cls.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") })) { load.WriteLine("{0} ret = null;", typeName); load.WriteLine("Tags tag = (Tags)stream.EnterChoice();"); using (var sw = load.Switch("tag")) { foreach(var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); sw.Case("Tags." + tag); sw.WriteLine("ret = Value<{0}>.Load(stream);", optionTypeName); sw.Break(); } sw.Default(); sw.WriteLine("throw new Exception();"); sw.Indent--; } load.WriteLine("stream.LeaveChoice();"); load.WriteLine("return ret;"); } cls.WriteLine(); using (var save = cls.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") })) { save.WriteLine("sink.EnterChoice((byte)value.Tag);"); using (var sw = save.Switch("value.Tag")) { foreach(var field in def.Fields) { var tag = _transformFieldName(field.Name); var optionTypeName = _choiceOptionNeedsWrapper(field) ? _transformFieldName(field.Name) + "Wrapper" : _getDefinitionName(null, field.Name, field.Type); sw.Case("Tags." + tag); sw.WriteLine("Value<{0}>.Save(sink, ({0})value);", optionTypeName); sw.Break(); } sw.Default(); sw.WriteLine("throw new Exception();"); sw.Indent--; } save.WriteLine("sink.LeaveChoice();"); } if (root) { _generateChoiceTags(cls, def); _generateChoiceOptions(cls, typeName, def); } } if (!root) { _generateChoiceOptions(emitter, typeName, def); } }
/// <summary> /// Generates types for sequence fields /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="def">The sequence definition</param> private void _generateSequenceFields(CSharpEmitter emitter, SequenceDefinition def) { foreach(var field in def.Fields) { var effectiveFieldName = _sequenceFieldEffectiveNameForType(field); _generateDefinition(emitter, null, effectiveFieldName, field.Type); } }
/// <summary> /// Generates a sequence type /// </summary> /// <param name="typeName">The name of the type</param> /// <param name="def">The sequence definition</param> private void _generateSequence(CSharpEmitter emitter, string typeName, string fieldName, SequenceDefinition def, bool root = false, string tag = null, string choiceBase = null) { string[] bases = choiceBase == null ? new string[0] { } : new string[] { choiceBase }; typeName = _getDefinitionName(typeName, fieldName, def); using(var cls = emitter.Class(typeName, false, bases)) { if(tag != null) { cls.OverrideProperty("Tag", "Tags", "return Tags." + tag + ";"); cls.WriteLine(); } foreach (var field in def.Fields) { var fieldName2 = _transformFieldName(field.Name); var typeName2 = _sequenceFieldTypeName(field); cls.Property(fieldName2, typeName2); cls.WriteLine(); } var cparams = def.Fields.Select(f => new Parameter( _sequenceFieldTypeName(f), _fieldNameToTempName(f.Name))) .ToArray(); using (var cons = cls.Constructor(typeName, cparams, Access.Public)) { foreach (var field in def.Fields) { cons.WriteLine("this.{0} = {1};", _transformFieldName(field.Name), _fieldNameToTempName(field.Name)); } } cls.WriteLine(); var schemaStr = "new SequenceSchema(false, " + Environment.NewLine + string.Join("," + Environment.NewLine, def.Fields.Select(f => cls.IndentString(1) + "new FieldSchema(\"" + _transformFieldName(f.Name) + "\", " + f.Tag + ", Value<" + _sequenceFieldTypeName(f) + ">.Schema)").ToArray()) + ")"; cls.StaticReadonlyField("Schema", "ISchema", schemaStr, @new:!string.IsNullOrEmpty(choiceBase)); cls.WriteLine(); using (var load = cls.StaticMethod("Load", typeName, new Parameter[] { new Parameter("IValueStream", "stream") }, @new:!string.IsNullOrEmpty(choiceBase))) { load.WriteLine("stream.EnterSequence();"); foreach(var field in def.Fields) { load.WriteLine("var {0} = Value<{1}>.Load(stream);", _fieldNameToTempName(field.Name), _sequenceFieldTypeName(field)); } load.WriteLine("stream.LeaveSequence();"); load.WriteLine("return new " + typeName + "(" + string.Join(", ", def.Fields.Select(f => _fieldNameToTempName(f.Name)).ToArray()) + ");"); } cls.WriteLine(); using (var save = cls.StaticMethod("Save", "void", new Parameter[] { new Parameter("IValueSink", "sink"), new Parameter(typeName, "value") })) { save.WriteLine("sink.EnterSequence();"); foreach (var field in def.Fields) { save.WriteLine("Value<{0}>.Save(sink, value.{1});", _sequenceFieldTypeName(field), _transformFieldName(field.Name)); } save.WriteLine("sink.LeaveSequence();"); } if (root) _generateSequenceFields(cls, def); } if (!root) _generateSequenceFields(emitter, def); }
/// <summary> /// Generates an enumeration type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The enumeration definition</param> private void _generateEnumeration(CSharpEmitter emitter, string typeName, string fieldName, EnumerationDefinition def) { typeName = _getDefinitionName(typeName, fieldName, def); using(var e = emitter.Enum(typeName)) { for(int i = 0; i < def.Options.Length; i++) { var opt = def.Options[i]; var optName = _transformFieldName(opt.Name); e.EnumValue(optName, opt.Value, i == def.Options.Length - 1); } } }
/// <summary> /// Generates an option type /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="typeName">The name of the type</param> /// <param name="def">The option definition</param> /// <param name="root">True if this is the root type, false otherwise</param> private void _generateOptionType(CSharpEmitter emitter, string typeName, string fieldName, OptionDefinition def, bool root) { if(root) { typeName = _getDefinitionName(typeName, fieldName, def); var elementTypeName = _getDefinitionName(null, "element", def); using (var wrapper = _generateWrapperType(emitter, typeName, elementTypeName)) { if(root) { _generateDefinition(wrapper, null, "element", def.ElementType); } } } if (!root) _generateDefinition(emitter, null, fieldName, def.ElementType); }
/// <summary> /// Generates a definition /// </summary> /// <param name="name">The name of the type</param> /// <param name="def">The definition</param> private void _generateDefinition(CSharpEmitter emitter, string name, string fieldName, TypeDefinition def, bool root = false, string tag = null, string choiceBase = null) { switch(def.Type) { case DefinitionType.Enumeration: _generateEnumeration(emitter, name, fieldName, (EnumerationDefinition)def); break; case DefinitionType.BitString: _generateBitString(emitter, name, fieldName, (BitStringDefinition)def); break; case DefinitionType.Sequence: _generateSequence(emitter, name, fieldName, (SequenceDefinition)def, root, tag, choiceBase); break; case DefinitionType.Choice: _generateChoice(emitter, name, fieldName, (ChoiceDefinition)def, root); break; case DefinitionType.Array: _generateArrayType(emitter, name, fieldName, (ArrayDefinition)def, root); break; case DefinitionType.Option: _generateOptionType(emitter, name, fieldName, (OptionDefinition)def, root); break; case DefinitionType.Name: _generateNameType(emitter, name, fieldName, (NameDefinition)def, root); break; case DefinitionType.Primitive: _generatePrimitiveType(emitter, name, fieldName, (PrimitiveDefinition)def, root); break; } }
/// <summary> /// If necessary, generates a wrapper for each non-sequence, non-choice option /// </summary> /// <param name="emitter">The emitter to write to</param> /// <param name="choiceName">The name of the choice type</param> /// <param name="def">The choice definition</param> private void _generateChoiceOptionWrappers(CSharpEmitter emitter, string choiceName, ChoiceDefinition def) { foreach(var field in def.Fields) { bool needsWrapper = def.Fields.Any(f => _choiceOptionNeedsWrapper(f)); var fieldName = _transformFieldName(field.Name); var typeName = _getDefinitionName(null, fieldName, field.Type); if (needsWrapper) { emitter.WriteLine(); using (var wrapper = _generateWrapperType(emitter, fieldName + "Wrapper", typeName, choiceName, fieldName)) { } } } }
public void SimpleLiterals() { var parser = new Parser(new Scanner("../../sources/for_unit_tests/simple_literals.exs")); parser.DoPostParseProcessing = true; parser.Parse(); var ast = parser.TopmostAst; var options = new ExpressoCompilerOptions{ LibraryPaths = new List<string>{""}, OutputPath = "../../test_executable", BuildType = BuildType.Debug | BuildType.Executable }; var emitter = new CSharpEmitter(parser, options); ast.AcceptWalker(emitter, null); var asm = emitter.AssemblyBuilder; var main_method = asm.GetModule("main.exe") .GetType("ExsMain") .GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Static); Assert.AreEqual(main_method.Name, "Main"); Assert.IsTrue(main_method.IsStatic); Assert.AreEqual(typeof(void), main_method.ReturnType); Assert.AreEqual(0, main_method.GetParameters().Length); }