emfrp 0.1.2 → 0.1.3

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