emfrp 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -12
- data/bin/emfrp +4 -1
- data/examples/LCDClock/LCDClock.mfrp +93 -93
- data/examples/LCDClock/LCDClock_LPC1768.bin +0 -0
- data/examples/LCDClock/README.md +24 -24
- data/examples/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/examples/LCDPositioner/LCDPositionerMain.c +15 -15
- data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -25
- data/examples/MostDistantPoint/MostDistantPointMain.c +14 -14
- data/lib/emfrp/compile/c/alloc.rb +200 -200
- data/lib/emfrp/compile/c/codegen.rb +18 -18
- data/lib/emfrp/compile/c/codegen_context.rb +218 -218
- data/lib/emfrp/compile/c/monofy.rb +185 -185
- data/lib/emfrp/compile/c/syntax_codegen.rb +364 -364
- data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -119
- data/lib/emfrp/compile/graphviz/graphviz.rb +53 -53
- data/lib/emfrp/compile_error.rb +95 -95
- data/lib/emfrp/interpreter/command_manager.rb +367 -367
- data/lib/emfrp/interpreter/evaluater.rb +146 -146
- data/lib/emfrp/interpreter/file_loader.rb +52 -52
- data/lib/emfrp/interpreter/interpreter.rb +200 -195
- data/lib/emfrp/parser/expression.rb +386 -386
- data/lib/emfrp/parser/misc.rb +184 -184
- data/lib/emfrp/parser/newnode_convert.rb +72 -72
- data/lib/emfrp/parser/operator.rb +25 -25
- data/lib/emfrp/parser/parser.rb +150 -150
- data/lib/emfrp/parser/parsing_error.rb +49 -49
- data/lib/emfrp/parser/toplevel.rb +555 -555
- data/lib/emfrp/pre_convert/pre_convert.rb +32 -32
- data/lib/emfrp/syntax.rb +171 -171
- data/lib/emfrp/typing/typing_error.rb +47 -47
- data/lib/emfrp/typing/union_type.rb +197 -197
- data/lib/emfrp/version.rb +1 -1
- data/mfrp_include/Std.mfrp +122 -122
- data/tests/Rakefile +8 -8
- data/tests/Rakefile.common +27 -27
- data/tests/command/Rakefile +2 -2
- data/tests/command/ReplaceNode.mfrp +39 -39
- data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -14
- data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -15
- data/tests/compiler/ComplexDataType/Rakefile +2 -2
- data/tests/compiler/ComplexDataType/expected_out.txt +0 -0
- data/tests/compiler/ComplexDataType/in.txt +5 -5
- data/tests/compiler/LCDClock/LCDClock.mfrp +90 -90
- data/tests/compiler/LCDClock/LCDClockMain.c +0 -0
- data/tests/compiler/LCDClock/Rakefile +2 -2
- data/tests/compiler/LCDClock/expected_out.txt +0 -0
- data/tests/compiler/LCDClock/in.txt +0 -0
- data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -30
- data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -15
- data/tests/compiler/LCDPositioner/Rakefile +2 -2
- data/tests/compiler/LCDPositioner/graph.dot +0 -0
- data/tests/compiler/LCDPositioner/graph.png +0 -0
- data/tests/compiler/Rakefile +8 -8
- data/tests/compiler/Rakefile.common +23 -23
- data/tests/compiler/UseData/Rakefile +2 -2
- data/tests/compiler/UseData/UseData.mfrp +8 -8
- data/tests/compiler/UseSubModule/Rakefile +2 -2
- data/tests/compiler/UseSubModule/SubModule.mfrp +8 -8
- data/tests/compiler/UseSubModule/SubModule2.mfrp +5 -5
- data/tests/compiler/UseSubModule/UseSubModule.mfrp +11 -11
- data/tests/core/FromAnnotation.mfrp +18 -18
- data/tests/core/Last.mfrp +10 -10
- data/tests/core/Rakefile +2 -2
- data/tests/core/TypingTest.mfrp +11 -11
- data/tests/core/WithoutInputs.mfrp +19 -19
- data/tests/load_time_error/Rakefile +32 -32
- data/tests/load_time_error/TypeMismatch.mfrp +4 -4
- metadata +3 -3
@@ -1,200 +1,200 @@
|
|
1
|
-
module Emfrp
|
2
|
-
class AllocRequirement
|
3
|
-
def initialize(top)
|
4
|
-
@top = top
|
5
|
-
@alloc_table = AllocTable.new(top)
|
6
|
-
@sorted_nodes = @top[:dict][:sorted_nodes].map{|x| x.get}
|
7
|
-
end
|
8
|
-
|
9
|
-
def requirement
|
10
|
-
sorted_datas = @top[:dict][:sorted_datas].map{|x| x.get}
|
11
|
-
init_nodes = @sorted_nodes.select{|n| n[:init_exp]}
|
12
|
-
max_amount = Alloc.empty
|
13
|
-
max_amount = data_requirement(sorted_datas, max_amount)
|
14
|
-
max_amount = node_init_requirement(init_nodes, max_amount, sorted_datas)
|
15
|
-
max_amount = node_loop_requirement(max_amount, init_nodes, sorted_datas)
|
16
|
-
return max_amount
|
17
|
-
end
|
18
|
-
|
19
|
-
def data_requirement(sorted_datas, max_amount)
|
20
|
-
retains = []
|
21
|
-
sorted_datas.each do |d|
|
22
|
-
max_amount |= type_alloc_sum(retains) & exp_alloc(d[:exp])
|
23
|
-
end
|
24
|
-
return max_amount
|
25
|
-
end
|
26
|
-
|
27
|
-
def node_init_requirement(init_nodes, max_amount, datas)
|
28
|
-
retains = datas.clone
|
29
|
-
init_nodes.each do |n|
|
30
|
-
max_amount |= type_alloc_sum(retains) & exp_alloc(n[:init_exp])
|
31
|
-
retains << n
|
32
|
-
end
|
33
|
-
return max_amount
|
34
|
-
end
|
35
|
-
|
36
|
-
def node_loop_requirement(max_amount, init_nodes, datas)
|
37
|
-
lrefs = init_nodes
|
38
|
-
crefs = []
|
39
|
-
@sorted_nodes.each_with_index do |n, i|
|
40
|
-
max_amount |= type_alloc_sum(datas + lrefs + crefs) & exp_alloc(n[:exp])
|
41
|
-
crefs << n
|
42
|
-
lrefs.reject! do |x|
|
43
|
-
i >= ref_pos_last(x)
|
44
|
-
end
|
45
|
-
crefs.reject! do |x|
|
46
|
-
i >= ref_pos_current(x)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
return max_amount
|
50
|
-
end
|
51
|
-
|
52
|
-
def ref_pos_last(node)
|
53
|
-
res = -1
|
54
|
-
@sorted_nodes.each_with_index do |n, i|
|
55
|
-
if n[:params].any?{|param| param[:last] && param[:name] == node[:name]}
|
56
|
-
res = i
|
57
|
-
end
|
58
|
-
end
|
59
|
-
return res
|
60
|
-
end
|
61
|
-
|
62
|
-
def ref_pos_current(node)
|
63
|
-
res = -1
|
64
|
-
@sorted_nodes.each_with_index do |n, i|
|
65
|
-
if n[:params].any?{|param| !param[:last] && param[:name] == node[:name]}
|
66
|
-
res = i
|
67
|
-
end
|
68
|
-
end
|
69
|
-
return res
|
70
|
-
end
|
71
|
-
|
72
|
-
def life_point(node)
|
73
|
-
self_position = @sorted_nodes.index{|x| x == node}
|
74
|
-
distance_to_end = @sorted_nodes.size - self_position
|
75
|
-
res = []
|
76
|
-
@sorted_nodes.each_with_index do |x, i|
|
77
|
-
x[:params].each do |param|
|
78
|
-
if param[:name] == node[:name]
|
79
|
-
if param[:last]
|
80
|
-
res << distance_to_end + i
|
81
|
-
else
|
82
|
-
res << i - self_position
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
if res == []
|
88
|
-
raise "Assertion error"
|
89
|
-
else
|
90
|
-
return res.max
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def type_alloc_sum(defs)
|
95
|
-
defs.inject(Alloc.empty) do |acc, d|
|
96
|
-
type_def = @alloc_table.utype_to_type_def(d[:typing])
|
97
|
-
acc & @alloc_table.type_alloc(type_def)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def exp_alloc(exp)
|
102
|
-
@alloc_table.exp_alloc(exp)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
class AllocTable
|
107
|
-
def initialize(top)
|
108
|
-
@top = top
|
109
|
-
@tbl = {}
|
110
|
-
@type_tbl = {}
|
111
|
-
end
|
112
|
-
|
113
|
-
def utype_to_type_def(utype)
|
114
|
-
if t = @top[:dict][:itype_space][utype.to_uniq_str]
|
115
|
-
t.get
|
116
|
-
elsif t = @top[:dict][:type_space][utype.typename]
|
117
|
-
t.get
|
118
|
-
else
|
119
|
-
raise "Assertion error"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def type_alloc(type_def)
|
124
|
-
return @type_tbl[type_def] if @type_tbl[type_def]
|
125
|
-
case type_def
|
126
|
-
when TypeDef
|
127
|
-
tvalue_type_max_allocs = type_def[:tvalues].map do |tval|
|
128
|
-
param_type_max_allocs = tval[:params].map do |param|
|
129
|
-
type_alloc(utype_to_type_def(param[:typing]))
|
130
|
-
end
|
131
|
-
param_type_max_allocs.inject(Alloc.empty, &:&)
|
132
|
-
end
|
133
|
-
self_type_alloc = type_def[:static] ? Alloc.empty : Alloc.one(Link.new(type_def))
|
134
|
-
@type_tbl[type_def] = tvalue_type_max_allocs.inject(&:|) & self_type_alloc
|
135
|
-
when PrimTypeDef
|
136
|
-
@type_tbl[type_def] = Alloc.empty
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def exp_alloc(exp)
|
141
|
-
return @tbl[exp] if @tbl[exp]
|
142
|
-
case exp
|
143
|
-
when MatchExp
|
144
|
-
@tbl[exp] = exp[:cases].map{|c| exp_alloc(c[:exp])}.inject(&:|) & exp_alloc(exp[:exp])
|
145
|
-
when FuncCall
|
146
|
-
args_alloc = exp[:args].map{|x| exp_alloc(x)}.inject(&:&)
|
147
|
-
key = ([exp] + exp[:args]).map{|x| x[:typing].to_uniq_str} + [exp[:name][:desc]]
|
148
|
-
if @top[:dict][:ifunc_space][key]
|
149
|
-
f = @top[:dict][:ifunc_space][key].get
|
150
|
-
@tbl[exp] = args_alloc & exp_alloc(f[:exp])
|
151
|
-
elsif f = @top[:dict][:func_space][exp[:name][:desc]]
|
152
|
-
if f.get.is_a?(PrimFuncDef)
|
153
|
-
@tbl[exp] = args_alloc
|
154
|
-
else
|
155
|
-
raise "Assertion error"
|
156
|
-
end
|
157
|
-
else
|
158
|
-
raise "Assertion error"
|
159
|
-
end
|
160
|
-
when ValueConst
|
161
|
-
args_alloc = exp[:args].map{|x| exp_alloc(x)}.inject(Alloc.empty, &:&)
|
162
|
-
key = exp[:typing].to_uniq_str
|
163
|
-
raise "Assertion error" unless @top[:dict][:itype_space][key]
|
164
|
-
type_def = @top[:dict][:itype_space][key].get
|
165
|
-
@tbl[exp] = args_alloc & Alloc.one(Link.new(type_def))
|
166
|
-
when Syntax
|
167
|
-
@tbl[exp] = Alloc.empty
|
168
|
-
else
|
169
|
-
raise "Assertion error"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
class Alloc
|
175
|
-
attr_reader :h
|
176
|
-
def initialize(hash)
|
177
|
-
@h = hash
|
178
|
-
end
|
179
|
-
|
180
|
-
def self.empty
|
181
|
-
self.new({})
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.one(k)
|
185
|
-
self.new(k => 1)
|
186
|
-
end
|
187
|
-
|
188
|
-
def |(other)
|
189
|
-
Alloc.new self.h.merge(other.h){|k, v1, v2| [v1, v2].max}
|
190
|
-
end
|
191
|
-
|
192
|
-
def &(other)
|
193
|
-
Alloc.new self.h.merge(other.h){|k, v1, v2| v1 + v2}
|
194
|
-
end
|
195
|
-
|
196
|
-
def each(&block)
|
197
|
-
@h.each(&block)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
1
|
+
module Emfrp
|
2
|
+
class AllocRequirement
|
3
|
+
def initialize(top)
|
4
|
+
@top = top
|
5
|
+
@alloc_table = AllocTable.new(top)
|
6
|
+
@sorted_nodes = @top[:dict][:sorted_nodes].map{|x| x.get}
|
7
|
+
end
|
8
|
+
|
9
|
+
def requirement
|
10
|
+
sorted_datas = @top[:dict][:sorted_datas].map{|x| x.get}
|
11
|
+
init_nodes = @sorted_nodes.select{|n| n[:init_exp]}
|
12
|
+
max_amount = Alloc.empty
|
13
|
+
max_amount = data_requirement(sorted_datas, max_amount)
|
14
|
+
max_amount = node_init_requirement(init_nodes, max_amount, sorted_datas)
|
15
|
+
max_amount = node_loop_requirement(max_amount, init_nodes, sorted_datas)
|
16
|
+
return max_amount
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_requirement(sorted_datas, max_amount)
|
20
|
+
retains = []
|
21
|
+
sorted_datas.each do |d|
|
22
|
+
max_amount |= type_alloc_sum(retains) & exp_alloc(d[:exp])
|
23
|
+
end
|
24
|
+
return max_amount
|
25
|
+
end
|
26
|
+
|
27
|
+
def node_init_requirement(init_nodes, max_amount, datas)
|
28
|
+
retains = datas.clone
|
29
|
+
init_nodes.each do |n|
|
30
|
+
max_amount |= type_alloc_sum(retains) & exp_alloc(n[:init_exp])
|
31
|
+
retains << n
|
32
|
+
end
|
33
|
+
return max_amount
|
34
|
+
end
|
35
|
+
|
36
|
+
def node_loop_requirement(max_amount, init_nodes, datas)
|
37
|
+
lrefs = init_nodes
|
38
|
+
crefs = []
|
39
|
+
@sorted_nodes.each_with_index do |n, i|
|
40
|
+
max_amount |= type_alloc_sum(datas + lrefs + crefs) & exp_alloc(n[:exp])
|
41
|
+
crefs << n
|
42
|
+
lrefs.reject! do |x|
|
43
|
+
i >= ref_pos_last(x)
|
44
|
+
end
|
45
|
+
crefs.reject! do |x|
|
46
|
+
i >= ref_pos_current(x)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return max_amount
|
50
|
+
end
|
51
|
+
|
52
|
+
def ref_pos_last(node)
|
53
|
+
res = -1
|
54
|
+
@sorted_nodes.each_with_index do |n, i|
|
55
|
+
if n[:params].any?{|param| param[:last] && param[:name] == node[:name]}
|
56
|
+
res = i
|
57
|
+
end
|
58
|
+
end
|
59
|
+
return res
|
60
|
+
end
|
61
|
+
|
62
|
+
def ref_pos_current(node)
|
63
|
+
res = -1
|
64
|
+
@sorted_nodes.each_with_index do |n, i|
|
65
|
+
if n[:params].any?{|param| !param[:last] && param[:name] == node[:name]}
|
66
|
+
res = i
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return res
|
70
|
+
end
|
71
|
+
|
72
|
+
def life_point(node)
|
73
|
+
self_position = @sorted_nodes.index{|x| x == node}
|
74
|
+
distance_to_end = @sorted_nodes.size - self_position
|
75
|
+
res = []
|
76
|
+
@sorted_nodes.each_with_index do |x, i|
|
77
|
+
x[:params].each do |param|
|
78
|
+
if param[:name] == node[:name]
|
79
|
+
if param[:last]
|
80
|
+
res << distance_to_end + i
|
81
|
+
else
|
82
|
+
res << i - self_position
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if res == []
|
88
|
+
raise "Assertion error"
|
89
|
+
else
|
90
|
+
return res.max
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def type_alloc_sum(defs)
|
95
|
+
defs.inject(Alloc.empty) do |acc, d|
|
96
|
+
type_def = @alloc_table.utype_to_type_def(d[:typing])
|
97
|
+
acc & @alloc_table.type_alloc(type_def)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def exp_alloc(exp)
|
102
|
+
@alloc_table.exp_alloc(exp)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class AllocTable
|
107
|
+
def initialize(top)
|
108
|
+
@top = top
|
109
|
+
@tbl = {}
|
110
|
+
@type_tbl = {}
|
111
|
+
end
|
112
|
+
|
113
|
+
def utype_to_type_def(utype)
|
114
|
+
if t = @top[:dict][:itype_space][utype.to_uniq_str]
|
115
|
+
t.get
|
116
|
+
elsif t = @top[:dict][:type_space][utype.typename]
|
117
|
+
t.get
|
118
|
+
else
|
119
|
+
raise "Assertion error"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def type_alloc(type_def)
|
124
|
+
return @type_tbl[type_def] if @type_tbl[type_def]
|
125
|
+
case type_def
|
126
|
+
when TypeDef
|
127
|
+
tvalue_type_max_allocs = type_def[:tvalues].map do |tval|
|
128
|
+
param_type_max_allocs = tval[:params].map do |param|
|
129
|
+
type_alloc(utype_to_type_def(param[:typing]))
|
130
|
+
end
|
131
|
+
param_type_max_allocs.inject(Alloc.empty, &:&)
|
132
|
+
end
|
133
|
+
self_type_alloc = type_def[:static] ? Alloc.empty : Alloc.one(Link.new(type_def))
|
134
|
+
@type_tbl[type_def] = tvalue_type_max_allocs.inject(&:|) & self_type_alloc
|
135
|
+
when PrimTypeDef
|
136
|
+
@type_tbl[type_def] = Alloc.empty
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def exp_alloc(exp)
|
141
|
+
return @tbl[exp] if @tbl[exp]
|
142
|
+
case exp
|
143
|
+
when MatchExp
|
144
|
+
@tbl[exp] = exp[:cases].map{|c| exp_alloc(c[:exp])}.inject(&:|) & exp_alloc(exp[:exp])
|
145
|
+
when FuncCall
|
146
|
+
args_alloc = exp[:args].map{|x| exp_alloc(x)}.inject(&:&)
|
147
|
+
key = ([exp] + exp[:args]).map{|x| x[:typing].to_uniq_str} + [exp[:name][:desc]]
|
148
|
+
if @top[:dict][:ifunc_space][key]
|
149
|
+
f = @top[:dict][:ifunc_space][key].get
|
150
|
+
@tbl[exp] = args_alloc & exp_alloc(f[:exp])
|
151
|
+
elsif f = @top[:dict][:func_space][exp[:name][:desc]]
|
152
|
+
if f.get.is_a?(PrimFuncDef)
|
153
|
+
@tbl[exp] = args_alloc
|
154
|
+
else
|
155
|
+
raise "Assertion error"
|
156
|
+
end
|
157
|
+
else
|
158
|
+
raise "Assertion error"
|
159
|
+
end
|
160
|
+
when ValueConst
|
161
|
+
args_alloc = exp[:args].map{|x| exp_alloc(x)}.inject(Alloc.empty, &:&)
|
162
|
+
key = exp[:typing].to_uniq_str
|
163
|
+
raise "Assertion error" unless @top[:dict][:itype_space][key]
|
164
|
+
type_def = @top[:dict][:itype_space][key].get
|
165
|
+
@tbl[exp] = args_alloc & Alloc.one(Link.new(type_def))
|
166
|
+
when Syntax
|
167
|
+
@tbl[exp] = Alloc.empty
|
168
|
+
else
|
169
|
+
raise "Assertion error"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
class Alloc
|
175
|
+
attr_reader :h
|
176
|
+
def initialize(hash)
|
177
|
+
@h = hash
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.empty
|
181
|
+
self.new({})
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.one(k)
|
185
|
+
self.new(k => 1)
|
186
|
+
end
|
187
|
+
|
188
|
+
def |(other)
|
189
|
+
Alloc.new self.h.merge(other.h){|k, v1, v2| [v1, v2].max}
|
190
|
+
end
|
191
|
+
|
192
|
+
def &(other)
|
193
|
+
Alloc.new self.h.merge(other.h){|k, v1, v2| v1 + v2}
|
194
|
+
end
|
195
|
+
|
196
|
+
def each(&block)
|
197
|
+
@h.each(&block)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -1,18 +1,18 @@
|
|
1
|
-
require 'emfrp/compile/c/monofy'
|
2
|
-
require 'emfrp/compile/c/alloc'
|
3
|
-
require 'emfrp/compile/c/codegen_context'
|
4
|
-
require 'emfrp/compile/c/syntax_codegen'
|
5
|
-
|
6
|
-
module Emfrp
|
7
|
-
module Codegen
|
8
|
-
extend self
|
9
|
-
|
10
|
-
def codegen(top, c_output, h_output, main_output, name)
|
11
|
-
Monofy.monofy(top)
|
12
|
-
ct = CodegenContext.new(top)
|
13
|
-
ar = AllocRequirement.new(top)
|
14
|
-
top.codegen(ct, ar)
|
15
|
-
ct.code_generate(c_output, h_output, main_output, name)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
require 'emfrp/compile/c/monofy'
|
2
|
+
require 'emfrp/compile/c/alloc'
|
3
|
+
require 'emfrp/compile/c/codegen_context'
|
4
|
+
require 'emfrp/compile/c/syntax_codegen'
|
5
|
+
|
6
|
+
module Emfrp
|
7
|
+
module Codegen
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def codegen(top, c_output, h_output, main_output, name)
|
11
|
+
Monofy.monofy(top)
|
12
|
+
ct = CodegenContext.new(top)
|
13
|
+
ar = AllocRequirement.new(top)
|
14
|
+
top.codegen(ct, ar)
|
15
|
+
ct.code_generate(c_output, h_output, main_output, name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|