emfrp 0.0.1

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +28 -0
  5. data/README.md +27 -0
  6. data/Rakefile +2 -0
  7. data/bin/emfrp +21 -0
  8. data/bin/emfrpi +24 -0
  9. data/emfrp.gemspec +26 -0
  10. data/examples/LCDPositioner/LCDPositioner.c +278 -0
  11. data/examples/LCDPositioner/LCDPositioner.h +6 -0
  12. data/examples/LCDPositioner/LCDPositioner.mfrp +30 -0
  13. data/examples/LCDPositioner/LCDPositionerMain.c +15 -0
  14. data/examples/LCDPositioner/LCDPositionerMain.c.gen +11 -0
  15. data/examples/LCDPositioner/graph.dot +31 -0
  16. data/examples/LCDPositioner/graph.png +0 -0
  17. data/examples/MostDistantPoint/MostDistantPoint.c +199 -0
  18. data/examples/MostDistantPoint/MostDistantPoint.h +6 -0
  19. data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -0
  20. data/examples/MostDistantPoint/MostDistantPointMain.c +14 -0
  21. data/examples/MostDistantPoint/graph.dot +12 -0
  22. data/examples/MostDistantPoint/graph.png +0 -0
  23. data/lib/emfrp/compile/c/alloc.rb +200 -0
  24. data/lib/emfrp/compile/c/codegen.rb +18 -0
  25. data/lib/emfrp/compile/c/codegen_context.rb +215 -0
  26. data/lib/emfrp/compile/c/monofy.rb +185 -0
  27. data/lib/emfrp/compile/c/syntax_codegen.rb +364 -0
  28. data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -0
  29. data/lib/emfrp/compile/graphviz/graphviz.rb +49 -0
  30. data/lib/emfrp/compile_error.rb +95 -0
  31. data/lib/emfrp/interpreter/command_manager.rb +367 -0
  32. data/lib/emfrp/interpreter/evaluater.rb +146 -0
  33. data/lib/emfrp/interpreter/file_loader.rb +52 -0
  34. data/lib/emfrp/interpreter/interpreter.rb +195 -0
  35. data/lib/emfrp/parser/expression.rb +386 -0
  36. data/lib/emfrp/parser/misc.rb +184 -0
  37. data/lib/emfrp/parser/operator.rb +25 -0
  38. data/lib/emfrp/parser/parser.rb +145 -0
  39. data/lib/emfrp/parser/parsing_error.rb +49 -0
  40. data/lib/emfrp/parser/toplevel.rb +523 -0
  41. data/lib/emfrp/pre_convert/alpha_convert.rb +119 -0
  42. data/lib/emfrp/pre_convert/make_name_dict.rb +96 -0
  43. data/lib/emfrp/pre_convert/node_check.rb +60 -0
  44. data/lib/emfrp/pre_convert/pre_convert.rb +32 -0
  45. data/lib/emfrp/syntax.rb +169 -0
  46. data/lib/emfrp/typing/typing.rb +256 -0
  47. data/lib/emfrp/typing/typing_error.rb +47 -0
  48. data/lib/emfrp/typing/union_type.rb +197 -0
  49. data/lib/emfrp/version.rb +3 -0
  50. data/lib/emfrp.rb +14 -0
  51. data/mfrp_include/Std.mfrp +122 -0
  52. data/tests/Rakefile +8 -0
  53. data/tests/Rakefile.common +27 -0
  54. data/tests/command/Rakefile +2 -0
  55. data/tests/command/ReplaceNode.mfrp +39 -0
  56. data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -0
  57. data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -0
  58. data/tests/compiler/ComplexDataType/Rakefile +2 -0
  59. data/tests/compiler/ComplexDataType/actual_out.txt +5 -0
  60. data/tests/compiler/ComplexDataType/expected_out.txt +5 -0
  61. data/tests/compiler/ComplexDataType/graph.png +0 -0
  62. data/tests/compiler/ComplexDataType/in.txt +5 -0
  63. data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -0
  64. data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -0
  65. data/tests/compiler/LCDPositioner/Rakefile +2 -0
  66. data/tests/compiler/LCDPositioner/actual_out.txt +9 -0
  67. data/tests/compiler/LCDPositioner/expected_out.txt +9 -0
  68. data/tests/compiler/LCDPositioner/graph.dot +31 -0
  69. data/tests/compiler/LCDPositioner/graph.png +0 -0
  70. data/tests/compiler/LCDPositioner/in.txt +11 -0
  71. data/tests/compiler/Rakefile +8 -0
  72. data/tests/compiler/Rakefile.common +23 -0
  73. data/tests/core/FromAnnotation.mfrp +18 -0
  74. data/tests/core/Last.mfrp +10 -0
  75. data/tests/core/Rakefile +2 -0
  76. data/tests/core/TypingTest.mfrp +11 -0
  77. data/tests/core/WithoutInputs.mfrp +19 -0
  78. data/tests/load_time_error/Rakefile +32 -0
  79. data/tests/load_time_error/TypeMismatch.mfrp +4 -0
  80. metadata +180 -0
