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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -12
  3. data/bin/emfrp +4 -1
  4. data/examples/LCDClock/LCDClock.mfrp +93 -93
  5. data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
  6. data/examples/LCDClock/README.md +24 -24
  7. data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
  8. data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
  9. data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
  10. data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
  11. data/lib/emfrp/compile/c/alloc.rb +200 -200
  12. data/lib/emfrp/compile/c/codegen.rb +18 -18
  13. data/lib/emfrp/compile/c/codegen_context.rb +218 -218
  14. data/lib/emfrp/compile/c/monofy.rb +185 -185
  15. data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
  16. data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
  17. data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
  18. data/lib/emfrp/compile_error.rb +95 -95
  19. data/lib/emfrp/interpreter/command_manager.rb +367 -367
  20. data/lib/emfrp/interpreter/evaluater.rb +146 -146
  21. data/lib/emfrp/interpreter/file_loader.rb +52 -52
  22. data/lib/emfrp/interpreter/interpreter.rb +200 -195
  23. data/lib/emfrp/parser/expression.rb +386 -386
  24. data/lib/emfrp/parser/misc.rb +184 -184
  25. data/lib/emfrp/parser/newnode_convert.rb +72 -72
  26. data/lib/emfrp/parser/operator.rb +25 -25
  27. data/lib/emfrp/parser/parser.rb +150 -150
  28. data/lib/emfrp/parser/parsing_error.rb +49 -49
  29. data/lib/emfrp/parser/toplevel.rb +555 -555
  30. data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
  31. data/lib/emfrp/syntax.rb +171 -171
  32. data/lib/emfrp/typing/typing_error.rb +47 -47
  33. data/lib/emfrp/typing/union_type.rb +197 -197
  34. data/lib/emfrp/version.rb +1 -1
  35. data/mfrp_include/Std.mfrp +122 -122
  36. data/tests/Rakefile +8 -8
  37. data/tests/Rakefile.common +27 -27
  38. data/tests/command/Rakefile +2 -2
  39. data/tests/command/ReplaceNode.mfrp +39 -39
  40. data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
  41. data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
  42. data/tests/compiler/ComplexDataType/Rakefile +2 -2
  43. data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
  44. data/tests/compiler/ComplexDataType/in.txt +5 -5
  45. data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
  46. data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
  47. data/tests/compiler/LCDClock/Rakefile +2 -2
  48. data/tests/compiler/LCDClock/expected_out.txt +0 -0
  49. data/tests/compiler/LCDClock/in.txt +0 -0
  50. data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
  51. data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
  52. data/tests/compiler/LCDPositioner/Rakefile +2 -2
  53. data/tests/compiler/LCDPositioner/graph.dot +0 -0
  54. data/tests/compiler/LCDPositioner/graph.png +0 -0
  55. data/tests/compiler/Rakefile +8 -8
  56. data/tests/compiler/Rakefile.common +23 -23
  57. data/tests/compiler/UseData/Rakefile +2 -2
  58. data/tests/compiler/UseData/UseData.mfrp +8 -8
  59. data/tests/compiler/UseSubModule/Rakefile +2 -2
  60. data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
  61. data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
  62. data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
  63. data/tests/core/FromAnnotation.mfrp +18 -18
  64. data/tests/core/Last.mfrp +10 -10
  65. data/tests/core/Rakefile +2 -2
  66. data/tests/core/TypingTest.mfrp +11 -11
  67. data/tests/core/WithoutInputs.mfrp +19 -19
  68. data/tests/load_time_error/Rakefile +32 -32
  69. data/tests/load_time_error/TypeMismatch.mfrp +4 -4
  70. 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