Skip to content

Commit a316ee8

Browse files
committed
add a generator that generates src/gen/sl_vm_opcode_t.h from the DSL
1 parent 55c81a9 commit a316ee8

File tree

3 files changed

+64
-50
lines changed

3 files changed

+64
-50
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ local.mk
1111
src/init_exts.c
1212
src/lib/error_page.c
1313
src/CaseFolding-3.2.0.txt
14+
src/gen
1415
tmp

inc/slash/vm.h

+2-50
Original file line numberDiff line numberDiff line change
@@ -113,56 +113,6 @@ typedef struct sl_vm {
113113
}
114114
sl_vm_t;
115115

116-
enum {
117-
SL_OP_RAW,
118-
SL_OP_ECHO,
119-
SL_OP_ECHO_RAW,
120-
SL_OP_NOT,
121-
SL_OP_MOV,
122-
SL_OP_GET_OUTER,
123-
SL_OP_GET_IVAR,
124-
SL_OP_GET_CVAR,
125-
SL_OP_GET_CONST,
126-
SL_OP_GET_OBJECT_CONST,
127-
SL_OP_SET_OUTER,
128-
SL_OP_SET_IVAR,
129-
SL_OP_SET_CVAR,
130-
SL_OP_SET_CONST,
131-
SL_OP_SET_OBJECT_CONST,
132-
SL_OP_IMMEDIATE,
133-
SL_OP_SEND,
134-
SL_OP_SEND_SELF,
135-
SL_OP_JUMP,
136-
SL_OP_JUMP_IF,
137-
SL_OP_JUMP_UNLESS,
138-
SL_OP_CLASS,
139-
SL_OP_DEFINE,
140-
SL_OP_DEFINE_ON,
141-
SL_OP_LAMBDA,
142-
SL_OP_SELF,
143-
SL_OP_ARRAY,
144-
SL_OP_ARRAY_DUMP,
145-
SL_OP_DICT,
146-
SL_OP_RETURN,
147-
SL_OP_RANGE_IN,
148-
SL_OP_RANGE_EX,
149-
SL_OP_LINE_TRACE,
150-
SL_OP_ABORT,
151-
SL_OP_THROW,
152-
SL_OP_TRY,
153-
SL_OP_END_TRY,
154-
SL_OP_CATCH,
155-
SL_OP_YADA_YADA,
156-
SL_OP_BIND_METHOD,
157-
SL_OP_USE,
158-
SL_OP_USE_TOP_LEVEL,
159-
SL_OP_BUILD_STRING,
160-
161-
SL_OP__MAX_OPCODE
162-
};
163-
164-
typedef uint8_t sl_vm_opcode_t;
165-
166116
typedef struct sl_vm_inline_method_cache {
167117
uint32_t state;
168118
SLVAL klass;
@@ -180,6 +130,8 @@ typedef struct sl_vm_inline_constant_cache {
180130
}
181131
sl_vm_inline_constant_cache_t;
182132

133+
typedef size_t sl_vm_opcode_t;
134+
183135
typedef union sl_vm_insn {
184136
sl_vm_opcode_t opcode;
185137
void* threaded_opcode;

scripts/vm_generator.rb

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
class Operand
2+
attr_reader :type, :name
3+
4+
def initialize(type, name)
5+
@type, @name = type, name
6+
end
7+
end
8+
9+
class Instruction
10+
attr_reader :name, :operands, :code
11+
12+
def initialize(name, operands, code)
13+
@name, @operands, @code = name, operands, code
14+
end
15+
16+
def self.parse(str)
17+
first, *rest = str.lines.to_a
18+
19+
unless /\A(?<name>[A-Z_]+)\((?<args>.*)\)\Z/ =~ first
20+
raise "Syntax error on line: #{first.inspect}"
21+
end
22+
23+
operands = args.split(",").map { |arg|
24+
arg.strip.split
25+
}.map { |type, name|
26+
Operand.new(type, name)
27+
}
28+
29+
new(name, operands, rest.join)
30+
end
31+
end
32+
33+
source = File.read("src/vm_defn.inc")
34+
35+
# remove C-style /*...*/ comments
36+
source.gsub!(%r{/\* .*? \*/}x, "")
37+
38+
# remove C++-style // comments
39+
source.gsub!(%r{//.*$}, "")
40+
41+
# parse out instructions
42+
insns = source.lines.slice_before { |line|
43+
line =~ /^[A-Z_]+\(/
44+
}.map { |lines|
45+
lines.join
46+
}.reject { |section|
47+
section.empty?
48+
}.map { |section|
49+
Instruction.parse(section)
50+
}
51+
52+
# generate the opcode enum
53+
File.open("src/gen/opcode_enum.inc", "w") do |f|
54+
f.puts "enum {"
55+
insns.each_with_index do |insn, index|
56+
f.printf " SL_OP_%-16s = %2d,\n", insn.name, index
57+
end
58+
f.puts
59+
f.puts " SL_OP__MAX_OPCODE"
60+
f.puts "};"
61+
end

0 commit comments

Comments
 (0)