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,367 +1,367 @@
|
|
1
|
-
require 'emfrp/compile/graphviz/graphviz'
|
2
|
-
|
3
|
-
module Emfrp
|
4
|
-
class Interpreter
|
5
|
-
class CommandManager
|
6
|
-
def initialize(interpreter, &proc)
|
7
|
-
@interpreter = interpreter
|
8
|
-
@command_names = []
|
9
|
-
@command_tbl = {}
|
10
|
-
@command_desc_tbl = {}
|
11
|
-
@command_usage_tbl = {}
|
12
|
-
@command_example_tbl = {}
|
13
|
-
@command_desc_buf = []
|
14
|
-
@command_usage_buf = []
|
15
|
-
@command_example_buf = []
|
16
|
-
instance_exec(&proc)
|
17
|
-
end
|
18
|
-
|
19
|
-
def command(*names, &proc)
|
20
|
-
names.each do |name|
|
21
|
-
@command_names << ":" + name
|
22
|
-
@command_tbl[name] = proc
|
23
|
-
@command_desc_tbl[name] = @command_desc_buf
|
24
|
-
@command_usage_tbl[name] = @command_usage_buf
|
25
|
-
@command_example_tbl[name] = @command_example_buf
|
26
|
-
@command_desc_buf, @command_usage_buf, @command_example_buf = [], [], []
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def desc(str)
|
31
|
-
@command_desc_buf << str
|
32
|
-
end
|
33
|
-
|
34
|
-
def usage(str)
|
35
|
-
@command_usage_buf << str
|
36
|
-
end
|
37
|
-
|
38
|
-
def example(str)
|
39
|
-
@command_example_buf << str
|
40
|
-
end
|
41
|
-
|
42
|
-
def print_usage(command_name, output_io)
|
43
|
-
if @command_tbl[command_name]
|
44
|
-
output_io.puts ":#{command_name}".colorize(:light_blue)
|
45
|
-
output_io.puts @command_desc_tbl[command_name].map{|x| " " + x}.join("\n")
|
46
|
-
if @command_usage_tbl[command_name].size > 0
|
47
|
-
output_io.puts " Usage:".colorize(:green)
|
48
|
-
output_io.puts @command_usage_tbl[command_name].map{|x| " " + x}.join("\n")
|
49
|
-
end
|
50
|
-
if @command_example_tbl[command_name].size > 0
|
51
|
-
output_io.puts " Example:".colorize(:green)
|
52
|
-
output_io.puts @command_example_tbl[command_name].map{|x| " " + x}.join("\n")
|
53
|
-
end
|
54
|
-
return nil
|
55
|
-
else
|
56
|
-
return :command_not_found
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def print_all_usages(output_io)
|
61
|
-
@command_tbl.keys.sort.each do |name|
|
62
|
-
print_usage(name, output_io)
|
63
|
-
end
|
64
|
-
return nil
|
65
|
-
end
|
66
|
-
|
67
|
-
def exec(command_name, arg, readline_id)
|
68
|
-
if @command_tbl[command_name]
|
69
|
-
@interpreter.instance_exec(arg, command_name, readline_id, &@command_tbl[command_name])
|
70
|
-
else
|
71
|
-
@interpreter.puts "Error: undefined command `#{command_name}'"
|
72
|
-
return :exec_error
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def completion_proc
|
77
|
-
proc do |s|
|
78
|
-
@command_names.select{|name| name.index(s) == 0}
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.make(interpreter)
|
83
|
-
CommandManager.new(interpreter) do
|
84
|
-
|
85
|
-
desc "Showing object type by specifying it's name."
|
86
|
-
example "data x = 1"
|
87
|
-
example ":t x"
|
88
|
-
command "t" do |arg|
|
89
|
-
name = arg.strip
|
90
|
-
if f = @top[:dict][:func_space][name]
|
91
|
-
puts "func #{name} : " + f.get[:params].map{|x| x[:typing].inspect}.join(", ") +
|
92
|
-
" -> " + f.get[:typing].inspect
|
93
|
-
end
|
94
|
-
if d = @top[:dict][:data_space][name]
|
95
|
-
puts "data #{name} : " + d.get[:typing].inspect
|
96
|
-
end
|
97
|
-
if t = @top[:dict][:type_space][name]
|
98
|
-
case t.get
|
99
|
-
when TypeDef
|
100
|
-
puts "Type #{name} : " + t.get[:tvalues][0][:typing].inspect
|
101
|
-
when PrimTypeDef
|
102
|
-
puts "PrimType #{name} : " + name
|
103
|
-
end
|
104
|
-
end
|
105
|
-
if c = @top[:dict][:const_space][name]
|
106
|
-
puts "constructor #{name} : " + c.get[:params].map{|x| x[:typing].inspect}.join(", ") +
|
107
|
-
" -> " + c.get[:typing].inspect
|
108
|
-
end
|
109
|
-
if n = @top[:dict][:node_space][name]
|
110
|
-
puts "node #{name} : " + n.get[:typing].inspect
|
111
|
-
end
|
112
|
-
next nil
|
113
|
-
end
|
114
|
-
|
115
|
-
desc "Showing internal AST by specifying element's name."
|
116
|
-
command "ast" do |arg|
|
117
|
-
name = arg.strip
|
118
|
-
if f = @top[:dict][:func_space][name]
|
119
|
-
pp f.get
|
120
|
-
elsif d = @top[:dict][:data_space][name]
|
121
|
-
pp d.get
|
122
|
-
elsif t = @top[:dict][:type_space][name]
|
123
|
-
pp t.get
|
124
|
-
elsif c = @top[:dict][:const_space][name]
|
125
|
-
pp c.get
|
126
|
-
elsif n = @top[:dict][:node_space][name]
|
127
|
-
pp n.get
|
128
|
-
elsif name == "top"
|
129
|
-
pp @top
|
130
|
-
elsif name == "ifuncs"
|
131
|
-
pp @top[:dict][:ifuncs_space].keys
|
132
|
-
elsif name == "itypes"
|
133
|
-
pp @top[:dict][:itypes_space].keys
|
134
|
-
else
|
135
|
-
puts "Error: `#{name}' is not found"
|
136
|
-
next :target_not_found
|
137
|
-
end
|
138
|
-
next nil
|
139
|
-
end
|
140
|
-
|
141
|
-
desc "Testing two expression's equality."
|
142
|
-
usage ":assert-equals <expected-exp>, <testing-exp>"
|
143
|
-
command "assert-equals" do |arg, c, rid|
|
144
|
-
if exp = str_to_exp("Pair(#{arg})")
|
145
|
-
val1 = Evaluater.eval_exp(@top, exp[:args][0])
|
146
|
-
val2 = Evaluater.eval_exp(@top, exp[:args][1])
|
147
|
-
if val1 == val2
|
148
|
-
nil
|
149
|
-
else
|
150
|
-
puts "Assertion failed".colorize(:red)
|
151
|
-
puts "Description: #{arg}"
|
152
|
-
puts "Type: #{exp[:args][0][:typing].inspect.colorize(:green)}"
|
153
|
-
puts "Expected: #{Evaluater.value_to_s(val1)}"
|
154
|
-
puts "Actual: #{Evaluater.value_to_s(val2)}"
|
155
|
-
:assertion_error
|
156
|
-
end
|
157
|
-
else
|
158
|
-
:command_format_error
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
desc "Executing all commands embedded on source-files."
|
163
|
-
command "exec-embedded-commands" do
|
164
|
-
exec_embedded_commands()
|
165
|
-
end
|
166
|
-
|
167
|
-
desc "Define documentation about function. (in preparation)"
|
168
|
-
command "set-func-doc" do |arg|
|
169
|
-
nil
|
170
|
-
end
|
171
|
-
|
172
|
-
desc "Testing node as function."
|
173
|
-
usage ":assert-node <node-name> <input-exp>* => <expected-output-exp>"
|
174
|
-
example ":assert-node mynode 1, 2 => 3"
|
175
|
-
command "assert-node" do |arg|
|
176
|
-
if arg =~ /^\s*([a-z][a-zA-Z0-9]*)\s+(.*)=>(.*)$/
|
177
|
-
n = @top[:dict][:node_space][$1]
|
178
|
-
if n && n.get.is_a?(NodeDef)
|
179
|
-
node_def = n.get
|
180
|
-
types = ["Unit", "Unit"] + node_def[:params].map{|x| x[:typing].to_uniq_str}
|
181
|
-
exp_str = ($2.strip == "" ? "(Unit, Unit)" : "(Unit, Unit, #{$2.strip})")
|
182
|
-
if a_exp = str_to_exp(exp_str, "(#{types.join(", ")})")
|
183
|
-
v1 = Evaluater.eval_node_as_func(@top, node_def, a_exp[:args].drop(2))
|
184
|
-
if $3.strip == "skip"
|
185
|
-
v2 = :skip
|
186
|
-
elsif r_exp = str_to_exp($3.strip, "#{node_def[:typing].to_uniq_str}")
|
187
|
-
v2 = Evaluater.eval_exp(@top, r_exp)
|
188
|
-
else
|
189
|
-
puts "Error: invalid expected-return-expression"
|
190
|
-
next :assert_node_error1
|
191
|
-
end
|
192
|
-
if v1 == v2
|
193
|
-
next nil
|
194
|
-
else
|
195
|
-
puts "Node Assertion failed".colorize(:red)
|
196
|
-
puts "Description: #{arg}"
|
197
|
-
puts "Expected: #{Evaluater.value_to_s(v2)}"
|
198
|
-
puts "Actual: #{Evaluater.value_to_s(v1)}"
|
199
|
-
next :assertion_error
|
200
|
-
end
|
201
|
-
else
|
202
|
-
puts "Error: invalid node-argument-expression"
|
203
|
-
next :assert_node_error2
|
204
|
-
end
|
205
|
-
else
|
206
|
-
puts "Error: invalid node name #{$1}"
|
207
|
-
next :assert_node_error3
|
208
|
-
end
|
209
|
-
else
|
210
|
-
next :command_format_error
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
desc "Testing whole-module by feeding inputs."
|
215
|
-
usage ":assert-module <input-exp>* => <expected-ouput-exp>*"
|
216
|
-
example ":assert-module 1, 2 => 2, 4"
|
217
|
-
command "assert-module" do |arg|
|
218
|
-
if arg =~ /^(.*)=>(.*)$/
|
219
|
-
input_types = ["Unit", "Unit"] + @top[:inputs].map{|x| x[:typing].to_uniq_str}
|
220
|
-
exp_str = ($1.strip == "" ? "(Unit, Unit)" : "(Unit, Unit, #{$1.strip})")
|
221
|
-
input_exps = str_to_exp(exp_str, "(#{input_types.join(", ")})")
|
222
|
-
output_types = @top[:outputs].map{|x| x[:typing].to_uniq_str}
|
223
|
-
output_exps = str_to_exp("(Unit, #{$2})", "(Unit, #{output_types.join(", ")})")
|
224
|
-
if input_exps == nil || output_exps == nil
|
225
|
-
puts "Error: invalid expression"
|
226
|
-
next :assert_module_error1
|
227
|
-
end
|
228
|
-
# evaluate
|
229
|
-
last_state = @current_state ? @current_state.clone : nil
|
230
|
-
@current_state = {}
|
231
|
-
@node_replacement ||= {}
|
232
|
-
output_vals = Evaluater.eval_module(@top, input_exps[:args].drop(2),
|
233
|
-
@current_state, last_state, @node_replacement)
|
234
|
-
expected_output_vals = output_exps[:args].drop(1).map{|x| Evaluater.eval_exp(@top, x)}
|
235
|
-
# assert
|
236
|
-
if expected_output_vals != output_vals
|
237
|
-
puts "Module Assertion failed".colorize(:red)
|
238
|
-
puts "Description: #{arg}"
|
239
|
-
puts "Expected: #{expected_output_vals.map{|x| Evaluater.value_to_s(x)}.join(", ")}"
|
240
|
-
puts "Actual: #{output_vals.map{|x| Evaluater.value_to_s(x)}.join(", ")}"
|
241
|
-
:assertion_error
|
242
|
-
else
|
243
|
-
nil
|
244
|
-
end
|
245
|
-
else
|
246
|
-
:command_format_error
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
desc "Testing expression's type."
|
251
|
-
usage ":assert-type: <exp> => <type>"
|
252
|
-
command "assert-type" do |arg|
|
253
|
-
if arg =~ /^(.*)=>(.*)$/
|
254
|
-
if exp = str_to_exp($1.strip)
|
255
|
-
if exp[:typing].to_uniq_str == $2.strip
|
256
|
-
next nil
|
257
|
-
else
|
258
|
-
puts "Type Assertion failed".colorize(:red)
|
259
|
-
puts "Description: #{$1.strip}"
|
260
|
-
puts "Expected: #{$2.strip}"
|
261
|
-
puts "Actual: #{exp[:typing].to_uniq_str}"
|
262
|
-
next :assertion_error
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
266
|
-
next :command_format_error
|
267
|
-
end
|
268
|
-
|
269
|
-
desc "Testing that specified command finishes with specified error-code"
|
270
|
-
usage ":assert-error <expected-error-code> => <testing-command>"
|
271
|
-
example ":assert-error assertion_error => :assert-type 1 => Double"
|
272
|
-
command "assert-error" do |arg|
|
273
|
-
if arg =~ /^\s*([a-z][a-zA-Z0-9_]*)\s*=>\s*(.*)$/
|
274
|
-
expected_error_code = $1
|
275
|
-
res = disable_io{ process_repl_line($2) }
|
276
|
-
if res.to_s == expected_error_code
|
277
|
-
next nil
|
278
|
-
else
|
279
|
-
puts "Error-Assertion error"
|
280
|
-
puts "Expected error-code: #{expected_error_code}"
|
281
|
-
puts "Actual error-code: #{res}"
|
282
|
-
next :assertion_error
|
283
|
-
end
|
284
|
-
else
|
285
|
-
next :command_format_error
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
desc "Replace one node to another like Stab."
|
290
|
-
desc "currently, this is only for testing (command-line assertion)."
|
291
|
-
usage ":replace-node <replaced-node-name> => <alternative-node-name>"
|
292
|
-
command "replace-node" do |arg|
|
293
|
-
if arg =~ /^\s*([a-z][a-zA-Z0-9]*)\s*=>\s*([a-z][a-zA-Z0-9]*)\s*$/
|
294
|
-
real_n_ln, dummy_n_ln = @top[:dict][:node_space][$1], @top[:dict][:node_space][$2]
|
295
|
-
unless real_n_ln
|
296
|
-
puts "Error: Node `#{$1}' is undefined"
|
297
|
-
next :replace_node_err1
|
298
|
-
end
|
299
|
-
unless dummy_n_ln
|
300
|
-
puts "Error: Node `#{$2}' is undefined"
|
301
|
-
next :replace_node_err2
|
302
|
-
end
|
303
|
-
unless real_n_ln.get[:typing].to_uniq_str == dummy_n_ln.get[:typing].to_uniq_str
|
304
|
-
puts "Error: Types of Real-Node `#{$1}' and Dummy-Node `#{$2}' are different"
|
305
|
-
puts "#{$1} : #{real_n_ln.get[:typing].to_uniq_str}"
|
306
|
-
puts "#{$2} : #{dummy_n_ln.get[:typing].to_uniq_str}"
|
307
|
-
next :replace_node_err3
|
308
|
-
end
|
309
|
-
collect_deps = proc do |node|
|
310
|
-
if node.is_a?(NodeDef)
|
311
|
-
[node] + node[:params].reject{|x| x[:last]}.map{|p|
|
312
|
-
collect_deps.call(@top[:dict][:node_space][p[:name][:desc]].get)
|
313
|
-
}.flatten
|
314
|
-
else
|
315
|
-
[node]
|
316
|
-
end
|
317
|
-
end
|
318
|
-
c1 = collect_deps.call(dummy_n_ln.get).find{|x| x[:name] == real_n_ln.get[:name]}
|
319
|
-
c2 = collect_deps.call(real_n_ln.get).find{|x| x[:name] == dummy_n_ln.get[:name]}
|
320
|
-
unless c1 == nil && c2 == nil
|
321
|
-
puts "Error: Real-Node `#{$1}' and Dummy-Node `#{$2}' are on depending relation"
|
322
|
-
next :replace_node_err4
|
323
|
-
end
|
324
|
-
if real_n_ln.get[:init_exp] && !dummy_n_ln.get[:init_exp]
|
325
|
-
puts "Error: Dummy-Node `#{$2}' should have init-exp"
|
326
|
-
next :replace_node_err5
|
327
|
-
end
|
328
|
-
@node_replacement ||= {}
|
329
|
-
@node_replacement[$1] = dummy_n_ln.get
|
330
|
-
next nil
|
331
|
-
else
|
332
|
-
next :command_format_error
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
desc "Compiling module-file into c-program code."
|
337
|
-
desc "Target file-name is currently fixed..."
|
338
|
-
desc "(module-name is used and files are dumped on current-dir)"
|
339
|
-
usage ":compile"
|
340
|
-
command "compile" do
|
341
|
-
next compile_default()
|
342
|
-
end
|
343
|
-
|
344
|
-
desc "Compiling module-file into graphviz-source code (.dot file)."
|
345
|
-
desc "If file-name is given as a command-argument, the code is output to it."
|
346
|
-
desc "Otherwise, the code is output on console."
|
347
|
-
example ":compile-dot graph.dot"
|
348
|
-
command "compile-dot" do |arg|
|
349
|
-
if arg.strip != ""
|
350
|
-
File.open(arg, "w") do |f|
|
351
|
-
Graphviz.compile(@top, f)
|
352
|
-
end
|
353
|
-
else
|
354
|
-
Graphviz.compile(@top, @output_io)
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
desc "Showing usage of all commands."
|
359
|
-
command "commands" do
|
360
|
-
@command_manager.print_all_usages(@output_io)
|
361
|
-
end
|
362
|
-
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
end
|
367
|
-
end
|
1
|
+
require 'emfrp/compile/graphviz/graphviz'
|
2
|
+
|
3
|
+
module Emfrp
|
4
|
+
class Interpreter
|
5
|
+
class CommandManager
|
6
|
+
def initialize(interpreter, &proc)
|
7
|
+
@interpreter = interpreter
|
8
|
+
@command_names = []
|
9
|
+
@command_tbl = {}
|
10
|
+
@command_desc_tbl = {}
|
11
|
+
@command_usage_tbl = {}
|
12
|
+
@command_example_tbl = {}
|
13
|
+
@command_desc_buf = []
|
14
|
+
@command_usage_buf = []
|
15
|
+
@command_example_buf = []
|
16
|
+
instance_exec(&proc)
|
17
|
+
end
|
18
|
+
|
19
|
+
def command(*names, &proc)
|
20
|
+
names.each do |name|
|
21
|
+
@command_names << ":" + name
|
22
|
+
@command_tbl[name] = proc
|
23
|
+
@command_desc_tbl[name] = @command_desc_buf
|
24
|
+
@command_usage_tbl[name] = @command_usage_buf
|
25
|
+
@command_example_tbl[name] = @command_example_buf
|
26
|
+
@command_desc_buf, @command_usage_buf, @command_example_buf = [], [], []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def desc(str)
|
31
|
+
@command_desc_buf << str
|
32
|
+
end
|
33
|
+
|
34
|
+
def usage(str)
|
35
|
+
@command_usage_buf << str
|
36
|
+
end
|
37
|
+
|
38
|
+
def example(str)
|
39
|
+
@command_example_buf << str
|
40
|
+
end
|
41
|
+
|
42
|
+
def print_usage(command_name, output_io)
|
43
|
+
if @command_tbl[command_name]
|
44
|
+
output_io.puts ":#{command_name}".colorize(:light_blue)
|
45
|
+
output_io.puts @command_desc_tbl[command_name].map{|x| " " + x}.join("\n")
|
46
|
+
if @command_usage_tbl[command_name].size > 0
|
47
|
+
output_io.puts " Usage:".colorize(:green)
|
48
|
+
output_io.puts @command_usage_tbl[command_name].map{|x| " " + x}.join("\n")
|
49
|
+
end
|
50
|
+
if @command_example_tbl[command_name].size > 0
|
51
|
+
output_io.puts " Example:".colorize(:green)
|
52
|
+
output_io.puts @command_example_tbl[command_name].map{|x| " " + x}.join("\n")
|
53
|
+
end
|
54
|
+
return nil
|
55
|
+
else
|
56
|
+
return :command_not_found
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_all_usages(output_io)
|
61
|
+
@command_tbl.keys.sort.each do |name|
|
62
|
+
print_usage(name, output_io)
|
63
|
+
end
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def exec(command_name, arg, readline_id)
|
68
|
+
if @command_tbl[command_name]
|
69
|
+
@interpreter.instance_exec(arg, command_name, readline_id, &@command_tbl[command_name])
|
70
|
+
else
|
71
|
+
@interpreter.puts "Error: undefined command `#{command_name}'"
|
72
|
+
return :exec_error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def completion_proc
|
77
|
+
proc do |s|
|
78
|
+
@command_names.select{|name| name.index(s) == 0}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.make(interpreter)
|
83
|
+
CommandManager.new(interpreter) do
|
84
|
+
|
85
|
+
desc "Showing object type by specifying it's name."
|
86
|
+
example "data x = 1"
|
87
|
+
example ":t x"
|
88
|
+
command "t" do |arg|
|
89
|
+
name = arg.strip
|
90
|
+
if f = @top[:dict][:func_space][name]
|
91
|
+
puts "func #{name} : " + f.get[:params].map{|x| x[:typing].inspect}.join(", ") +
|
92
|
+
" -> " + f.get[:typing].inspect
|
93
|
+
end
|
94
|
+
if d = @top[:dict][:data_space][name]
|
95
|
+
puts "data #{name} : " + d.get[:typing].inspect
|
96
|
+
end
|
97
|
+
if t = @top[:dict][:type_space][name]
|
98
|
+
case t.get
|
99
|
+
when TypeDef
|
100
|
+
puts "Type #{name} : " + t.get[:tvalues][0][:typing].inspect
|
101
|
+
when PrimTypeDef
|
102
|
+
puts "PrimType #{name} : " + name
|
103
|
+
end
|
104
|
+
end
|
105
|
+
if c = @top[:dict][:const_space][name]
|
106
|
+
puts "constructor #{name} : " + c.get[:params].map{|x| x[:typing].inspect}.join(", ") +
|
107
|
+
" -> " + c.get[:typing].inspect
|
108
|
+
end
|
109
|
+
if n = @top[:dict][:node_space][name]
|
110
|
+
puts "node #{name} : " + n.get[:typing].inspect
|
111
|
+
end
|
112
|
+
next nil
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "Showing internal AST by specifying element's name."
|
116
|
+
command "ast" do |arg|
|
117
|
+
name = arg.strip
|
118
|
+
if f = @top[:dict][:func_space][name]
|
119
|
+
pp f.get
|
120
|
+
elsif d = @top[:dict][:data_space][name]
|
121
|
+
pp d.get
|
122
|
+
elsif t = @top[:dict][:type_space][name]
|
123
|
+
pp t.get
|
124
|
+
elsif c = @top[:dict][:const_space][name]
|
125
|
+
pp c.get
|
126
|
+
elsif n = @top[:dict][:node_space][name]
|
127
|
+
pp n.get
|
128
|
+
elsif name == "top"
|
129
|
+
pp @top
|
130
|
+
elsif name == "ifuncs"
|
131
|
+
pp @top[:dict][:ifuncs_space].keys
|
132
|
+
elsif name == "itypes"
|
133
|
+
pp @top[:dict][:itypes_space].keys
|
134
|
+
else
|
135
|
+
puts "Error: `#{name}' is not found"
|
136
|
+
next :target_not_found
|
137
|
+
end
|
138
|
+
next nil
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "Testing two expression's equality."
|
142
|
+
usage ":assert-equals <expected-exp>, <testing-exp>"
|
143
|
+
command "assert-equals" do |arg, c, rid|
|
144
|
+
if exp = str_to_exp("Pair(#{arg})")
|
145
|
+
val1 = Evaluater.eval_exp(@top, exp[:args][0])
|
146
|
+
val2 = Evaluater.eval_exp(@top, exp[:args][1])
|
147
|
+
if val1 == val2
|
148
|
+
nil
|
149
|
+
else
|
150
|
+
puts "Assertion failed".colorize(:red)
|
151
|
+
puts "Description: #{arg}"
|
152
|
+
puts "Type: #{exp[:args][0][:typing].inspect.colorize(:green)}"
|
153
|
+
puts "Expected: #{Evaluater.value_to_s(val1)}"
|
154
|
+
puts "Actual: #{Evaluater.value_to_s(val2)}"
|
155
|
+
:assertion_error
|
156
|
+
end
|
157
|
+
else
|
158
|
+
:command_format_error
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
desc "Executing all commands embedded on source-files."
|
163
|
+
command "exec-embedded-commands" do
|
164
|
+
exec_embedded_commands()
|
165
|
+
end
|
166
|
+
|
167
|
+
desc "Define documentation about function. (in preparation)"
|
168
|
+
command "set-func-doc" do |arg|
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
|
172
|
+
desc "Testing node as function."
|
173
|
+
usage ":assert-node <node-name> <input-exp>* => <expected-output-exp>"
|
174
|
+
example ":assert-node mynode 1, 2 => 3"
|
175
|
+
command "assert-node" do |arg|
|
176
|
+
if arg =~ /^\s*([a-z][a-zA-Z0-9]*)\s+(.*)=>(.*)$/
|
177
|
+
n = @top[:dict][:node_space][$1]
|
178
|
+
if n && n.get.is_a?(NodeDef)
|
179
|
+
node_def = n.get
|
180
|
+
types = ["Unit", "Unit"] + node_def[:params].map{|x| x[:typing].to_uniq_str}
|
181
|
+
exp_str = ($2.strip == "" ? "(Unit, Unit)" : "(Unit, Unit, #{$2.strip})")
|
182
|
+
if a_exp = str_to_exp(exp_str, "(#{types.join(", ")})")
|
183
|
+
v1 = Evaluater.eval_node_as_func(@top, node_def, a_exp[:args].drop(2))
|
184
|
+
if $3.strip == "skip"
|
185
|
+
v2 = :skip
|
186
|
+
elsif r_exp = str_to_exp($3.strip, "#{node_def[:typing].to_uniq_str}")
|
187
|
+
v2 = Evaluater.eval_exp(@top, r_exp)
|
188
|
+
else
|
189
|
+
puts "Error: invalid expected-return-expression"
|
190
|
+
next :assert_node_error1
|
191
|
+
end
|
192
|
+
if v1 == v2
|
193
|
+
next nil
|
194
|
+
else
|
195
|
+
puts "Node Assertion failed".colorize(:red)
|
196
|
+
puts "Description: #{arg}"
|
197
|
+
puts "Expected: #{Evaluater.value_to_s(v2)}"
|
198
|
+
puts "Actual: #{Evaluater.value_to_s(v1)}"
|
199
|
+
next :assertion_error
|
200
|
+
end
|
201
|
+
else
|
202
|
+
puts "Error: invalid node-argument-expression"
|
203
|
+
next :assert_node_error2
|
204
|
+
end
|
205
|
+
else
|
206
|
+
puts "Error: invalid node name #{$1}"
|
207
|
+
next :assert_node_error3
|
208
|
+
end
|
209
|
+
else
|
210
|
+
next :command_format_error
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
desc "Testing whole-module by feeding inputs."
|
215
|
+
usage ":assert-module <input-exp>* => <expected-ouput-exp>*"
|
216
|
+
example ":assert-module 1, 2 => 2, 4"
|
217
|
+
command "assert-module" do |arg|
|
218
|
+
if arg =~ /^(.*)=>(.*)$/
|
219
|
+
input_types = ["Unit", "Unit"] + @top[:inputs].map{|x| x[:typing].to_uniq_str}
|
220
|
+
exp_str = ($1.strip == "" ? "(Unit, Unit)" : "(Unit, Unit, #{$1.strip})")
|
221
|
+
input_exps = str_to_exp(exp_str, "(#{input_types.join(", ")})")
|
222
|
+
output_types = @top[:outputs].map{|x| x[:typing].to_uniq_str}
|
223
|
+
output_exps = str_to_exp("(Unit, #{$2})", "(Unit, #{output_types.join(", ")})")
|
224
|
+
if input_exps == nil || output_exps == nil
|
225
|
+
puts "Error: invalid expression"
|
226
|
+
next :assert_module_error1
|
227
|
+
end
|
228
|
+
# evaluate
|
229
|
+
last_state = @current_state ? @current_state.clone : nil
|
230
|
+
@current_state = {}
|
231
|
+
@node_replacement ||= {}
|
232
|
+
output_vals = Evaluater.eval_module(@top, input_exps[:args].drop(2),
|
233
|
+
@current_state, last_state, @node_replacement)
|
234
|
+
expected_output_vals = output_exps[:args].drop(1).map{|x| Evaluater.eval_exp(@top, x)}
|
235
|
+
# assert
|
236
|
+
if expected_output_vals != output_vals
|
237
|
+
puts "Module Assertion failed".colorize(:red)
|
238
|
+
puts "Description: #{arg}"
|
239
|
+
puts "Expected: #{expected_output_vals.map{|x| Evaluater.value_to_s(x)}.join(", ")}"
|
240
|
+
puts "Actual: #{output_vals.map{|x| Evaluater.value_to_s(x)}.join(", ")}"
|
241
|
+
:assertion_error
|
242
|
+
else
|
243
|
+
nil
|
244
|
+
end
|
245
|
+
else
|
246
|
+
:command_format_error
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
desc "Testing expression's type."
|
251
|
+
usage ":assert-type: <exp> => <type>"
|
252
|
+
command "assert-type" do |arg|
|
253
|
+
if arg =~ /^(.*)=>(.*)$/
|
254
|
+
if exp = str_to_exp($1.strip)
|
255
|
+
if exp[:typing].to_uniq_str == $2.strip
|
256
|
+
next nil
|
257
|
+
else
|
258
|
+
puts "Type Assertion failed".colorize(:red)
|
259
|
+
puts "Description: #{$1.strip}"
|
260
|
+
puts "Expected: #{$2.strip}"
|
261
|
+
puts "Actual: #{exp[:typing].to_uniq_str}"
|
262
|
+
next :assertion_error
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
next :command_format_error
|
267
|
+
end
|
268
|
+
|
269
|
+
desc "Testing that specified command finishes with specified error-code"
|
270
|
+
usage ":assert-error <expected-error-code> => <testing-command>"
|
271
|
+
example ":assert-error assertion_error => :assert-type 1 => Double"
|
272
|
+
command "assert-error" do |arg|
|
273
|
+
if arg =~ /^\s*([a-z][a-zA-Z0-9_]*)\s*=>\s*(.*)$/
|
274
|
+
expected_error_code = $1
|
275
|
+
res = disable_io{ process_repl_line($2) }
|
276
|
+
if res.to_s == expected_error_code
|
277
|
+
next nil
|
278
|
+
else
|
279
|
+
puts "Error-Assertion error"
|
280
|
+
puts "Expected error-code: #{expected_error_code}"
|
281
|
+
puts "Actual error-code: #{res}"
|
282
|
+
next :assertion_error
|
283
|
+
end
|
284
|
+
else
|
285
|
+
next :command_format_error
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
desc "Replace one node to another like Stab."
|
290
|
+
desc "currently, this is only for testing (command-line assertion)."
|
291
|
+
usage ":replace-node <replaced-node-name> => <alternative-node-name>"
|
292
|
+
command "replace-node" do |arg|
|
293
|
+
if arg =~ /^\s*([a-z][a-zA-Z0-9]*)\s*=>\s*([a-z][a-zA-Z0-9]*)\s*$/
|
294
|
+
real_n_ln, dummy_n_ln = @top[:dict][:node_space][$1], @top[:dict][:node_space][$2]
|
295
|
+
unless real_n_ln
|
296
|
+
puts "Error: Node `#{$1}' is undefined"
|
297
|
+
next :replace_node_err1
|
298
|
+
end
|
299
|
+
unless dummy_n_ln
|
300
|
+
puts "Error: Node `#{$2}' is undefined"
|
301
|
+
next :replace_node_err2
|
302
|
+
end
|
303
|
+
unless real_n_ln.get[:typing].to_uniq_str == dummy_n_ln.get[:typing].to_uniq_str
|
304
|
+
puts "Error: Types of Real-Node `#{$1}' and Dummy-Node `#{$2}' are different"
|
305
|
+
puts "#{$1} : #{real_n_ln.get[:typing].to_uniq_str}"
|
306
|
+
puts "#{$2} : #{dummy_n_ln.get[:typing].to_uniq_str}"
|
307
|
+
next :replace_node_err3
|
308
|
+
end
|
309
|
+
collect_deps = proc do |node|
|
310
|
+
if node.is_a?(NodeDef)
|
311
|
+
[node] + node[:params].reject{|x| x[:last]}.map{|p|
|
312
|
+
collect_deps.call(@top[:dict][:node_space][p[:name][:desc]].get)
|
313
|
+
}.flatten
|
314
|
+
else
|
315
|
+
[node]
|
316
|
+
end
|
317
|
+
end
|
318
|
+
c1 = collect_deps.call(dummy_n_ln.get).find{|x| x[:name] == real_n_ln.get[:name]}
|
319
|
+
c2 = collect_deps.call(real_n_ln.get).find{|x| x[:name] == dummy_n_ln.get[:name]}
|
320
|
+
unless c1 == nil && c2 == nil
|
321
|
+
puts "Error: Real-Node `#{$1}' and Dummy-Node `#{$2}' are on depending relation"
|
322
|
+
next :replace_node_err4
|
323
|
+
end
|
324
|
+
if real_n_ln.get[:init_exp] && !dummy_n_ln.get[:init_exp]
|
325
|
+
puts "Error: Dummy-Node `#{$2}' should have init-exp"
|
326
|
+
next :replace_node_err5
|
327
|
+
end
|
328
|
+
@node_replacement ||= {}
|
329
|
+
@node_replacement[$1] = dummy_n_ln.get
|
330
|
+
next nil
|
331
|
+
else
|
332
|
+
next :command_format_error
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
desc "Compiling module-file into c-program code."
|
337
|
+
desc "Target file-name is currently fixed..."
|
338
|
+
desc "(module-name is used and files are dumped on current-dir)"
|
339
|
+
usage ":compile"
|
340
|
+
command "compile" do
|
341
|
+
next compile_default()
|
342
|
+
end
|
343
|
+
|
344
|
+
desc "Compiling module-file into graphviz-source code (.dot file)."
|
345
|
+
desc "If file-name is given as a command-argument, the code is output to it."
|
346
|
+
desc "Otherwise, the code is output on console."
|
347
|
+
example ":compile-dot graph.dot"
|
348
|
+
command "compile-dot" do |arg|
|
349
|
+
if arg.strip != ""
|
350
|
+
File.open(arg, "w") do |f|
|
351
|
+
Graphviz.compile(@top, f)
|
352
|
+
end
|
353
|
+
else
|
354
|
+
Graphviz.compile(@top, @output_io)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
desc "Showing usage of all commands."
|
359
|
+
command "commands" do
|
360
|
+
@command_manager.print_all_usages(@output_io)
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|