private OpCodeKb(OpCodeFamilyKb familyKb, OpCode? opcode) { FamilyKb = familyKb; _opCode = opcode; Tags = new HashSet<String>(); Meta = new Dictionary<String, String>(); Fields = new Dictionary<String, FieldSpec>(); Props = new Dictionary<String, PropertySpec>(); Prefixes = new Dictionary<String, PrefixSpec>(); }
private OpCodeKb(OpCodeFamilyKb familyKb, OpCode?opcode) { FamilyKb = familyKb; _opCode = opcode; Tags = new HashSet <String>(); Meta = new Dictionary <String, String>(); Fields = new Dictionary <String, FieldSpec>(); Props = new Dictionary <String, PropertySpec>(); Prefixes = new Dictionary <String, PrefixSpec>(); }
public OpCodeKb(OpCodeFamilyKb familyKb, OpCode opcode) : this(familyKb, (OpCode?)opcode) { }
public OpCodeKb(OpCodeFamilyKb familyKb) : this(familyKb, null) { }
private PropertySpec UniteSubSpecsForProp(OpCodeFamilyKb fkb, String pname) { // 1. Create a property spec var pspecs = fkb.SubSpecs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Props.Values.SingleOrDefault(f => f.Name == pname) ?? new PropertySpec{Name = pname}); var united = new PropertySpec(); united.Name = pname; // 2. Find out an unified type (it should be specified at least once and every time the same) var ptypes = pspecs.Values.Select(v => v.Type); var ptype = ptypes.Where(v => v != null).Distinct().Single(); united.Type = ptype; // 3. Normalize getters (setters ain't supported) for every opcode (replace null with default(T)) foreach (var spec in pspecs.Values) { var init = spec.Getter; if (init.IsNullOrEmpty()) { spec.Getter = "default(" + ptype.GetCSharpRef(ToCSharpOptions.ForCodegen) + ")"; } } // 4. Now assemble all initializers into a single language construct (setters ain't supported)! var getters = pspecs.Where(kvp => kvp.Value.Getter.IsNeitherNullNorEmpty()) .GroupBy(kvp => kvp.Value.Getter, kvp => kvp.Key); (getters.Count() >= 1).AssertTrue(); // 4.1. There's only 1 possible opcode => 1 possible getter // or maybe all getters for different opcodes are the same. // This means that we can reuse its expression and just return it. EZ! if (getters.Count() == 1) { var getterCode = getters.Single().Key; if (!getterCode.EndsWith(";")) getterCode = getterCode + ";"; if (!getterCode.StartsWith("return") && !getterCode.Contains(Environment.NewLine)) getterCode = "return " + getterCode; united.Getter = getterCode; } // 4.2. There are multiple distinct getters // Thus, we're forced to implement a switch depending on the opcode. // Default will crash the switch since we're unprepared to it. else { var getter = new StringBuilder(); getter.AppendLine(String.Format("switch(({0})OpSpec.OpCode.Value)", typeof(UInt16).GetCSharpRef(ToCSharpOptions.ForCodegen))); getter.AppendLine("{"); foreach (var getterClause in getters) { foreach (var opcode in getterClause) { var @case = "case " + opcode.GetCSharpByteSequence() + ":"; @case = @case + " //" + opcode.Name; getter.AppendLine(@case.Indent()); } var getterCode = getterClause.Key; if (!getterCode.EndsWith(";")) getterCode = getterCode + ";"; if (!getterCode.StartsWith("return") && !getterCode.Contains(Environment.NewLine)) getterCode = "return " + getterCode; getter.AppendLine(getterCode.Indent().Indent()); } getter.AppendLine("default:".Indent()); var throwOnUnknown = String.Format("throw {0}.Fail();", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen)); getter.AppendLine(throwOnUnknown.Indent().Indent()); getter.AppendLine("}"); united.Getter = getter.ToString(); } // 5. Setters ain't supported since they weren't necessary var setters = pspecs.Where(kvp => kvp.Value.Setter.IsNeitherNullNorEmpty()) .GroupBy(kvp => kvp.Value.Setter, kvp => kvp.Key); setters.AssertCount(0); return united; }
private FieldSpec UniteSubSpecsForField(OpCodeFamilyKb fkb, String fname) { // 1. Create a field spec var fspecs = fkb.SubSpecs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Fields.Values.SingleOrDefault(f => f.Name == fname) ?? new FieldSpec{Name = fname}); var united = new FieldSpec(); united.Name = fname; // 2. Find out an unified type (it should be specified at least once and every time the same) var ftypes = fspecs.Values.Select(v => v.Type); var ftype = ftypes.Where(v => v != null).Distinct().Single(); united.Type = ftype; // 3. Normalize initializers for every opcode (replace null with default(T)) foreach (var spec in fspecs.Values) { var init = spec.Initializer; if (init.IsNullOrEmpty()) { spec.Initializer = "default(" + ftype.GetCSharpRef(ToCSharpOptions.ForCodegen) + ")"; } } // 4. Now assemble all initializers into a single language construct var initGroups = fspecs.Where(kvp => kvp.Value.Initializer.IsNeitherNullNorEmpty()) .GroupBy(kvp => kvp.Value.Initializer, kvp => kvp.Key); (initGroups.Count() >= 1).AssertTrue(); // 4.1. There's only 1 possible opcode => 1 possible initializer // or maybe all initializers for different opcodes are the same. // This means that we can reuse its expression and assign the value to the field. EZ! if (initGroups.Count() == 1) { var initCode = initGroups.Single().Key; if (!initCode.EndsWith(";")) initCode = initCode + ";"; initCode = fname + " = " + initCode; united.Initializer = (initCode + Environment.NewLine); } // 4.2. There are multiple distinct initializers // Thus, we're forced to implement a switch depending on the opcode. // Default will crash the switch since we're unprepared to it. else { var init = new StringBuilder(); init.AppendLine(String.Format("switch(({0})OpSpec.OpCode.Value)", typeof(UInt16).GetCSharpRef(ToCSharpOptions.ForCodegen))); init.AppendLine("{"); foreach (var initGroup in initGroups) { foreach (var opcode in initGroup) { var @case = "case " + opcode.GetCSharpByteSequence() + ":"; @case = @case + " //" + opcode.Name; init.AppendLine(@case.Indent()); } var initCode = initGroup.Key; if (!initCode.EndsWith(";")) initCode = initCode + ";"; initCode = fname + " = " + initCode; init.AppendLine(initCode.Indent().Indent()); init.AppendLine("break;".Indent().Indent()); } init.AppendLine("default:".Indent()); var throwOnUnknown = String.Format("throw {0}.Fail();", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen)); init.AppendLine(throwOnUnknown.Indent().Indent()); init.AppendLine("}"); united.Initializer = init.ToString(); } return united; }