@@ -0,0 +1,523 @@
1
+ require 'parser_combinator/string_parser'
2
+
3
+ module Emfrp
4
+ class Parser < ParserCombinator::StringParser
5
+
6
+ # Top Level Definition Statements
7
+ # --------------------
8
+
9
+ parser :module_top_def do
10
+ (data_def ^ func_def ^ node_def ^ type_def ^ infix_def ^ primtype_def ^ primfunc_def ^ command_def).map do |x|
11
+ [x].flatten
12
+ end
13
+ end
14
+
15
+ parser :material_top_def do
16
+ (data_def ^ func_def ^ type_def ^ infix_def ^ primtype_def ^ primfunc_def ^ command_def).map do |x|
17
+ [x].flatten
18
+ end
19
+ end
20
+
21
+ parser :appendable_top_def do
22
+ (data_def ^ func_def ^ type_def).map do |x|
23
+ [x].flatten
24
+ end
25
+ end
26
+
27
+ parser :module_or_material_file do
28
+ (module_file ^ material_file).err("file", "module-file or material_file")
29
+ end
30
+
31
+ parser :module_file do
32
+ place = "module-file"
33
+ seq(
34
+ many(ws),
35
+ symbol("module").name(:keyword1),
36
+ many1(ws).err(place, "space after `module' keyword"),
37
+ ident_begin_upper.name(:name),
38
+ opt_fail(
39
+ many1(ws) > symbol("in") > many1(ws) >
40
+ many1_fail(input_def, comma_separator).err(place, "definitions of inputs")
41
+ ).map(&:flatten).name(:inputs),
42
+ many1(ws).err(place, "spaec after definitions of input"),
43
+ symbol("out").err(place, "keyword `out'"),
44
+ many1(ws).err(place, "space after keyword `out'"),
45
+ many1_fail(output_def, comma_separator).err(place, "definitions of outputs").name(:outputs),
46
+ opt_fail(
47
+ many1(ws) >
48
+ symbol("use") >
49
+ many1(ws).err(place, "space after keyword `use'") >
50
+ many1_fail(load_path, comma_separator).err(place, "definitions of include-files")
51
+ ).map{|x| x == [] ? [] : x[0]}.name(:uses),
52
+ many1(ws).err(place, "space before top-definitions"),
53
+ many_fail(module_top_def, many(ws)).map(&:flatten).err(place, "top definitions").name(:defs),
54
+ many(ws),
55
+ end_of_input.err("module-file", "valid end of file")
56
+ ).map do |x|
57
+ t = Top.new(:inputs => x[:inputs], :outputs => x[:outputs], :uses => x[:uses], :module_name => x[:name])
58
+ x[:defs].each do |d|
59
+ k = case d
60
+ when DataDef then :datas
61
+ when FuncDef then :funcs
62
+ when NodeDef then :nodes
63
+ when TypeDef then :types
64
+ when InfixDef then :infixes
65
+ when PrimTypeDef then :ptypes
66
+ when PrimFuncDef then :pfuncs
67
+ when CommandDef then :commands
68
+ end
69
+ t[k] << d
70
+ end
71
+ t
72
+ end
73
+ end
74
+
75
+ parser :material_file do
76
+ place = "material-file"
77
+ seq(
78
+ many(ws),
79
+ symbol("material").name(:keyword1),
80
+ many1(ws),
81
+ ident_begin_upper.name(:name),
82
+ opt_fail(
83
+ many1(ws) >
84
+ symbol("use") >
85
+ many1(ws) >
86
+ many1_fail(load_path, comma_separator)
87
+ ).to_nil.name(:uses),
88
+ many1(ws),
89
+ many_fail(material_top_def, many(ws)).map(&:flatten).name(:defs),
90
+ many(ws),
91
+ end_of_input.err("module", "valid end of file")
92
+ ).map do |x|
93
+ t = Top.new(:uses => x[:uses], :module_name => nil)
94
+ x[:defs].each do |d|
95
+ k = case d
96
+ when DataDef then :datas
97
+ when FuncDef then :funcs
98
+ when TypeDef then :types
99
+ when InfixDef then :infixes
100
+ when PrimTypeDef then :ptypes
101
+ when PrimFuncDef then :pfuncs
102
+ when CommandDef then :commands
103
+ end
104
+ t[k] << d
105
+ end
106
+ t
107
+ end
108
+ end
109
+
110
+ parser :oneline_file do
111
+ many(ws) > appendable_top_def < many(ws) < end_of_input
112
+ end
113
+
114
+ parser :load_path do
115
+ many1(ident_begin_upper, str("."))
116
+ end
117
+
118
+ parser :input_def do
119
+ seq(
120
+ var_name.name(:name),
121
+ opt_fail(
122
+ symbol("(") > exp < symbol(")")
123
+ ).to_nil.name(:init_exp),
124
+ many(ws),
125
+ str(":"),
126
+ many(ws),
127
+ type.err("param-def", "type").name(:type)
128
+ ).map do |x|
129
+ InputDef.new(x.to_h)
130
+ end
131
+ end
132
+
133
+ parser :output_def do
134
+ seq(
135
+ var_name.name(:name),
136
+ opt_fail(
137
+ many(ws) > str(":") > many(ws) >
138
+ type.err("param-def", "type")
139
+ ).to_nil.name(:type)
140
+ ).map do |x|
141
+ OutputDef.new(x.to_h)
142
+ end
143
+ end
144
+
145
+ parser :data_def do # -> DataDef
146
+ seq(
147
+ symbol("data").name(:keyword),
148
+ many1(ws),
149
+ data_name.err("data-def", "name of data").name(:name),
150
+ opt_fail(
151
+ many(ws) >
152
+ str(":") >
153
+ many(ws) >
154
+ type.err("data-def", "type")
155
+ ).to_nil.name(:type),
156
+ many(ws),
157
+ str("="),
158
+ many(ws),
159
+ exp.err("data-def", "valid expression").name(:exp),
160
+ end_of_def.err("data-def", "valid end of data-def")
161
+ ).map do |x|
162
+ DataDef.new(x.to_h)
163
+ end
164
+ end
165
+
166
+ parser :func_def do # -> FuncDef
167
+ seq(
168
+ symbol("func").name(:keyword),
169
+ many1(ws),
170
+ (func_name | operator).err("func-def", "name of func").name(:name),
171
+ many(ws),
172
+ str("("),
173
+ many1_fail(func_param_def, comma_separator).err("func-def", "list of param for function").name(:params),
174
+ str(")"),
175
+ opt_fail(
176
+ many(ws) >
177
+ str(":") >
178
+ many(ws) >
179
+ type_with_var.err("func-def", "type of return value")
180
+ ).to_nil.name(:type),
181
+ many(ws),
182
+ str("="),
183
+ many(ws),
184
+ exp.err("func-def", "valid expression").name(:exp),
185
+ end_of_def.err("func-def", "valid end of func-def")
186
+ ).map do |x|
187
+ FuncDef.new(x.to_h)
188
+ end
189
+ end
190
+
191
+ parser :node_def do # -> [NodeDef]
192
+ seq(
193
+ symbol("node").name(:keyword),
194
+ opt_fail(many1(ws) > init_def).to_nil.name(:init_exp),
195
+ opt_fail(many1(ws) > from_def).to_nil.name(:params),
196
+ many1(ws),
197
+ pattern.name(:pattern),
198
+ many(ws),
199
+ str("="),
200
+ many(ws),
201
+ exp.err("node-def", "body").name(:exp),
202
+ end_of_def.err("node-def", "valid end of node-def")
203
+ ).map do |x|
204
+ refs = x[:pattern].find_refs
205
+ if x[:pattern][:ref]
206
+ whole_name = x[:pattern][:ref]
207
+ else
208
+ whole_name = SSymbol.new(
209
+ :desc => "tmpNode" + x[:pattern].object_id.to_s,
210
+ :keyword => x[:pattern].deep_copy
211
+ )
212
+ end
213
+ whole_node = NodeDef.new(
214
+ :keyword => x[:keyword],
215
+ :init_exp => x[:init_exp],
216
+ :params => x[:params],
217
+ :exp => x[:exp],
218
+ :type => x[:pattern][:type],
219
+ :name => whole_name
220
+ )
221
+ if refs.size == 0
222
+ []
223
+ else
224
+ gen = proc do |left_exp, ref|
225
+ c = Case.new(:pattern => x[:pattern].deep_copy, :exp => VarRef.new(:name => ref))
226
+ MatchExp.new(:exp => left_exp, :cases => [c])
227
+ end
228
+ child_nodes = refs.reject{|x| x == whole_name}.map do |ref|
229
+ init_exp = x[:init_exp] ? gen.call(x[:init_exp].deep_copy, ref) : nil
230
+ params = [NodeRef.new(:name => whole_name, :as => whole_name, :last => false)]
231
+ exp = gen.call(VarRef.new(:name => whole_name), ref)
232
+ NodeDef.new(
233
+ :keyword => x[:keyword],
234
+ :init_exp => init_exp,
235
+ :params => params,
236
+ :name => ref,
237
+ :type => nil,
238
+ :exp => exp
239
+ )
240
+ end
241
+ [whole_node] + child_nodes
242
+ end
243
+ end
244
+ end
245
+
246
+ parser :type_def do # -> TypeDef
247
+ seq(
248
+ symbol("type").name(:keyword),
249
+ opt(many1(ws) > str("static")).map{|x| x == [] ? false : true}.name(:static),
250
+ many1(ws),
251
+ type_with_param.err("type-def", "type with param").name(:type),
252
+ many(ws),
253
+ opt_fail(
254
+ seq(
255
+ str("["),
256
+ many1_fail(type_var, comma_separator).err("type-def", "valid params"),
257
+ str("]").err("type-def", "']' after params")
258
+ ).map{|x| x[1]}
259
+ ).map{|x| x.flatten}.name(:params),
260
+ many(ws),
261
+ str("=").err("type-def", "'='"),
262
+ many(ws),
263
+ many1_fail(tvalue_def, or_separator).err("type-def", "value constructors").name(:tvalues),
264
+ end_of_def.err("type-def", "valid end of type-def")
265
+ ).map do |x|
266
+ TypeDef.new(x.to_h, :name => x[:type][:name])
267
+ end
268
+ end
269
+
270
+ parser :infix_def do # -> InfixDef
271
+ seq(
272
+ (symbol("infixl") | symbol("infixr") | symbol("infix")).name(:type),
273
+ opt(many1(ws) > digit_symbol).to_nil.name(:priority),
274
+ many1(ws),
275
+ operator_general.err("infix-def", "operator").name(:op),
276
+ end_of_def
277
+ ). map do |x|
278
+ InfixDef.new(x.to_h)
279
+ end
280
+ end
281
+
282
+ parser :primtype_def do
283
+ seq(
284
+ symbol("primtype").name(:keyword),
285
+ many1(ws),
286
+ type_symbol.err("primtype-def", "type symbol to be define").name(:name),
287
+ many(ws),
288
+ str("=").err("primtype-def", "'='"),
289
+ many(ws),
290
+ many1(foreign_exp, comma_separator).err("primtype-def", "foreign-definitions").name(:foreigns),
291
+ end_of_def.err("primtype-def", "valid end of primtype-def")
292
+ ).map do |x|
293
+ PrimTypeDef.new(x.to_h)
294
+ end
295
+ end
296
+
297
+ parser :primfunc_def do
298
+ seq(
299
+ symbol("primfunc").name(:keyword),
300
+ many1(ws),
301
+ (func_name | operator).err("primfunc-def", "name of primfunc").name(:name),
302
+ many(ws),
303
+ str("("),
304
+ many1_fail(primfunc_param_def, comma_separator).err("primfunc-def", "list of param for function").name(:params),
305
+ str(")"),
306
+ many(ws),
307
+ str(":"),
308
+ many(ws),
309
+ type_with_var.err("func-def", "type of return value").name(:type),
310
+ many(ws),
311
+ str("=").err("primfunc-def", "'='"),
312
+ many(ws),
313
+ many1(foreign_exp, comma_separator).err("primfunc-def", "foreign-definitions").name(:foreigns),
314
+ end_of_def.err("primfunc-def", "valid end of primfunc-def")
315
+ ).map do |x|
316
+ PrimFuncDef.new(x.to_h)
317
+ end
318
+ end
319
+
320
+ parser :command_def do
321
+ seq(
322
+ symbol("#@").name(:keyword1),
323
+ many(non_newline).name(:command),
324
+ char("\n"),
325
+ many(str("#-") > many(non_newline) < char("\n")).name(:following_lines)
326
+ ).map do |x|
327
+ lines = [x[:command]] + x[:following_lines]
328
+ CommandDef.new(
329
+ :line_number => x[:keyword1][:start_pos][:line_number],
330
+ :file_name => x[:keyword1][:start_pos][:document_name],
331
+ :command_str => lines.map{|line| line.map(&:item).join}.join(" ")
332
+ )
333
+ end
334
+ end
335
+
336
+ # Func associated
337
+ # --------------------
338
+
339
+ parser :func_param_def do # -> ParamDef
340
+ seq(
341
+ var_name.name(:name),
342
+ opt_fail(
343
+ many(ws) >
344
+ str(":") >
345
+ many(ws) >
346
+ type_with_var.err("param-def", "type with type-var")
347
+ ).to_nil.name(:type)
348
+ ).map do |x|
349
+ ParamDef.new(x.to_h)
350
+ end
351
+ end
352
+
353
+ parser :primfunc_param_def do # -> ParamDef
354
+ seq(
355
+ var_name.name(:name),
356
+ many(ws),
357
+ str(":"),
358
+ many(ws),
359
+ type_with_var.err("param-def", "type with type-var").name(:type)
360
+ ).map do |x|
361
+ ParamDef.new(x.to_h)
362
+ end
363
+ end
364
+
365
+
366
+ # Body associated
367
+ # --------------------
368
+
369
+ parser :foreign_exp do
370
+ seq(
371
+ ident_begin_lower.name(:language),
372
+ symbol("{").name(:keyword1),
373
+ many(ws),
374
+ many1(notchar("}")).name(:items),
375
+ symbol("}").err("body-def", "'}' after c-expression").name(:keyword2)
376
+ ).map do |x|
377
+ ForeignExp.new(
378
+ :language => x[:language],
379
+ :keyword1 => x[:keyword1],
380
+ :keyword2 => x[:keyword2],
381
+ :desc => x[:items].map(&:item).join.strip,
382
+ )
383
+ end
384
+ end
385
+
386
+ # Node associated
387
+ # --------------------
388
+
389
+ parser :init_def do # -> InitDef
390
+ seq(
391
+ symbol("init").name(:keyword1),
392
+ many(ws),
393
+ str("["),
394
+ many(ws),
395
+ exp.name(:exp),
396
+ many(ws),
397
+ symbol("]").name(:keyword)
398
+ ).map do |x|
399
+ x[:exp]
400
+ end
401
+ end
402
+
403
+ parser :from_def do
404
+ seq(
405
+ symbol("from"),
406
+ str("[").err("from-def", "["),
407
+ many_fail(node_ref, comma_separator).err("from-def", "list of depended nodes").name(:params),
408
+ str("]").err("from-def", "]"),
409
+ ).map do |x|
410
+ x[:params]
411
+ end
412
+ end
413
+
414
+ parser :node_ref do
415
+ node_name_last | node_name_current
416
+ end
417
+
418
+ parser :node_name_last do
419
+ seq(
420
+ node_instance_name.name(:name),
421
+ symbol("@last").name(:keyword),
422
+ opt_fail(many(ws) > str("as") > many(ws) > var_name.err("node-parameter", "name as exposed")).to_nil.name(:as)
423
+ ).map do |x|
424
+ as = x[:as] || SSymbol.new(
425
+ :desc => x[:name][:desc] + "@last",
426
+ :start_pos => x[:name][:start_pos],
427
+ :end_pos => x[:keyword][:end_pos]
428
+ )
429
+ NodeRef.new(:last => true, :as => as, :name => x[:name])
430
+ end
431
+ end
432
+
433
+ parser :node_name_current do
434
+ seq(
435
+ node_instance_name.name(:name),
436
+ opt_fail(many(ws) > str("as") > many(ws) > var_name.err("node-parameter", "name as exposed")).to_nil.name(:as)
437
+ ).map do |x|
438
+ NodeRef.new(:last => false, :as => x[:as] || x[:name], :name => x[:name])
439
+ end
440
+ end
441
+
442
+ # Type associated
443
+ # --------------------
444
+
445
+ parser :type_with_args do |inner|
446
+ seq(
447
+ type_symbol.name(:name),
448
+ symbol("[").name(:keyword1),
449
+ many1_fail(inner, comma_separator).err("type", "list of type").name(:args),
450
+ symbol("]").err("type", "']'").name(:keyword2)
451
+ ).map do |x|
452
+ Type.new(x.to_h)
453
+ end
454
+ end
455
+
456
+ parser :type_without_args do
457
+ type_symbol.map do |x|
458
+ Type.new(:name => x, :args => [])
459
+ end
460
+ end
461
+
462
+ parser :type_tuple do |inner|
463
+ seq(
464
+ symbol("(").name(:keyword1),
465
+ many1_fail(inner, comma_separator).err("type", "list of type").name(:args),
466
+ symbol(")").err("type", "')'").name(:keyword2)
467
+ ).map do |x|
468
+ type_name = SSymbol.new(:desc => "Tuple" + x[:args].size.to_s)
469
+ Type.new(x.to_h, :name => type_name)
470
+ end
471
+ end
472
+
473
+ parser :type_symbol do
474
+ ident_begin_upper
475
+ end
476
+
477
+ parser :tvalue_symbol do
478
+ ident_begin_upper
479
+ end
480
+
481
+ parser :type_var do # => TypeVar
482
+ ident_begin_lower.map do |s|
483
+ TypeVar.new(:name => s)
484
+ end
485
+ end
486
+
487
+ parser :type do
488
+ type_with_args(type) ^ type_tuple(type) ^ type_without_args
489
+ end
490
+
491
+ parser :type_with_var do
492
+ type_with_args(type_with_var) ^ type_tuple(type_with_var) ^ type_without_args ^ type_var
493
+ end
494
+
495
+ parser :type_with_param do
496
+ type_with_args(type_var) ^ type_tuple(type_var) ^ type_without_args
497
+ end
498
+
499
+ parser :tvalue_def do # -> TValue
500
+ seq(
501
+ tvalue_symbol.name(:name),
502
+ opt_fail(
503
+ many(ws) >
504
+ str("(") >
505
+ many1_fail(tvalue_def_type, comma_separator) <
506
+ str(")").err("value-constructor-def", "')'")
507
+ ).map{|x| x.flatten}.name(:params),
508
+ ).map do |x|
509
+ TValue.new(x.to_h)
510
+ end
511
+ end
512
+
513
+ parser :tvalue_def_type do # -> TValueParam
514
+ colon = (many(ws) < str(":") < many(ws))
515
+ seq(
516
+ opt_fail(func_name < colon).to_nil.name(:name),
517
+ type_with_var.name(:type)
518
+ ).map do |x|
519
+ TValueParam.new(x.to_h)
520
+ end
521
+ end
522
+ end
523
+ end
@@ -0,0 +1,119 @@
1
+ module Emfrp
2
+ module AlphaConvert
3
+ extend self
4
+
5
+ def alpha_convert(top, syntax, tbl=nil)
6
+ tbl ||= Hash.new{|h,k| h[k] = []}
7
+ case syntax
8
+ when InputDef
9
+ alpha_convert(top, syntax[:init_exp], tbl) if syntax[:init_exp]
10
+ when NodeDef
11
+ alpha_convert(top, syntax[:init_exp], tbl) if syntax[:init_exp]
12
+ if syntax[:params]
13
+ check_duplicate_name(syntax[:params].map{|x| x[:name]})
14
+ vars = syntax[:params].map{|x| x[:as]}
15
+ check_duplicate_name(vars)
16
+ vars.each do |v|
17
+ tbl[v].push(syntax)
18
+ end
19
+ alpha_convert(top, syntax[:exp], tbl)
20
+ vars.each do |v|
21
+ tbl[v].pop
22
+ end
23
+ else
24
+ syntax[:params] = []
25
+ vars = (top[:nodes] + top[:inputs]).map{|x|
26
+ [x[:name], SSymbol.new(:desc => x[:name][:desc] + "@last")]
27
+ }.flatten
28
+ vars.each do |v|
29
+ tbl[v].push(syntax)
30
+ end
31
+ alpha_convert(top, syntax[:exp], tbl)
32
+ vars.each do |v|
33
+ tbl[v].pop
34
+ end
35
+ end
36
+ when FuncDef
37
+ vars = syntax[:params].map{|x| x[:name]}
38
+ check_duplicate_name(vars)
39
+ vars.each do |v|
40
+ tbl[v].push(syntax)
41
+ end
42
+ alpha_convert(top, syntax[:exp], tbl)
43
+ vars.each do |v|
44
+ tbl[v].pop
45
+ end
46
+ when DataDef
47
+ alpha_convert(top, syntax[:exp], tbl)
48
+ when Case
49
+ vars = syntax[:pattern].find_refs()
50
+ check_duplicate_name(vars)
51
+ vars.each do |v|
52
+ tbl[v].push(syntax)
53
+ end
54
+ alpha_convert(top, syntax[:exp], tbl)
55
+ vars.each do |v|
56
+ tbl[v].pop
57
+ end
58
+ when VarRef
59
+ if tbl[syntax[:name]].size == 0
60
+ if top[:dict][:data_space][syntax[:name][:desc]]
61
+ syntax[:binder] = top[:dict][:data_space][syntax[:name][:desc]]
62
+ else
63
+ PreConvert.err(:unbound, "Unbound variable `#{syntax[:name][:desc]}':\n", syntax)
64
+ end
65
+ else
66
+ binder = tbl[syntax[:name]].last
67
+ if binder.is_a?(NodeDef) && !binder[:params].find{|x| x[:as] == syntax[:name]}
68
+ if syntax[:name][:desc] =~ /^(.+)@last$/
69
+ name = SSymbol.new(:desc => $1)
70
+ last = true
71
+ else
72
+ name = syntax[:name]
73
+ last = false
74
+ end
75
+ binder[:params] << NodeRef.new(:as => syntax[:name], :name => name, :last => last)
76
+ end
77
+ syntax[:binder] = Link.new(binder)
78
+ end
79
+ when ValueConst, ValuePattern
80
+ name = syntax[:name][:desc]
81
+ if tvalue_link = top[:dict][:const_space][name]
82
+ tvalue = tvalue_link.get
83
+ if syntax[:args].size != tvalue[:params].size
84
+ s = "#{syntax[:args].size} for #{tvalue[:params].size}"
85
+ PreConvert.err(:arg_num, "Wrong number of arguments (#{s}) for `#{name}':\n", syntax)
86
+ end
87
+ else
88
+ PreConvert.err(:undef, "Undefined value-constructor `#{name}':\n", syntax)
89
+ end
90
+ alpha_convert(top, syntax.values, tbl)
91
+ when FuncCall
92
+ name = syntax[:name][:desc]
93
+ if func_link = top[:dict][:func_space][name]
94
+ f = func_link.get
95
+ if syntax[:args].size != f[:params].size
96
+ s = "#{syntax[:args].size} for #{f[:params].size}"
97
+ PreConvert.err(:arg_num, "Wrong number of arguments (#{s}) for `#{name}':\n", syntax)
98
+ end
99
+ else
100
+ PreConvert.err(:undef, "Undefined function `#{name}':\n", syntax)
101
+ end
102
+ alpha_convert(top, syntax.values, tbl)
103
+ when Syntax
104
+ alpha_convert(top, syntax.values, tbl)
105
+ when Array
106
+ syntax.each{|e| alpha_convert(top, e, tbl)}
107
+ end
108
+ end
109
+
110
+ def check_duplicate_name(names)
111
+ names.each do |name|
112
+ dups = names.select{|x| x == name}
113
+ if dups.size > 1
114
+ PreConvert.err(:dup, "Duplicate variable names `#{name[:desc]}':\n", *dups)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end