emfrp 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|