Skip to content

Commit 699f91c

Browse files
committed
Specialization of InstructionSpec into VmInstructionSpec and DataDirectiveSpec
1 parent 7921ab8 commit 699f91c

16 files changed

+110
-275
lines changed

mgs-spec-bank/datadirectives/base.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
flags: [~stringid_16]
44

55
- name: "StringID"
6-
operands: [int16]
6+
operands: [uint16]
77
flags: [stringid_16]
88

99
- name: "dw"
10-
operands: [int16]
10+
operands: [uint16]
1111
flags: []
1212

1313
- name: "Adr"
14-
operands: [int16]
14+
operands: [uint16]
1515
flags: []
1616

1717
- name: "dd"

src/MagesScriptTool/DataDirective.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/MagesScriptTool/DataDirectiveEncoding.cs

Lines changed: 0 additions & 112 deletions
This file was deleted.

src/MagesScriptTool/DataDirectiveSpec.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22

33
namespace MagesScriptTool;
44

5-
sealed class DataDirectiveSpec {
6-
public readonly string Name;
7-
public readonly ImmutableArray<OperandKind> Operands;
8-
9-
public DataDirectiveSpec(string name, ImmutableArray<OperandKind> operands) {
10-
Name = name;
11-
Operands = operands;
12-
}
5+
sealed class DataDirectiveSpec : InstructionSpec {
6+
public DataDirectiveSpec(string name, ImmutableArray<OperandKind> operands) : base(name, operands) {}
137
}

src/MagesScriptTool/DataDirectivesSpec.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

src/MagesScriptTool/InstructionEncoding.cs

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
using System.Collections.Immutable;
2+
using System.Diagnostics;
23
using System.Text;
4+
using System.Xml;
35

46
namespace MagesScriptTool;
57

68
sealed class InstructionEncoding {
7-
readonly ImmutableTree<byte, InstructionSpec> _tree;
8-
readonly ImmutableDictionary<string, InstructionSpec> _table;
9+
readonly ImmutableTree<byte, VmInstructionSpec> _opcodeTree;
10+
readonly ImmutableDictionary<string, InstructionSpec> _specTable;
911

10-
InstructionEncoding(ImmutableTree<byte, InstructionSpec> tree, ImmutableDictionary<string, InstructionSpec> table) {
11-
_tree = tree;
12-
_table = table;
12+
InstructionEncoding(ImmutableTree<byte, VmInstructionSpec> opcodeTree, ImmutableDictionary<string, InstructionSpec> specTable) {
13+
_opcodeTree = opcodeTree;
14+
_specTable = specTable;
1315
}
1416

1517
public void Encode(Stream stream, Instruction instruction) {
16-
InstructionSpec spec = _table[instruction.Name];
17-
PutBytes(stream, spec.Opcode.AsSpan());
18+
InstructionSpec spec = _specTable[instruction.Name];
19+
if (spec is VmInstructionSpec vmInstructionSpec) {
20+
PutBytes(stream, vmInstructionSpec.Opcode.AsSpan());
21+
}
1822
ImmutableArray<OperandKind> kinds = spec.Operands;
1923
ImmutableArray<ExpressionNode> operands = instruction.Operands;
2024
if (operands.Length != kinds.Length) {
@@ -32,9 +36,22 @@ public Instruction Decode(Stream stream) {
3236
foreach (OperandKind operandSpec in operandSpecs) {
3337
operands.Add(DecodeOperand(stream, operandSpec));
3438
}
35-
return new(spec.Name, [..operands]);
39+
return new (spec.Name, [..operands]);
3640
}
3741

42+
public Instruction Decode(Stream stream, string dataDirective) {
43+
DataDirectiveSpec spec = _specTable.GetValueOrDefault(dataDirective) switch {
44+
DataDirectiveSpec dataDirectiveSpec => dataDirectiveSpec,
45+
_ => throw new Exception($"Unrecognized data directive name: {dataDirective}")
46+
};
47+
48+
ImmutableArray<OperandKind> operandSpecs = spec.Operands;
49+
List<ExpressionNode> operands = [];
50+
foreach (OperandKind operandSpec in operandSpecs) {
51+
operands.Add(DecodeOperand(stream, operandSpec));
52+
}
53+
return new (spec.Name, [..operands]);
54+
}
3855
static void EncodeOperand(Stream stream, OperandKind kind, ExpressionNode operand) {
3956
switch (kind) {
4057
case OperandKind.Expr: {
@@ -45,6 +62,7 @@ static void EncodeOperand(Stream stream, OperandKind kind, ExpressionNode operan
4562
EncodeOperandInt8(stream, operand);
4663
break;
4764
}
65+
case OperandKind.UInt16:
4866
case OperandKind.Int16: {
4967
EncodeOperandInt16(stream, operand);
5068
break;
@@ -95,17 +113,17 @@ static void PutBytes(Stream stream, ReadOnlySpan<byte> data) {
95113
stream.Write(data);
96114
}
97115

98-
InstructionSpec DecodeOpcode(Stream stream) {
116+
VmInstructionSpec DecodeOpcode(Stream stream) {
99117
long start = stream.Position;
100-
ImmutableTree<byte, InstructionSpec> cursor = _tree;
118+
ImmutableTree<byte, VmInstructionSpec> cursor = _opcodeTree;
101119
while (true) {
102120
byte b = GetByte(stream);
103-
ImmutableTree<byte, InstructionSpec>? next = cursor[b];
121+
ImmutableTree<byte, VmInstructionSpec>? next = cursor[b];
104122
if (next is null) {
105123
throw new Exception($"Unrecognized instruction at {start}.");
106124
}
107125
cursor = next;
108-
if (cursor.Value is InstructionSpec opcodeSpec) {
126+
if (cursor.Value is VmInstructionSpec opcodeSpec) {
109127
return opcodeSpec;
110128
}
111129
}
@@ -115,6 +133,7 @@ static ExpressionNode DecodeOperand(Stream stream, OperandKind kind) {
115133
return kind switch {
116134
OperandKind.Expr => ExpressionEncoding.Decode(stream),
117135
OperandKind.Int8 => DecodeOperandInt8(stream),
136+
OperandKind.UInt16 => DecodeOperandUInt16(stream),
118137
OperandKind.Int16 => DecodeOperandInt16(stream),
119138
OperandKind.Int32 => DecodeOperandInt32(stream),
120139
OperandKind.Str => DecodeOperandStr(stream),
@@ -138,6 +157,13 @@ static ExpressionNodeNumber DecodeOperandInt8(Stream stream) {
138157
return new(value);
139158
}
140159

160+
static ExpressionNodeNumber DecodeOperandUInt16(Stream stream) {
161+
int value = 0;
162+
value |= GetByte(stream) << 0;
163+
value |= GetByte(stream) << 8;
164+
return new(value);
165+
}
166+
141167
static ExpressionNodeNumber DecodeOperandInt16(Stream stream) {
142168
int value = 0;
143169
value |= GetByte(stream) << 0;
@@ -169,10 +195,10 @@ static int SignExtend(int value, int length) {
169195
return value | ~(sign - 1);
170196
}
171197

172-
public static InstructionEncoding BuildFrom(ImmutableArray<InstructionSpec> opcodeSpecs) {
173-
ImmutableTree<byte, InstructionSpec> tree = BuildOpcodeTree(opcodeSpecs);
198+
public static InstructionEncoding BuildFrom(ImmutableArray<InstructionSpec> specs) {
199+
ImmutableTree<byte, VmInstructionSpec> tree = BuildOpcodeTree(specs);
174200
Dictionary<string, InstructionSpec> table = [];
175-
foreach (InstructionSpec spec in opcodeSpecs) {
201+
foreach (InstructionSpec spec in specs) {
176202
if (table.ContainsKey(spec.Name)) {
177203
throw new Exception($"Duplicate instruction name: {spec.Name}.");
178204
}
@@ -181,14 +207,16 @@ public static InstructionEncoding BuildFrom(ImmutableArray<InstructionSpec> opco
181207
return new(tree, table.ToImmutableDictionary());
182208
}
183209

184-
static ImmutableTree<byte, InstructionSpec> BuildOpcodeTree(ImmutableArray<InstructionSpec> specs) {
185-
Tree<byte, InstructionSpec> tree = new();
210+
static ImmutableTree<byte, VmInstructionSpec> BuildOpcodeTree(ImmutableArray<InstructionSpec> specs) {
211+
Tree<byte, VmInstructionSpec> tree = new();
186212
foreach (InstructionSpec spec in specs) {
187-
ImmutableArray<byte> opcode = spec.Opcode;
213+
if (spec is not VmInstructionSpec) continue;
214+
VmInstructionSpec vmInstructionSpec = (VmInstructionSpec)spec;
215+
ImmutableArray<byte> opcode = vmInstructionSpec.Opcode;
188216
if (opcode.Length == 0) {
189217
throw new Exception($"Empty opcode: {spec.Name}.");
190218
}
191-
Tree<byte, InstructionSpec> cursor = tree;
219+
Tree<byte, VmInstructionSpec> cursor = tree;
192220
for (int i = 0; i < opcode.Length; i++) {
193221
if (cursor.HasValue) {
194222
throw new Exception($"Duplicate opcode prefix: {Convert.ToHexString(opcode.AsSpan()[..i])}.");
@@ -201,7 +229,7 @@ static ImmutableTree<byte, InstructionSpec> BuildOpcodeTree(ImmutableArray<Instr
201229
if (cursor.HasValue) {
202230
throw new Exception($"Duplicate opcode: {Convert.ToHexString(opcode.AsSpan())}.");
203231
}
204-
cursor.Value = spec;
232+
cursor.Value = vmInstructionSpec;
205233
}
206234
return tree.ToImmutableTree();
207235
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace MagesScriptTool;
2+
enum InstructionKind {
3+
VM_INSTRUCTION,
4+
DATA_DIRECTIVE
5+
};

src/MagesScriptTool/InstructionSpec.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
namespace MagesScriptTool;
44

5-
sealed class InstructionSpec {
5+
abstract class InstructionSpec {
66
public readonly string Name;
7-
public readonly ImmutableArray<byte> Opcode;
87
public readonly ImmutableArray<OperandKind> Operands;
98

10-
public InstructionSpec(string name, ImmutableArray<byte> opcode, ImmutableArray<OperandKind> operands) {
9+
public InstructionSpec(string name, ImmutableArray<OperandKind> operands) {
1110
Name = name;
12-
Opcode = opcode;
1311
Operands = operands;
1412
}
1513
}

src/MagesScriptTool/OperandKind.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ enum OperandKind {
44
Expr,
55
UInt8,
66
Int8,
7+
UInt16,
78
Int16,
89
Int32,
910
Str,

0 commit comments

Comments
 (0)