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,119 +1,119 @@
1
- require 'emfrp/syntax'
2
-
3
- module Emfrp
4
- class FuncCall
5
- def codegen(ct, stmts)
6
- name = ct.func_name(self[:name][:desc], self[:typing], self[:args].map{|x| x[:typing]})
7
- "#{name}(#{self[:args].map{|x| x.codegen(ct, stmts)}.join(", ")})"
8
- end
9
- end
10
-
11
- class ValueConst
12
- def codegen(ct, stmts)
13
- if ct.tdef(self[:typing]).enum?(ct)
14
- ct.tdef(self[:typing])[:tvalues].index{|t| t[:name] == self[:name]}.to_s
15
- else
16
- name = ct.constructor_name(self[:name][:desc], self[:typing])
17
- "#{name}(#{self[:args].map{|x| x.codegen(ct, stmts)}.join(", ")})"
18
- end
19
- end
20
- end
21
-
22
- class ParenthExp
23
- def codegen(ct, stmts)
24
- self[:exp].codegen(ct, stmts)
25
- end
26
- end
27
-
28
- class LiteralIntegral
29
- def codegen(ct, stmts)
30
- self[:entity][:desc]
31
- end
32
- end
33
-
34
- class LiteralFloating
35
- def codegen(ct, stmts)
36
- self[:entity][:desc]
37
- end
38
- end
39
-
40
- class LitaralChar
41
- def codegen(ct, stmts)
42
- self[:entity][:desc]
43
- end
44
- end
45
-
46
- class VarRef
47
- def codegen(ct, stmts)
48
- self[:binder].get.var_name(ct, self[:name][:desc])
49
- end
50
- end
51
-
52
- class MatchExp
53
- def codegen(ct, stmts)
54
- vname = "_tmp%03d" % ct.uniq_id_gen
55
- stmts << "#{ct.tref(self)} #{vname};"
56
- left = self[:exp]
57
- if left.is_a?(VarRef)
58
- left_vname = left[:name][:desc]
59
- else
60
- left_vname = "_tmp%03d" % ct.uniq_id_gen
61
- stmts.unshift "#{ct.tref(left)} #{left_vname};"
62
- stmts.push "#{left_vname} = #{left.codegen(ct, stmts)};"
63
- end
64
- self[:cases].each_with_index do |c, i|
65
- then_stmts = []
66
- cond_exps = pattern_to_cond_exps(ct, left_vname, then_stmts, c, c[:pattern])
67
- cond_exp = cond_exps.size == 0 ? "1" : cond_exps.join(" && ")
68
- if c[:exp].is_a?(SkipExp)
69
- then_stmts << "return 0;"
70
- else
71
- then_stmts << "#{vname} = #{c[:exp].codegen(ct, then_stmts)};"
72
- end
73
- if i == 0
74
- stmts << ct.make_block("if (#{cond_exp}) {", then_stmts, "}")
75
- else
76
- stmts << ct.make_block("else if (#{cond_exp}) {", then_stmts, "}")
77
- end
78
- end
79
- return vname
80
- end
81
-
82
- def pattern_to_cond_exps(ct, receiver, stmts, case_def, pattern)
83
- if pattern[:ref]
84
- vname = case_def.var_name(ct, pattern[:ref][:desc])
85
- stmts << "#{ct.tref(pattern)} #{vname} = #{receiver};"
86
- end
87
- case pattern
88
- when ValuePattern
89
- conds = []
90
- type_def = ct.tdef(pattern)
91
- accessor = type_def[:static] ? "." : "->"
92
- if type_def[:tvalues].size > 1
93
- tvalue_id = type_def[:tvalues].index{|x| x[:name] == pattern[:name]}
94
- if type_def.enum?(ct)
95
- conds << "#{receiver} == #{tvalue_id}"
96
- else
97
- conds << "#{receiver}" + accessor + "tvalue_type == " + tvalue_id.to_s
98
- end
99
- end
100
- new_receiver = "#{receiver}" + accessor + "value." + pattern[:name][:desc]
101
- pattern[:args].each_with_index do |x, i|
102
- conds += pattern_to_cond_exps(ct, new_receiver + ".member#{i}", stmts, case_def, x)
103
- end
104
- return conds
105
- when IntegralPattern
106
- return ["#{receiver} == #{pattern[:val][:entity][:desc]}"]
107
- else
108
- return []
109
- end
110
- end
111
- end
112
-
113
- class Case
114
- def var_name(ct, name)
115
- "pvar#{ct.serial(nil, self)}_" + ct.escape_name(name)
116
- end
117
- end
118
-
119
- end
1
+ require 'emfrp/syntax'
2
+
3
+ module Emfrp
4
+ class FuncCall
5
+ def codegen(ct, stmts)
6
+ name = ct.func_name(self[:name][:desc], self[:typing], self[:args].map{|x| x[:typing]})
7
+ "#{name}(#{self[:args].map{|x| x.codegen(ct, stmts)}.join(", ")})"
8
+ end
9
+ end
10
+
11
+ class ValueConst
12
+ def codegen(ct, stmts)
13
+ if ct.tdef(self[:typing]).enum?(ct)
14
+ ct.tdef(self[:typing])[:tvalues].index{|t| t[:name] == self[:name]}.to_s
15
+ else
16
+ name = ct.constructor_name(self[:name][:desc], self[:typing])
17
+ "#{name}(#{self[:args].map{|x| x.codegen(ct, stmts)}.join(", ")})"
18
+ end
19
+ end
20
+ end
21
+
22
+ class ParenthExp
23
+ def codegen(ct, stmts)
24
+ self[:exp].codegen(ct, stmts)
25
+ end
26
+ end
27
+
28
+ class LiteralIntegral
29
+ def codegen(ct, stmts)
30
+ self[:entity][:desc]
31
+ end
32
+ end
33
+
34
+ class LiteralFloating
35
+ def codegen(ct, stmts)
36
+ self[:entity][:desc]
37
+ end
38
+ end
39
+
40
+ class LitaralChar
41
+ def codegen(ct, stmts)
42
+ self[:entity][:desc]
43
+ end
44
+ end
45
+
46
+ class VarRef
47
+ def codegen(ct, stmts)
48
+ self[:binder].get.var_name(ct, self[:name][:desc])
49
+ end
50
+ end
51
+
52
+ class MatchExp
53
+ def codegen(ct, stmts)
54
+ vname = "_tmp%03d" % ct.uniq_id_gen
55
+ stmts << "#{ct.tref(self)} #{vname};"
56
+ left = self[:exp]
57
+ if left.is_a?(VarRef)
58
+ left_vname = ct.escape_name(left[:name][:desc])
59
+ else
60
+ left_vname = "_tmp%03d" % ct.uniq_id_gen
61
+ stmts.unshift "#{ct.tref(left)} #{left_vname};"
62
+ stmts.push "#{left_vname} = #{left.codegen(ct, stmts)};"
63
+ end
64
+ self[:cases].each_with_index do |c, i|
65
+ then_stmts = []
66
+ cond_exps = pattern_to_cond_exps(ct, left_vname, then_stmts, c, c[:pattern])
67
+ cond_exp = cond_exps.size == 0 ? "1" : cond_exps.join(" && ")
68
+ if c[:exp].is_a?(SkipExp)
69
+ then_stmts << "return 0;"
70
+ else
71
+ then_stmts << "#{vname} = #{c[:exp].codegen(ct, then_stmts)};"
72
+ end
73
+ if i == 0
74
+ stmts << ct.make_block("if (#{cond_exp}) {", then_stmts, "}")
75
+ else
76
+ stmts << ct.make_block("else if (#{cond_exp}) {", then_stmts, "}")
77
+ end
78
+ end
79
+ return vname
80
+ end
81
+
82
+ def pattern_to_cond_exps(ct, receiver, stmts, case_def, pattern)
83
+ if pattern[:ref]
84
+ vname = case_def.var_name(ct, pattern[:ref][:desc])
85
+ stmts << "#{ct.tref(pattern)} #{vname} = #{receiver};"
86
+ end
87
+ case pattern
88
+ when ValuePattern
89
+ conds = []
90
+ type_def = ct.tdef(pattern)
91
+ accessor = type_def[:static] ? "." : "->"
92
+ if type_def[:tvalues].size > 1
93
+ tvalue_id = type_def[:tvalues].index{|x| x[:name] == pattern[:name]}
94
+ if type_def.enum?(ct)
95
+ conds << "#{receiver} == #{tvalue_id}"
96
+ else
97
+ conds << "#{receiver}" + accessor + "tvalue_type == " + tvalue_id.to_s
98
+ end
99
+ end
100
+ new_receiver = "#{receiver}" + accessor + "value." + pattern[:name][:desc]
101
+ pattern[:args].each_with_index do |x, i|
102
+ conds += pattern_to_cond_exps(ct, new_receiver + ".member#{i}", stmts, case_def, x)
103
+ end
104
+ return conds
105
+ when IntegralPattern
106
+ return ["#{receiver} == #{pattern[:val][:entity][:desc]}"]
107
+ else
108
+ return []
109
+ end
110
+ end
111
+ end
112
+
113
+ class Case
114
+ def var_name(ct, name)
115
+ "pvar#{ct.serial(nil, self)}_" + ct.escape_name(name)
116
+ end
117
+ end
118
+
119
+ end
@@ -1,53 +1,53 @@
1
- module Emfrp
2
- module Graphviz
3
- extend self
4
-
5
- def compile(top, output_io)
6
- node_stmts, edge_stmts = [], []
7
- visited = {}
8
- top[:outputs].each do |n|
9
- node = top[:dict][:node_space][n[:name][:desc]].get
10
- traverse(top, node, node_stmts, edge_stmts, visited)
11
- end
12
- output_io << "digraph #{top[:module_name][:desc]} {\n"
13
- node_stmts.each do |s|
14
- output_io << " #{s}\n"
15
- end
16
- edge_stmts.each do |s|
17
- output_io << " #{s}\n"
18
- end
19
- output_io << "}\n"
20
- end
21
-
22
- def traverse(top, node, node_stmts, edge_stmts, visited)
23
- return if visited[node]
24
- visited[node] = true
25
- name = node[:name][:desc]
26
- type = node[:typing].to_uniq_str
27
- node_attrs = ["label = \"#{name} : #{type}\""]
28
- case node
29
- when NodeDef
30
- if top[:outputs].find{|o| o[:name] == node[:name]}
31
- node_attrs += ["style = filled", "fillcolor = \"#e4e4e4\""]
32
- end
33
- node[:params].each do |n|
34
- ch_name = n[:name][:desc]
35
- if n[:last]
36
- edge_stmts << "#{escape_name(ch_name)} -> #{escape_name(name)} [style = dashed];"
37
- else
38
- edge_stmts << "#{escape_name(ch_name)} -> #{escape_name(name)};"
39
- end
40
- ch_node = top[:dict][:node_space][ch_name].get
41
- traverse(top, ch_node, node_stmts, edge_stmts, visited)
42
- end
43
- when InputDef
44
- node_attrs << "shape = \"invhouse\""
45
- end
46
- node_stmts << "#{escape_name(name)} [#{node_attrs.join(", ")}];"
47
- end
48
-
49
- def escape_name(name)
50
- CodegenContext.new(nil).escape_name(name)
51
- end
52
- end
53
- end
1
+ module Emfrp
2
+ module Graphviz
3
+ extend self
4
+
5
+ def compile(top, output_io)
6
+ node_stmts, edge_stmts = [], []
7
+ visited = {}
8
+ top[:outputs].each do |n|
9
+ node = top[:dict][:node_space][n[:name][:desc]].get
10
+ traverse(top, node, node_stmts, edge_stmts, visited)
11
+ end
12
+ output_io << "digraph #{top[:module_name][:desc]} {\n"
13
+ node_stmts.each do |s|
14
+ output_io << " #{s}\n"
15
+ end
16
+ edge_stmts.each do |s|
17
+ output_io << " #{s}\n"
18
+ end
19
+ output_io << "}\n"
20
+ end
21
+
22
+ def traverse(top, node, node_stmts, edge_stmts, visited)
23
+ return if visited[node]
24
+ visited[node] = true
25
+ name = node[:name][:desc]
26
+ type = node[:typing].to_uniq_str
27
+ node_attrs = ["label = \"#{name} : #{type}\""]
28
+ case node
29
+ when NodeDef
30
+ if top[:outputs].find{|o| o[:name] == node[:name]}
31
+ node_attrs += ["style = filled", "fillcolor = \"#e4e4e4\""]
32
+ end
33
+ node[:params].each do |n|
34
+ ch_name = n[:name][:desc]
35
+ if n[:last]
36
+ edge_stmts << "#{escape_name(ch_name)} -> #{escape_name(name)} [style = dashed];"
37
+ else
38
+ edge_stmts << "#{escape_name(ch_name)} -> #{escape_name(name)};"
39
+ end
40
+ ch_node = top[:dict][:node_space][ch_name].get
41
+ traverse(top, ch_node, node_stmts, edge_stmts, visited)
42
+ end
43
+ when InputDef
44
+ node_attrs << "shape = \"invhouse\""
45
+ end
46
+ node_stmts << "#{escape_name(name)} [#{node_attrs.join(", ")}];"
47
+ end
48
+
49
+ def escape_name(name)
50
+ CodegenContext.new(nil).escape_name(name)
51
+ end
52
+ end
53
+ end
@@ -1,95 +1,95 @@
1
- require 'colorize'
2
-
3
- module Emfrp
4
- class CompileError < RuntimeError
5
- attr_reader :message, :factors
6
-
7
- def initialize(message, code, *factors)
8
- @message = message
9
- @code = message
10
- @factors = factors
11
- end
12
-
13
- def code
14
- @code
15
- end
16
-
17
- def tag_comp(a, b)
18
- [a[:line_number], a[:column_number]] <=> [b[:line_number], b[:column_number]]
19
- end
20
-
21
- def collect_factor_tags(factor)
22
- case factor
23
- when Syntax
24
- if factor.has_key?(:start_pos)
25
- collect_factor_tags(factor.values) + [[factor[:start_pos], factor[:end_pos]]]
26
- else
27
- collect_factor_tags(factor.values)
28
- end
29
- when Array
30
- factor.flat_map{|x| collect_factor_tags(x)}
31
- else
32
- []
33
- end
34
- end
35
-
36
- def find_factor_file_name(factor)
37
- case factor
38
- when Syntax
39
- if factor.has_key?(:start_pos)
40
- return factor[:start_pos][:document_name]
41
- else
42
- return find_factor_file_name(factor.values)
43
- end
44
- when Array
45
- factor.each do |x|
46
- if res = find_factor_file_name(x)
47
- return res
48
- end
49
- end
50
- end
51
- nil
52
- end
53
-
54
- def factor_name(factor)
55
- klass = factor.class.name.split("::").last
56
- if factor.is_a?(Syntax)
57
- name = factor.has_key?(:name) ? "`#{factor[:name][:desc]}`" : ""
58
- else
59
- name = factor.inspect
60
- end
61
- klass + " " + name
62
- end
63
-
64
- def print_lexical_factor(factor, output_io, file_loader)
65
- src_lines = nil
66
- unless factor_file_name = find_factor_file_name(factor)
67
- raise "assertion error: cannot detect file_name"
68
- end
69
- src_str = file_loader.get_src_from_full_path(factor_file_name)
70
- src_lines = src_str.each_line.to_a
71
- tags = collect_factor_tags(factor)
72
- spos = tags.map{|x| x[0]}.min{|a, b| tag_comp(a, b)}
73
- epos = tags.map{|x| x[1]}.max{|a, b| tag_comp(a, b)}
74
- line_nums = (spos[:line_number]..epos[:line_number]).to_a
75
- if line_nums.size == 1
76
- output_io << "#{factor_file_name}:#{line_nums[0]}:\n"
77
- output_io << "> " + src_lines[line_nums[0] - 1].chomp + "\n"
78
- output_io << " " + " " * (spos[:column_number] - 1)
79
- output_io << ("^" * (epos[:column_number] - spos[:column_number] + 1)).colorize(:green) + "\n"
80
- else
81
- output_io << "#{factor_file_name}:#{line_nums.first}-#{line_nums.last}:\n"
82
- line_nums.each do |line_num|
83
- output_io << "> " + src_lines[line_num - 1]
84
- end
85
- end
86
- end
87
-
88
- def print_error(output_io, file_loader)
89
- output_io << "\e[31m[Error]\e[m: #{@message}"
90
- @factors.each do |factor|
91
- print_lexical_factor(factor, output_io, file_loader)
92
- end
93
- end
94
- end
95
- end
1
+ require 'colorize'
2
+
3
+ module Emfrp
4
+ class CompileError < RuntimeError
5
+ attr_reader :message, :factors
6
+
7
+ def initialize(message, code, *factors)
8
+ @message = message
9
+ @code = message
10
+ @factors = factors
11
+ end
12
+
13
+ def code
14
+ @code
15
+ end
16
+
17
+ def tag_comp(a, b)
18
+ [a[:line_number], a[:column_number]] <=> [b[:line_number], b[:column_number]]
19
+ end
20
+
21
+ def collect_factor_tags(factor)
22
+ case factor
23
+ when Syntax
24
+ if factor.has_key?(:start_pos)
25
+ collect_factor_tags(factor.values) + [[factor[:start_pos], factor[:end_pos]]]
26
+ else
27
+ collect_factor_tags(factor.values)
28
+ end
29
+ when Array
30
+ factor.flat_map{|x| collect_factor_tags(x)}
31
+ else
32
+ []
33
+ end
34
+ end
35
+
36
+ def find_factor_file_name(factor)
37
+ case factor
38
+ when Syntax
39
+ if factor.has_key?(:start_pos)
40
+ return factor[:start_pos][:document_name]
41
+ else
42
+ return find_factor_file_name(factor.values)
43
+ end
44
+ when Array
45
+ factor.each do |x|
46
+ if res = find_factor_file_name(x)
47
+ return res
48
+ end
49
+ end
50
+ end
51
+ nil
52
+ end
53
+
54
+ def factor_name(factor)
55
+ klass = factor.class.name.split("::").last
56
+ if factor.is_a?(Syntax)
57
+ name = factor.has_key?(:name) ? "`#{factor[:name][:desc]}`" : ""
58
+ else
59
+ name = factor.inspect
60
+ end
61
+ klass + " " + name
62
+ end
63
+
64
+ def print_lexical_factor(factor, output_io, file_loader)
65
+ src_lines = nil
66
+ unless factor_file_name = find_factor_file_name(factor)
67
+ raise "assertion error: cannot detect file_name"
68
+ end
69
+ src_str = file_loader.get_src_from_full_path(factor_file_name)
70
+ src_lines = src_str.each_line.to_a
71
+ tags = collect_factor_tags(factor)
72
+ spos = tags.map{|x| x[0]}.min{|a, b| tag_comp(a, b)}
73
+ epos = tags.map{|x| x[1]}.max{|a, b| tag_comp(a, b)}
74
+ line_nums = (spos[:line_number]..epos[:line_number]).to_a
75
+ if line_nums.size == 1
76
+ output_io << "#{factor_file_name}:#{line_nums[0]}:\n"
77
+ output_io << "> " + src_lines[line_nums[0] - 1].chomp + "\n"
78
+ output_io << " " + " " * (spos[:column_number] - 1)
79
+ output_io << ("^" * (epos[:column_number] - spos[:column_number] + 1)).colorize(:green) + "\n"
80
+ else
81
+ output_io << "#{factor_file_name}:#{line_nums.first}-#{line_nums.last}:\n"
82
+ line_nums.each do |line_num|
83
+ output_io << "> " + src_lines[line_num - 1]
84
+ end
85
+ end
86
+ end
87
+
88
+ def print_error(output_io, file_loader)
89
+ output_io << "\e[31m[Error]\e[m: #{@message}"
90
+ @factors.each do |factor|
91
+ print_lexical_factor(factor, output_io, file_loader)
92
+ end
93
+ end
94
+ end
95
+ end