emfrp 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +45 -12
- data/bin/emfrp +4 -1
- data/examples/LCDClock/LCDClock.mfrp +93 -93
- data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
- data/examples/LCDClock/README.md +24 -24
- data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
- data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
- data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
- data/lib/emfrp/compile/c/alloc.rb +200 -200
- data/lib/emfrp/compile/c/codegen.rb +18 -18
- data/lib/emfrp/compile/c/codegen_context.rb +218 -218
- data/lib/emfrp/compile/c/monofy.rb +185 -185
- data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
- data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
- data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
- data/lib/emfrp/compile_error.rb +95 -95
- data/lib/emfrp/interpreter/command_manager.rb +367 -367
- data/lib/emfrp/interpreter/evaluater.rb +146 -146
- data/lib/emfrp/interpreter/file_loader.rb +52 -52
- data/lib/emfrp/interpreter/interpreter.rb +200 -195
- data/lib/emfrp/parser/expression.rb +386 -386
- data/lib/emfrp/parser/misc.rb +184 -184
- data/lib/emfrp/parser/newnode_convert.rb +72 -72
- data/lib/emfrp/parser/operator.rb +25 -25
- data/lib/emfrp/parser/parser.rb +150 -150
- data/lib/emfrp/parser/parsing_error.rb +49 -49
- data/lib/emfrp/parser/toplevel.rb +555 -555
- data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
- data/lib/emfrp/syntax.rb +171 -171
- data/lib/emfrp/typing/typing_error.rb +47 -47
- data/lib/emfrp/typing/union_type.rb +197 -197
- data/lib/emfrp/version.rb +1 -1
- data/mfrp_include/Std.mfrp +122 -122
- data/tests/Rakefile +8 -8
- data/tests/Rakefile.common +27 -27
- data/tests/command/Rakefile +2 -2
- data/tests/command/ReplaceNode.mfrp +39 -39
- data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
- data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
- data/tests/compiler/ComplexDataType/Rakefile +2 -2
- data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
- data/tests/compiler/ComplexDataType/in.txt +5 -5
- data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
- data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
- data/tests/compiler/LCDClock/Rakefile +2 -2
- data/tests/compiler/LCDClock/expected_out.txt +0 -0
- data/tests/compiler/LCDClock/in.txt +0 -0
- data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
- data/tests/compiler/LCDPositioner/Rakefile +2 -2
- data/tests/compiler/LCDPositioner/graph.dot +0 -0
- data/tests/compiler/LCDPositioner/graph.png +0 -0
- data/tests/compiler/Rakefile +8 -8
- data/tests/compiler/Rakefile.common +23 -23
- data/tests/compiler/UseData/Rakefile +2 -2
- data/tests/compiler/UseData/UseData.mfrp +8 -8
- data/tests/compiler/UseSubModule/Rakefile +2 -2
- data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
- data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
- data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
- data/tests/core/FromAnnotation.mfrp +18 -18
- data/tests/core/Last.mfrp +10 -10
- data/tests/core/Rakefile +2 -2
- data/tests/core/TypingTest.mfrp +11 -11
- data/tests/core/WithoutInputs.mfrp +19 -19
- data/tests/load_time_error/Rakefile +32 -32
- data/tests/load_time_error/TypeMismatch.mfrp +4 -4
- metadata +3 -3
@@ -1,364 +1,364 @@
|
|
1
|
-
require 'emfrp/syntax'
|
2
|
-
require 'emfrp/compile/c/syntax_exp_codegen'
|
3
|
-
|
4
|
-
module Emfrp
|
5
|
-
class Top
|
6
|
-
def codegen(ct, ar)
|
7
|
-
self[:dict][:itype_space].each do |k, v|
|
8
|
-
v.get.struct_gen(ct)
|
9
|
-
v.get.constructor_gen(ct)
|
10
|
-
v.get.marker_gen(ct)
|
11
|
-
end
|
12
|
-
self[:inputs].each do |i|
|
13
|
-
if i[:init_exp]
|
14
|
-
i.init_func_gen(ct)
|
15
|
-
ct.define_init_stmt "#{i.node_var_name(ct)}[last_side] = #{i.init_func_name(ct)}();"
|
16
|
-
end
|
17
|
-
i.node_var_gen(ct)
|
18
|
-
end
|
19
|
-
self[:dict][:sorted_nodes].each_with_index do |n, i|
|
20
|
-
node = n.get
|
21
|
-
node.func_gen(ct)
|
22
|
-
node.node_var_gen(ct)
|
23
|
-
if node[:init_exp]
|
24
|
-
node.init_func_gen(ct)
|
25
|
-
ct.define_init_stmt "#{node.node_var_name(ct)}[last_side] = #{node.init_func_name(ct)}();"
|
26
|
-
t = ct.tdef(node)
|
27
|
-
if t.is_a?(TypeDef) && !t.enum?(ct)
|
28
|
-
ct.define_init_stmt "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[last_side], #{ar.ref_pos_last(node) + 1});"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
self[:dict][:ifunc_space].each do |k, v|
|
33
|
-
v.get.codegen(ct)
|
34
|
-
end
|
35
|
-
self[:dict][:used_pfuncs].each do |v|
|
36
|
-
v.get.codegen(ct)
|
37
|
-
end
|
38
|
-
self[:dict][:sorted_datas].reverse.each do |v|
|
39
|
-
v.get.codegen(ct)
|
40
|
-
end
|
41
|
-
memory_gen(ct, ar)
|
42
|
-
main_gen(ct, ar)
|
43
|
-
io_proto_gen(ct)
|
44
|
-
end
|
45
|
-
|
46
|
-
def memory_gen(ct, ar)
|
47
|
-
max_memory = ar.requirement()
|
48
|
-
max_memory.each do |t, i|
|
49
|
-
t = t.get
|
50
|
-
next if t[:static] || t.enum?(ct)
|
51
|
-
ct.define_global_var("struct #{t.struct_name(ct)}", "#{t.memory_name(ct)}[#{i}]")
|
52
|
-
ct.define_global_var("int", "#{t.memory_size_name(ct)}", "#{i}")
|
53
|
-
ct.define_global_var("int", "#{t.memory_counter_name(ct)}", "0")
|
54
|
-
end
|
55
|
-
ct.define_global_var("int", "Counter", "1")
|
56
|
-
ct.define_global_var("int", "NodeSize", "#{self[:dict][:sorted_nodes].size}")
|
57
|
-
ct.define_func("void", "refreshMark", []) do |x|
|
58
|
-
x << "int i;"
|
59
|
-
max_memory.each do |t, i|
|
60
|
-
t = t.get
|
61
|
-
next if t[:static] || t.enum?(ct)
|
62
|
-
mn = "#{t.memory_name(ct)}[i].mark"
|
63
|
-
stmts = []
|
64
|
-
stmts << "if (#{mn} < Counter) #{mn} = 0;"
|
65
|
-
stmts << "else #{mn} -= Counter - 1;"
|
66
|
-
x << ct.make_block("for (i = 0; i < #{t.memory_size_name(ct)}; i++) {", stmts, "}")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def main_gen(ct, ar)
|
72
|
-
ct.define_func("void", "Activate" + self[:module_name][:desc], [], :none) do |x|
|
73
|
-
x << "int current_side = 0, last_side = 1;"
|
74
|
-
ct.define_init_stmt "Counter = NodeSize + 1;"
|
75
|
-
ct.define_init_stmt "refreshMark();"
|
76
|
-
ct.init_stmts.each do |i|
|
77
|
-
x << i
|
78
|
-
end
|
79
|
-
stmts = []
|
80
|
-
stmts << "Counter = 1;"
|
81
|
-
inputs = self[:inputs].map{|x| "&#{x.node_var_name(ct)}[current_side]"}.join(", ")
|
82
|
-
stmts << "Input(#{inputs});"
|
83
|
-
self[:dict][:sorted_nodes].each do |n|
|
84
|
-
node = n.get
|
85
|
-
args = node[:params].map do |x|
|
86
|
-
pn = self[:dict][:node_space][x[:name][:desc]].get
|
87
|
-
"#{pn.node_var_name(ct)}[#{x[:last] ? "last_side" : "current_side"}]"
|
88
|
-
end
|
89
|
-
output_arg = "&#{node.node_var_name(ct)}[current_side]"
|
90
|
-
stmts << "#{node.node_func_name(ct)}(#{[*args, output_arg].join(", ")});"
|
91
|
-
t = ct.tdef(node)
|
92
|
-
if t.is_a?(TypeDef) && !t.enum?(ct)
|
93
|
-
mark_val = "Counter + #{ar.life_point(node)}"
|
94
|
-
stmts << "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[current_side], #{mark_val});"
|
95
|
-
end
|
96
|
-
stmts << "Counter++;"
|
97
|
-
end
|
98
|
-
outputs = self[:outputs].map do |x|
|
99
|
-
node = self[:dict][:node_space][x[:name][:desc]].get
|
100
|
-
"&#{node.node_var_name(ct)}[current_side]"
|
101
|
-
end
|
102
|
-
stmts << "Output(#{outputs.join(", ")});"
|
103
|
-
stmts << "refreshMark();"
|
104
|
-
stmts << "current_side ^= 1;"
|
105
|
-
stmts << "last_side ^= 1;"
|
106
|
-
x << ct.make_block("while (1) {", stmts, "}")
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def io_proto_gen(ct)
|
111
|
-
ct.define_proto("void", "Input", self[:inputs].map{|x| ct.tref(x) + "*"}, :extern)
|
112
|
-
ct.define_proto("void", "Output", self[:outputs].map{|x| ct.tref(x) + "*"}, :extern)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
class TypeDef
|
117
|
-
def struct_gen(ct)
|
118
|
-
return if enum?(ct)
|
119
|
-
ct.define_struct("struct", struct_name(ct), nil) do |s1|
|
120
|
-
s1 << "int tvalue_id;" if self[:tvalues].length > 1
|
121
|
-
s1 << "int mark;" unless self[:static]
|
122
|
-
s1 << ct.define_struct("union", nil, "value") do |s2|
|
123
|
-
self[:tvalues].each_with_index do |tvalue, i|
|
124
|
-
next if tvalue[:params].size == 0
|
125
|
-
s2 << ct.define_struct("struct", nil, tvalue.struct_name(ct)) do |s3|
|
126
|
-
tvalue[:params].each_with_index do |param, i|
|
127
|
-
s3 << "#{ct.tref(param)} member#{i};"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def constructor_gen(ct)
|
136
|
-
return if enum?(ct)
|
137
|
-
self[:tvalues].each_with_index do |tvalue, i|
|
138
|
-
params = tvalue[:params].each_with_index.map do |param, i|
|
139
|
-
[ct.tref(param), "member#{i}"]
|
140
|
-
end
|
141
|
-
ct.define_func(ref_name(ct), tvalue.constructor_name(ct), params) do |s|
|
142
|
-
while_stmts = []
|
143
|
-
while_stmts << "#{memory_counter_name(ct)}++;"
|
144
|
-
while_stmts << "#{memory_counter_name(ct)} %= #{memory_size_name(ct)};"
|
145
|
-
mn = "#{memory_name(ct)}[#{memory_counter_name(ct)}].mark"
|
146
|
-
while_stmts << "if (#{mn} < Counter) { x = #{memory_name(ct)} + #{memory_counter_name(ct)}; break; }"
|
147
|
-
s << "#{ref_name(ct)} x;"
|
148
|
-
s << ct.make_block("while (1) {", while_stmts, "}")
|
149
|
-
s << "x->tvalue_id = #{i};" if self[:tvalues].length > 1
|
150
|
-
tvalue[:params].each_with_index do |param, i|
|
151
|
-
s << "x->value.#{tvalue.struct_name(ct)}.member#{i} = member#{i};"
|
152
|
-
end
|
153
|
-
s << "return x;"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def marker_gen(ct)
|
159
|
-
return if enum?(ct)
|
160
|
-
params = [[ref_name(ct), "x"], ["int", "mark"]]
|
161
|
-
ct.define_func("void", marker_func_name(ct), params) do |x|
|
162
|
-
x << "x->mark = mark;" unless self[:static]
|
163
|
-
accessor = self[:static] ? "." : "->"
|
164
|
-
cases = []
|
165
|
-
self[:tvalues].each_with_index do |tvalue, i|
|
166
|
-
calls = []
|
167
|
-
tvalue[:params].each_with_index do |param, i|
|
168
|
-
if ct.tdef(param).is_a?(TypeDef) && !ct.tdef(param).enum?(ct)
|
169
|
-
fn = ct.tdef(param).marker_func_name(ct)
|
170
|
-
calls << "#{fn}(x#{accessor}value.#{tvalue.struct_name(ct)}.member#{i}, mark);"
|
171
|
-
end
|
172
|
-
end
|
173
|
-
cases << "case #{i}: #{calls.join(" ")} break;" if calls.size > 0
|
174
|
-
end
|
175
|
-
if cases.size > 0
|
176
|
-
switch_exp = self[:tvalues].size == 1 ? "0" : "x#{accessor}tvalue_id"
|
177
|
-
x << ct.make_block("switch (#{switch_exp}) {", cases, "}")
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def enum?(ct)
|
183
|
-
self[:tvalues].all?{|x| x[:params].length == 0}
|
184
|
-
end
|
185
|
-
|
186
|
-
def struct_name(ct)
|
187
|
-
unless enum?(ct)
|
188
|
-
self[:tvalues][0][:typing].to_flatten_uniq_str
|
189
|
-
else
|
190
|
-
raise
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def marker_func_name(ct)
|
195
|
-
unless enum?(ct)
|
196
|
-
"mark_#{struct_name(ct)}"
|
197
|
-
else
|
198
|
-
raise
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def ref_name(ct)
|
203
|
-
if enum?(ct)
|
204
|
-
"int"
|
205
|
-
else
|
206
|
-
"struct " + struct_name(ct) + (self[:static] ? "" : "*")
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def memory_name(ct)
|
211
|
-
"memory_#{struct_name(ct)}"
|
212
|
-
end
|
213
|
-
|
214
|
-
def memory_size_name(ct)
|
215
|
-
"size_#{struct_name(ct)}"
|
216
|
-
end
|
217
|
-
|
218
|
-
def memory_counter_name(ct)
|
219
|
-
"counter_#{struct_name(ct)}"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
class TValue
|
224
|
-
def constructor_name(ct)
|
225
|
-
self[:name][:desc] + "_" + ct.serial(self[:name][:desc], self).to_s
|
226
|
-
end
|
227
|
-
|
228
|
-
def struct_name(ct)
|
229
|
-
self[:name][:desc]
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
class PrimTypeDef
|
234
|
-
def codegen(ct)
|
235
|
-
# do nothing
|
236
|
-
end
|
237
|
-
|
238
|
-
def ref_name(ct)
|
239
|
-
ctype_foreign = self[:foreigns].find{|x| x[:language][:desc] == "c"}
|
240
|
-
unless ctype_foreign
|
241
|
-
raise "compile error: foreign for c is undefined in #{self[:name][:desc]}"
|
242
|
-
end
|
243
|
-
ctype_foreign[:desc]
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
class NodeDef
|
248
|
-
def func_gen(ct)
|
249
|
-
params = self[:params].map{|x| [ct.tref(x), ct.escape_name(x[:as][:desc])]}
|
250
|
-
output_param = [ct.tref(self) + "*", "output"]
|
251
|
-
ct.define_func("int", node_func_name(ct), params + [output_param]) do |x|
|
252
|
-
x << "*output = #{self[:exp].codegen(ct, x)};"
|
253
|
-
x << "return 1;"
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def init_func_gen(ct)
|
258
|
-
ct.define_func(ct.tref(self), init_func_name(ct), []) do |x|
|
259
|
-
x << "return #{self[:init_exp].codegen(ct, x)};"
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def node_var_gen(ct)
|
264
|
-
ct.define_global_var(ct.tref(self), "#{node_var_name(ct)}[2]")
|
265
|
-
end
|
266
|
-
|
267
|
-
def init_func_name(ct)
|
268
|
-
"init_#{ct.escape_name(self[:name][:desc])}"
|
269
|
-
end
|
270
|
-
|
271
|
-
def node_func_name(ct)
|
272
|
-
"node_#{ct.escape_name(self[:name][:desc])}"
|
273
|
-
end
|
274
|
-
|
275
|
-
def node_var_name(ct)
|
276
|
-
"node_memory_#{ct.escape_name(self[:name][:desc])}"
|
277
|
-
end
|
278
|
-
|
279
|
-
def var_suffix(ct)
|
280
|
-
"_nvar#{ct.serial(nil, self)}"
|
281
|
-
end
|
282
|
-
|
283
|
-
def var_name(ct, name)
|
284
|
-
ct.escape_name(name)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
class InputDef
|
289
|
-
def init_func_gen(ct)
|
290
|
-
ct.define_func(ct.tref(self), init_func_name(ct), []) do |x|
|
291
|
-
x << "return #{self[:init_exp].codegen(ct, x)};"
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
def node_var_gen(ct)
|
296
|
-
ct.define_global_var(ct.tref(self), "#{node_var_name(ct)}[2]")
|
297
|
-
end
|
298
|
-
|
299
|
-
def init_func_name(ct)
|
300
|
-
"init_#{self[:name][:desc]}"
|
301
|
-
end
|
302
|
-
|
303
|
-
def node_var_name(ct)
|
304
|
-
"node_memory_#{self[:name][:desc]}"
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
class DataDef
|
309
|
-
def codegen(ct)
|
310
|
-
t = ct.tref(self)
|
311
|
-
ct.define_global_var(t, var_name(ct, self[:name][:desc]))
|
312
|
-
ct.define_init_stmt("#{var_name(ct, self[:name][:desc])} = #{init_func_name(ct)}();")
|
313
|
-
ct.define_func(t, init_func_name(ct), []) do |x|
|
314
|
-
x << "return #{self[:exp].codegen(ct, x)};"
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
def var_name(ct)
|
319
|
-
"data_#{self[:name][:desc]}"
|
320
|
-
end
|
321
|
-
|
322
|
-
def init_func_name(ct)
|
323
|
-
"init_#{self[:name][:desc]}"
|
324
|
-
end
|
325
|
-
|
326
|
-
def var_name(ct, name)
|
327
|
-
ct.escape_name(name)
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
class FuncDef
|
332
|
-
def codegen(ct)
|
333
|
-
params = self[:params].map{|x| [ct.tref(x), x[:name][:desc]]}
|
334
|
-
ct.define_func(ct.tref(self), func_name(ct), params) do |x|
|
335
|
-
x << "return #{self[:exp].codegen(ct, x)};"
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
def func_name(ct)
|
340
|
-
ct.escape_name(self[:name][:desc]) + "_" + ct.serial(self[:name][:desc], self).to_s
|
341
|
-
end
|
342
|
-
|
343
|
-
def var_name(ct, name)
|
344
|
-
ct.escape_name(name)
|
345
|
-
end
|
346
|
-
end
|
347
|
-
|
348
|
-
class PrimFuncDef
|
349
|
-
def codegen(ct)
|
350
|
-
params = self[:params].map{|x| x[:name][:desc]}
|
351
|
-
exp = self[:foreigns].find{|x| x[:language][:desc] == "c"}
|
352
|
-
raise "assertion error: foreign for c is undefined in #{self[:name][:desc]}" unless exp
|
353
|
-
ct.define_macro(func_name(ct), params, exp[:desc])
|
354
|
-
end
|
355
|
-
|
356
|
-
def func_name(ct)
|
357
|
-
ct.escape_name(self[:name][:desc])
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
class ParamDef
|
362
|
-
|
363
|
-
end
|
364
|
-
end
|
1
|
+
require 'emfrp/syntax'
|
2
|
+
require 'emfrp/compile/c/syntax_exp_codegen'
|
3
|
+
|
4
|
+
module Emfrp
|
5
|
+
class Top
|
6
|
+
def codegen(ct, ar)
|
7
|
+
self[:dict][:itype_space].each do |k, v|
|
8
|
+
v.get.struct_gen(ct)
|
9
|
+
v.get.constructor_gen(ct)
|
10
|
+
v.get.marker_gen(ct)
|
11
|
+
end
|
12
|
+
self[:inputs].each do |i|
|
13
|
+
if i[:init_exp]
|
14
|
+
i.init_func_gen(ct)
|
15
|
+
ct.define_init_stmt "#{i.node_var_name(ct)}[last_side] = #{i.init_func_name(ct)}();"
|
16
|
+
end
|
17
|
+
i.node_var_gen(ct)
|
18
|
+
end
|
19
|
+
self[:dict][:sorted_nodes].each_with_index do |n, i|
|
20
|
+
node = n.get
|
21
|
+
node.func_gen(ct)
|
22
|
+
node.node_var_gen(ct)
|
23
|
+
if node[:init_exp]
|
24
|
+
node.init_func_gen(ct)
|
25
|
+
ct.define_init_stmt "#{node.node_var_name(ct)}[last_side] = #{node.init_func_name(ct)}();"
|
26
|
+
t = ct.tdef(node)
|
27
|
+
if t.is_a?(TypeDef) && !t.enum?(ct)
|
28
|
+
ct.define_init_stmt "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[last_side], #{ar.ref_pos_last(node) + 1});"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
self[:dict][:ifunc_space].each do |k, v|
|
33
|
+
v.get.codegen(ct)
|
34
|
+
end
|
35
|
+
self[:dict][:used_pfuncs].each do |v|
|
36
|
+
v.get.codegen(ct)
|
37
|
+
end
|
38
|
+
self[:dict][:sorted_datas].reverse.each do |v|
|
39
|
+
v.get.codegen(ct)
|
40
|
+
end
|
41
|
+
memory_gen(ct, ar)
|
42
|
+
main_gen(ct, ar)
|
43
|
+
io_proto_gen(ct)
|
44
|
+
end
|
45
|
+
|
46
|
+
def memory_gen(ct, ar)
|
47
|
+
max_memory = ar.requirement()
|
48
|
+
max_memory.each do |t, i|
|
49
|
+
t = t.get
|
50
|
+
next if t[:static] || t.enum?(ct)
|
51
|
+
ct.define_global_var("struct #{t.struct_name(ct)}", "#{t.memory_name(ct)}[#{i}]")
|
52
|
+
ct.define_global_var("int", "#{t.memory_size_name(ct)}", "#{i}")
|
53
|
+
ct.define_global_var("int", "#{t.memory_counter_name(ct)}", "0")
|
54
|
+
end
|
55
|
+
ct.define_global_var("int", "Counter", "1")
|
56
|
+
ct.define_global_var("int", "NodeSize", "#{self[:dict][:sorted_nodes].size}")
|
57
|
+
ct.define_func("void", "refreshMark", []) do |x|
|
58
|
+
x << "int i;"
|
59
|
+
max_memory.each do |t, i|
|
60
|
+
t = t.get
|
61
|
+
next if t[:static] || t.enum?(ct)
|
62
|
+
mn = "#{t.memory_name(ct)}[i].mark"
|
63
|
+
stmts = []
|
64
|
+
stmts << "if (#{mn} < Counter) #{mn} = 0;"
|
65
|
+
stmts << "else #{mn} -= Counter - 1;"
|
66
|
+
x << ct.make_block("for (i = 0; i < #{t.memory_size_name(ct)}; i++) {", stmts, "}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def main_gen(ct, ar)
|
72
|
+
ct.define_func("void", "Activate" + self[:module_name][:desc], [], :none) do |x|
|
73
|
+
x << "int current_side = 0, last_side = 1;"
|
74
|
+
ct.define_init_stmt "Counter = NodeSize + 1;"
|
75
|
+
ct.define_init_stmt "refreshMark();"
|
76
|
+
ct.init_stmts.each do |i|
|
77
|
+
x << i
|
78
|
+
end
|
79
|
+
stmts = []
|
80
|
+
stmts << "Counter = 1;"
|
81
|
+
inputs = self[:inputs].map{|x| "&#{x.node_var_name(ct)}[current_side]"}.join(", ")
|
82
|
+
stmts << "Input(#{inputs});"
|
83
|
+
self[:dict][:sorted_nodes].each do |n|
|
84
|
+
node = n.get
|
85
|
+
args = node[:params].map do |x|
|
86
|
+
pn = self[:dict][:node_space][x[:name][:desc]].get
|
87
|
+
"#{pn.node_var_name(ct)}[#{x[:last] ? "last_side" : "current_side"}]"
|
88
|
+
end
|
89
|
+
output_arg = "&#{node.node_var_name(ct)}[current_side]"
|
90
|
+
stmts << "#{node.node_func_name(ct)}(#{[*args, output_arg].join(", ")});"
|
91
|
+
t = ct.tdef(node)
|
92
|
+
if t.is_a?(TypeDef) && !t.enum?(ct)
|
93
|
+
mark_val = "Counter + #{ar.life_point(node)}"
|
94
|
+
stmts << "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[current_side], #{mark_val});"
|
95
|
+
end
|
96
|
+
stmts << "Counter++;"
|
97
|
+
end
|
98
|
+
outputs = self[:outputs].map do |x|
|
99
|
+
node = self[:dict][:node_space][x[:name][:desc]].get
|
100
|
+
"&#{node.node_var_name(ct)}[current_side]"
|
101
|
+
end
|
102
|
+
stmts << "Output(#{outputs.join(", ")});"
|
103
|
+
stmts << "refreshMark();"
|
104
|
+
stmts << "current_side ^= 1;"
|
105
|
+
stmts << "last_side ^= 1;"
|
106
|
+
x << ct.make_block("while (1) {", stmts, "}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def io_proto_gen(ct)
|
111
|
+
ct.define_proto("void", "Input", self[:inputs].map{|x| ct.tref(x) + "*"}, :extern)
|
112
|
+
ct.define_proto("void", "Output", self[:outputs].map{|x| ct.tref(x) + "*"}, :extern)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class TypeDef
|
117
|
+
def struct_gen(ct)
|
118
|
+
return if enum?(ct)
|
119
|
+
ct.define_struct("struct", struct_name(ct), nil) do |s1|
|
120
|
+
s1 << "int tvalue_id;" if self[:tvalues].length > 1
|
121
|
+
s1 << "int mark;" unless self[:static]
|
122
|
+
s1 << ct.define_struct("union", nil, "value") do |s2|
|
123
|
+
self[:tvalues].each_with_index do |tvalue, i|
|
124
|
+
next if tvalue[:params].size == 0
|
125
|
+
s2 << ct.define_struct("struct", nil, tvalue.struct_name(ct)) do |s3|
|
126
|
+
tvalue[:params].each_with_index do |param, i|
|
127
|
+
s3 << "#{ct.tref(param)} member#{i};"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def constructor_gen(ct)
|
136
|
+
return if enum?(ct)
|
137
|
+
self[:tvalues].each_with_index do |tvalue, i|
|
138
|
+
params = tvalue[:params].each_with_index.map do |param, i|
|
139
|
+
[ct.tref(param), "member#{i}"]
|
140
|
+
end
|
141
|
+
ct.define_func(ref_name(ct), tvalue.constructor_name(ct), params) do |s|
|
142
|
+
while_stmts = []
|
143
|
+
while_stmts << "#{memory_counter_name(ct)}++;"
|
144
|
+
while_stmts << "#{memory_counter_name(ct)} %= #{memory_size_name(ct)};"
|
145
|
+
mn = "#{memory_name(ct)}[#{memory_counter_name(ct)}].mark"
|
146
|
+
while_stmts << "if (#{mn} < Counter) { x = #{memory_name(ct)} + #{memory_counter_name(ct)}; break; }"
|
147
|
+
s << "#{ref_name(ct)} x;"
|
148
|
+
s << ct.make_block("while (1) {", while_stmts, "}")
|
149
|
+
s << "x->tvalue_id = #{i};" if self[:tvalues].length > 1
|
150
|
+
tvalue[:params].each_with_index do |param, i|
|
151
|
+
s << "x->value.#{tvalue.struct_name(ct)}.member#{i} = member#{i};"
|
152
|
+
end
|
153
|
+
s << "return x;"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def marker_gen(ct)
|
159
|
+
return if enum?(ct)
|
160
|
+
params = [[ref_name(ct), "x"], ["int", "mark"]]
|
161
|
+
ct.define_func("void", marker_func_name(ct), params) do |x|
|
162
|
+
x << "x->mark = mark;" unless self[:static]
|
163
|
+
accessor = self[:static] ? "." : "->"
|
164
|
+
cases = []
|
165
|
+
self[:tvalues].each_with_index do |tvalue, i|
|
166
|
+
calls = []
|
167
|
+
tvalue[:params].each_with_index do |param, i|
|
168
|
+
if ct.tdef(param).is_a?(TypeDef) && !ct.tdef(param).enum?(ct)
|
169
|
+
fn = ct.tdef(param).marker_func_name(ct)
|
170
|
+
calls << "#{fn}(x#{accessor}value.#{tvalue.struct_name(ct)}.member#{i}, mark);"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
cases << "case #{i}: #{calls.join(" ")} break;" if calls.size > 0
|
174
|
+
end
|
175
|
+
if cases.size > 0
|
176
|
+
switch_exp = self[:tvalues].size == 1 ? "0" : "x#{accessor}tvalue_id"
|
177
|
+
x << ct.make_block("switch (#{switch_exp}) {", cases, "}")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def enum?(ct)
|
183
|
+
self[:tvalues].all?{|x| x[:params].length == 0}
|
184
|
+
end
|
185
|
+
|
186
|
+
def struct_name(ct)
|
187
|
+
unless enum?(ct)
|
188
|
+
self[:tvalues][0][:typing].to_flatten_uniq_str
|
189
|
+
else
|
190
|
+
raise
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def marker_func_name(ct)
|
195
|
+
unless enum?(ct)
|
196
|
+
"mark_#{struct_name(ct)}"
|
197
|
+
else
|
198
|
+
raise
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def ref_name(ct)
|
203
|
+
if enum?(ct)
|
204
|
+
"int"
|
205
|
+
else
|
206
|
+
"struct " + struct_name(ct) + (self[:static] ? "" : "*")
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def memory_name(ct)
|
211
|
+
"memory_#{struct_name(ct)}"
|
212
|
+
end
|
213
|
+
|
214
|
+
def memory_size_name(ct)
|
215
|
+
"size_#{struct_name(ct)}"
|
216
|
+
end
|
217
|
+
|
218
|
+
def memory_counter_name(ct)
|
219
|
+
"counter_#{struct_name(ct)}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class TValue
|
224
|
+
def constructor_name(ct)
|
225
|
+
self[:name][:desc] + "_" + ct.serial(self[:name][:desc], self).to_s
|
226
|
+
end
|
227
|
+
|
228
|
+
def struct_name(ct)
|
229
|
+
self[:name][:desc]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class PrimTypeDef
|
234
|
+
def codegen(ct)
|
235
|
+
# do nothing
|
236
|
+
end
|
237
|
+
|
238
|
+
def ref_name(ct)
|
239
|
+
ctype_foreign = self[:foreigns].find{|x| x[:language][:desc] == "c"}
|
240
|
+
unless ctype_foreign
|
241
|
+
raise "compile error: foreign for c is undefined in #{self[:name][:desc]}"
|
242
|
+
end
|
243
|
+
ctype_foreign[:desc]
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
class NodeDef
|
248
|
+
def func_gen(ct)
|
249
|
+
params = self[:params].map{|x| [ct.tref(x), ct.escape_name(x[:as][:desc])]}
|
250
|
+
output_param = [ct.tref(self) + "*", "output"]
|
251
|
+
ct.define_func("int", node_func_name(ct), params + [output_param]) do |x|
|
252
|
+
x << "*output = #{self[:exp].codegen(ct, x)};"
|
253
|
+
x << "return 1;"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def init_func_gen(ct)
|
258
|
+
ct.define_func(ct.tref(self), init_func_name(ct), []) do |x|
|
259
|
+
x << "return #{self[:init_exp].codegen(ct, x)};"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def node_var_gen(ct)
|
264
|
+
ct.define_global_var(ct.tref(self), "#{node_var_name(ct)}[2]")
|
265
|
+
end
|
266
|
+
|
267
|
+
def init_func_name(ct)
|
268
|
+
"init_#{ct.escape_name(self[:name][:desc])}"
|
269
|
+
end
|
270
|
+
|
271
|
+
def node_func_name(ct)
|
272
|
+
"node_#{ct.escape_name(self[:name][:desc])}"
|
273
|
+
end
|
274
|
+
|
275
|
+
def node_var_name(ct)
|
276
|
+
"node_memory_#{ct.escape_name(self[:name][:desc])}"
|
277
|
+
end
|
278
|
+
|
279
|
+
def var_suffix(ct)
|
280
|
+
"_nvar#{ct.serial(nil, self)}"
|
281
|
+
end
|
282
|
+
|
283
|
+
def var_name(ct, name)
|
284
|
+
ct.escape_name(name)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class InputDef
|
289
|
+
def init_func_gen(ct)
|
290
|
+
ct.define_func(ct.tref(self), init_func_name(ct), []) do |x|
|
291
|
+
x << "return #{self[:init_exp].codegen(ct, x)};"
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def node_var_gen(ct)
|
296
|
+
ct.define_global_var(ct.tref(self), "#{node_var_name(ct)}[2]")
|
297
|
+
end
|
298
|
+
|
299
|
+
def init_func_name(ct)
|
300
|
+
"init_#{self[:name][:desc]}"
|
301
|
+
end
|
302
|
+
|
303
|
+
def node_var_name(ct)
|
304
|
+
"node_memory_#{self[:name][:desc]}"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
class DataDef
|
309
|
+
def codegen(ct)
|
310
|
+
t = ct.tref(self)
|
311
|
+
ct.define_global_var(t, var_name(ct, self[:name][:desc]))
|
312
|
+
ct.define_init_stmt("#{var_name(ct, self[:name][:desc])} = #{init_func_name(ct)}();")
|
313
|
+
ct.define_func(t, init_func_name(ct), []) do |x|
|
314
|
+
x << "return #{self[:exp].codegen(ct, x)};"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def var_name(ct)
|
319
|
+
"data_#{self[:name][:desc]}"
|
320
|
+
end
|
321
|
+
|
322
|
+
def init_func_name(ct)
|
323
|
+
"init_#{self[:name][:desc]}"
|
324
|
+
end
|
325
|
+
|
326
|
+
def var_name(ct, name)
|
327
|
+
ct.escape_name(name)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
class FuncDef
|
332
|
+
def codegen(ct)
|
333
|
+
params = self[:params].map{|x| [ct.tref(x), x[:name][:desc]]}
|
334
|
+
ct.define_func(ct.tref(self), func_name(ct), params) do |x|
|
335
|
+
x << "return #{self[:exp].codegen(ct, x)};"
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def func_name(ct)
|
340
|
+
ct.escape_name(self[:name][:desc]) + "_" + ct.serial(self[:name][:desc], self).to_s
|
341
|
+
end
|
342
|
+
|
343
|
+
def var_name(ct, name)
|
344
|
+
ct.escape_name(name)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
class PrimFuncDef
|
349
|
+
def codegen(ct)
|
350
|
+
params = self[:params].map{|x| x[:name][:desc]}
|
351
|
+
exp = self[:foreigns].find{|x| x[:language][:desc] == "c"}
|
352
|
+
raise "assertion error: foreign for c is undefined in #{self[:name][:desc]}" unless exp
|
353
|
+
ct.define_macro(func_name(ct), params, exp[:desc])
|
354
|
+
end
|
355
|
+
|
356
|
+
def func_name(ct)
|
357
|
+
ct.escape_name(self[:name][:desc])
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
class ParamDef
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|