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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +6 -0
- data/LICENSE +28 -0
- data/README.md +27 -0
- data/Rakefile +2 -0
- data/bin/emfrp +21 -0
- data/bin/emfrpi +24 -0
- data/emfrp.gemspec +26 -0
- data/examples/LCDPositioner/LCDPositioner.c +278 -0
- data/examples/LCDPositioner/LCDPositioner.h +6 -0
- data/examples/LCDPositioner/LCDPositioner.mfrp +30 -0
- data/examples/LCDPositioner/LCDPositionerMain.c +15 -0
- data/examples/LCDPositioner/LCDPositionerMain.c.gen +11 -0
- data/examples/LCDPositioner/graph.dot +31 -0
- data/examples/LCDPositioner/graph.png +0 -0
- data/examples/MostDistantPoint/MostDistantPoint.c +199 -0
- data/examples/MostDistantPoint/MostDistantPoint.h +6 -0
- data/examples/MostDistantPoint/MostDistantPoint.mfrp +25 -0
- data/examples/MostDistantPoint/MostDistantPointMain.c +14 -0
- data/examples/MostDistantPoint/graph.dot +12 -0
- data/examples/MostDistantPoint/graph.png +0 -0
- data/lib/emfrp/compile/c/alloc.rb +200 -0
- data/lib/emfrp/compile/c/codegen.rb +18 -0
- data/lib/emfrp/compile/c/codegen_context.rb +215 -0
- data/lib/emfrp/compile/c/monofy.rb +185 -0
- data/lib/emfrp/compile/c/syntax_codegen.rb +364 -0
- data/lib/emfrp/compile/c/syntax_exp_codegen.rb +119 -0
- data/lib/emfrp/compile/graphviz/graphviz.rb +49 -0
- data/lib/emfrp/compile_error.rb +95 -0
- data/lib/emfrp/interpreter/command_manager.rb +367 -0
- data/lib/emfrp/interpreter/evaluater.rb +146 -0
- data/lib/emfrp/interpreter/file_loader.rb +52 -0
- data/lib/emfrp/interpreter/interpreter.rb +195 -0
- data/lib/emfrp/parser/expression.rb +386 -0
- data/lib/emfrp/parser/misc.rb +184 -0
- data/lib/emfrp/parser/operator.rb +25 -0
- data/lib/emfrp/parser/parser.rb +145 -0
- data/lib/emfrp/parser/parsing_error.rb +49 -0
- data/lib/emfrp/parser/toplevel.rb +523 -0
- data/lib/emfrp/pre_convert/alpha_convert.rb +119 -0
- data/lib/emfrp/pre_convert/make_name_dict.rb +96 -0
- data/lib/emfrp/pre_convert/node_check.rb +60 -0
- data/lib/emfrp/pre_convert/pre_convert.rb +32 -0
- data/lib/emfrp/syntax.rb +169 -0
- data/lib/emfrp/typing/typing.rb +256 -0
- data/lib/emfrp/typing/typing_error.rb +47 -0
- data/lib/emfrp/typing/union_type.rb +197 -0
- data/lib/emfrp/version.rb +3 -0
- data/lib/emfrp.rb +14 -0
- data/mfrp_include/Std.mfrp +122 -0
- data/tests/Rakefile +8 -0
- data/tests/Rakefile.common +27 -0
- data/tests/command/Rakefile +2 -0
- data/tests/command/ReplaceNode.mfrp +39 -0
- data/tests/compiler/ComplexDataType/ComplexDataType.mfrp +14 -0
- data/tests/compiler/ComplexDataType/ComplexDataTypeMain.c +15 -0
- data/tests/compiler/ComplexDataType/Rakefile +2 -0
- data/tests/compiler/ComplexDataType/actual_out.txt +5 -0
- data/tests/compiler/ComplexDataType/expected_out.txt +5 -0
- data/tests/compiler/ComplexDataType/graph.png +0 -0
- data/tests/compiler/ComplexDataType/in.txt +5 -0
- data/tests/compiler/LCDPositioner/LCDPositioner.mfrp +30 -0
- data/tests/compiler/LCDPositioner/LCDPositionerMain.c +15 -0
- data/tests/compiler/LCDPositioner/Rakefile +2 -0
- data/tests/compiler/LCDPositioner/actual_out.txt +9 -0
- data/tests/compiler/LCDPositioner/expected_out.txt +9 -0
- data/tests/compiler/LCDPositioner/graph.dot +31 -0
- data/tests/compiler/LCDPositioner/graph.png +0 -0
- data/tests/compiler/LCDPositioner/in.txt +11 -0
- data/tests/compiler/Rakefile +8 -0
- data/tests/compiler/Rakefile.common +23 -0
- data/tests/core/FromAnnotation.mfrp +18 -0
- data/tests/core/Last.mfrp +10 -0
- data/tests/core/Rakefile +2 -0
- data/tests/core/TypingTest.mfrp +11 -0
- data/tests/core/WithoutInputs.mfrp +19 -0
- data/tests/load_time_error/Rakefile +32 -0
- data/tests/load_time_error/TypeMismatch.mfrp +4 -0
- metadata +180 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#include "MostDistantPoint.h"
|
|
2
|
+
/* Primitive functions (Macros) */
|
|
3
|
+
#define _lt_(a, b) (a < b)
|
|
4
|
+
#define _plus_(a, b) (a + b)
|
|
5
|
+
#define _asterisk_(a, b) (a * b)
|
|
6
|
+
#define _minus_(a, b) (a - b)
|
|
7
|
+
/* Data types */
|
|
8
|
+
struct Tuple2_Int_Int{
|
|
9
|
+
int mark;
|
|
10
|
+
union {
|
|
11
|
+
struct {
|
|
12
|
+
int member0;
|
|
13
|
+
int member1;
|
|
14
|
+
}Tuple2;
|
|
15
|
+
}value;
|
|
16
|
+
};
|
|
17
|
+
/* Global variables */
|
|
18
|
+
int node_memory_inX[2];
|
|
19
|
+
int node_memory_inY[2];
|
|
20
|
+
struct Tuple2_Int_Int* node_memory_point[2];
|
|
21
|
+
int node_memory_outX[2];
|
|
22
|
+
int node_memory_outY[2];
|
|
23
|
+
struct Tuple2_Int_Int memory_Tuple2_Int_Int[5];
|
|
24
|
+
int size_Tuple2_Int_Int = 5;
|
|
25
|
+
int counter_Tuple2_Int_Int = 0;
|
|
26
|
+
int Counter = 1;
|
|
27
|
+
int NodeSize = 3;
|
|
28
|
+
/* Static prototypes */
|
|
29
|
+
static struct Tuple2_Int_Int* Tuple2_0(int, int);
|
|
30
|
+
static void mark_Tuple2_Int_Int(struct Tuple2_Int_Int*, int);
|
|
31
|
+
static int node_point(int, int, struct Tuple2_Int_Int*, struct Tuple2_Int_Int**);
|
|
32
|
+
static struct Tuple2_Int_Int* init_point();
|
|
33
|
+
static int node_outX(struct Tuple2_Int_Int*, int*);
|
|
34
|
+
static int init_outX();
|
|
35
|
+
static int node_outY(struct Tuple2_Int_Int*, int*);
|
|
36
|
+
static int init_outY();
|
|
37
|
+
static int distant2_0(struct Tuple2_Int_Int*, struct Tuple2_Int_Int*);
|
|
38
|
+
static int snd_0(struct Tuple2_Int_Int*);
|
|
39
|
+
static int fst_0(struct Tuple2_Int_Int*);
|
|
40
|
+
static void refreshMark();
|
|
41
|
+
extern void Input(int*, int*);
|
|
42
|
+
extern void Output(int*, int*);
|
|
43
|
+
/* Functions, Constructors, GCMarkers, etc... */
|
|
44
|
+
static struct Tuple2_Int_Int* Tuple2_0(int member0, int member1) {
|
|
45
|
+
struct Tuple2_Int_Int* x;
|
|
46
|
+
while (1) {
|
|
47
|
+
counter_Tuple2_Int_Int++;
|
|
48
|
+
counter_Tuple2_Int_Int %= size_Tuple2_Int_Int;
|
|
49
|
+
if (memory_Tuple2_Int_Int[counter_Tuple2_Int_Int].mark < Counter) { x = memory_Tuple2_Int_Int + counter_Tuple2_Int_Int; break; }
|
|
50
|
+
}
|
|
51
|
+
x->value.Tuple2.member0 = member0;
|
|
52
|
+
x->value.Tuple2.member1 = member1;
|
|
53
|
+
return x;
|
|
54
|
+
}
|
|
55
|
+
static void mark_Tuple2_Int_Int(struct Tuple2_Int_Int* x, int mark) {
|
|
56
|
+
x->mark = mark;
|
|
57
|
+
}
|
|
58
|
+
static int node_point(int inX, int inY, struct Tuple2_Int_Int* point_at_last, struct Tuple2_Int_Int** output) {
|
|
59
|
+
int _tmp001;
|
|
60
|
+
struct Tuple2_Int_Int* _tmp000;
|
|
61
|
+
_tmp001 = distant2_0(Tuple2_0(0, 0), point_at_last);
|
|
62
|
+
if (1) {
|
|
63
|
+
int _tmp003;
|
|
64
|
+
int pvar0_d1 = _tmp001;
|
|
65
|
+
struct Tuple2_Int_Int* _tmp002;
|
|
66
|
+
_tmp003 = distant2_0(Tuple2_0(0, 0), Tuple2_0(inX, inY));
|
|
67
|
+
if (1) {
|
|
68
|
+
int _tmp005;
|
|
69
|
+
int pvar1_d2 = _tmp003;
|
|
70
|
+
struct Tuple2_Int_Int* _tmp004;
|
|
71
|
+
_tmp005 = _lt_(pvar0_d1, pvar1_d2);
|
|
72
|
+
if (_tmp005 == 1) {
|
|
73
|
+
_tmp004 = Tuple2_0(inX, inY);
|
|
74
|
+
}
|
|
75
|
+
else if (_tmp005 == 0) {
|
|
76
|
+
_tmp004 = point_at_last;
|
|
77
|
+
}
|
|
78
|
+
_tmp002 = _tmp004;
|
|
79
|
+
}
|
|
80
|
+
_tmp000 = _tmp002;
|
|
81
|
+
}
|
|
82
|
+
*output = _tmp000;
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
static struct Tuple2_Int_Int* init_point() {
|
|
86
|
+
return Tuple2_0(0, 0);
|
|
87
|
+
}
|
|
88
|
+
static int node_outX(struct Tuple2_Int_Int* point, int* output) {
|
|
89
|
+
int _tmp006;
|
|
90
|
+
if (1) {
|
|
91
|
+
struct Tuple2_Int_Int* pvar2_point = point;
|
|
92
|
+
int pvar2_outX = point->value.Tuple2.member0;
|
|
93
|
+
int pvar2_outY = point->value.Tuple2.member1;
|
|
94
|
+
_tmp006 = pvar2_outX;
|
|
95
|
+
}
|
|
96
|
+
*output = _tmp006;
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
static int init_outX() {
|
|
100
|
+
struct Tuple2_Int_Int* _tmp008;
|
|
101
|
+
int _tmp007;
|
|
102
|
+
_tmp008 = Tuple2_0(0, 0);
|
|
103
|
+
if (1) {
|
|
104
|
+
struct Tuple2_Int_Int* pvar3_point = _tmp008;
|
|
105
|
+
int pvar3_outX = _tmp008->value.Tuple2.member0;
|
|
106
|
+
int pvar3_outY = _tmp008->value.Tuple2.member1;
|
|
107
|
+
_tmp007 = pvar3_outX;
|
|
108
|
+
}
|
|
109
|
+
return _tmp007;
|
|
110
|
+
}
|
|
111
|
+
static int node_outY(struct Tuple2_Int_Int* point, int* output) {
|
|
112
|
+
int _tmp009;
|
|
113
|
+
if (1) {
|
|
114
|
+
struct Tuple2_Int_Int* pvar4_point = point;
|
|
115
|
+
int pvar4_outX = point->value.Tuple2.member0;
|
|
116
|
+
int pvar4_outY = point->value.Tuple2.member1;
|
|
117
|
+
_tmp009 = pvar4_outY;
|
|
118
|
+
}
|
|
119
|
+
*output = _tmp009;
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
static int init_outY() {
|
|
123
|
+
struct Tuple2_Int_Int* _tmp011;
|
|
124
|
+
int _tmp010;
|
|
125
|
+
_tmp011 = Tuple2_0(0, 0);
|
|
126
|
+
if (1) {
|
|
127
|
+
struct Tuple2_Int_Int* pvar5_point = _tmp011;
|
|
128
|
+
int pvar5_outX = _tmp011->value.Tuple2.member0;
|
|
129
|
+
int pvar5_outY = _tmp011->value.Tuple2.member1;
|
|
130
|
+
_tmp010 = pvar5_outY;
|
|
131
|
+
}
|
|
132
|
+
return _tmp010;
|
|
133
|
+
}
|
|
134
|
+
static int distant2_0(struct Tuple2_Int_Int* pointA, struct Tuple2_Int_Int* pointB) {
|
|
135
|
+
int _tmp013;
|
|
136
|
+
int _tmp012;
|
|
137
|
+
_tmp013 = _minus_(fst_0(pointA), fst_0(pointB));
|
|
138
|
+
if (1) {
|
|
139
|
+
int _tmp015;
|
|
140
|
+
int pvar6_dx = _tmp013;
|
|
141
|
+
int _tmp014;
|
|
142
|
+
_tmp015 = _minus_(snd_0(pointA), snd_0(pointB));
|
|
143
|
+
if (1) {
|
|
144
|
+
int pvar7_dy = _tmp015;
|
|
145
|
+
_tmp014 = _plus_(_asterisk_(pvar6_dx, pvar6_dx), _asterisk_(pvar7_dy, pvar7_dy));
|
|
146
|
+
}
|
|
147
|
+
_tmp012 = _tmp014;
|
|
148
|
+
}
|
|
149
|
+
return _tmp012;
|
|
150
|
+
}
|
|
151
|
+
static int snd_0(struct Tuple2_Int_Int* t) {
|
|
152
|
+
int _tmp016;
|
|
153
|
+
if (1) {
|
|
154
|
+
int pvar8_x = t->value.Tuple2.member0;
|
|
155
|
+
int pvar8_y = t->value.Tuple2.member1;
|
|
156
|
+
_tmp016 = pvar8_y;
|
|
157
|
+
}
|
|
158
|
+
return _tmp016;
|
|
159
|
+
}
|
|
160
|
+
static int fst_0(struct Tuple2_Int_Int* t) {
|
|
161
|
+
int _tmp017;
|
|
162
|
+
if (1) {
|
|
163
|
+
int pvar9_x = t->value.Tuple2.member0;
|
|
164
|
+
int pvar9_y = t->value.Tuple2.member1;
|
|
165
|
+
_tmp017 = pvar9_x;
|
|
166
|
+
}
|
|
167
|
+
return _tmp017;
|
|
168
|
+
}
|
|
169
|
+
static void refreshMark() {
|
|
170
|
+
int i;
|
|
171
|
+
for (i = 0; i < size_Tuple2_Int_Int; i++) {
|
|
172
|
+
if (memory_Tuple2_Int_Int[i].mark < Counter) memory_Tuple2_Int_Int[i].mark = 0;
|
|
173
|
+
else memory_Tuple2_Int_Int[i].mark -= Counter - 1;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
void ActivateMostDistantPoint() {
|
|
177
|
+
int current_side = 0, last_side = 1;
|
|
178
|
+
node_memory_point[last_side] = init_point();
|
|
179
|
+
mark_Tuple2_Int_Int(node_memory_point[last_side], 1 + 3);
|
|
180
|
+
node_memory_outX[last_side] = init_outX();
|
|
181
|
+
node_memory_outY[last_side] = init_outY();
|
|
182
|
+
Counter = NodeSize + 1;
|
|
183
|
+
refreshMark();
|
|
184
|
+
while (1) {
|
|
185
|
+
Counter = 1;
|
|
186
|
+
Input(&node_memory_inX[current_side], &node_memory_inY[current_side]);
|
|
187
|
+
node_point(node_memory_inX[current_side], node_memory_inY[current_side], node_memory_point[last_side], &node_memory_point[current_side]);
|
|
188
|
+
mark_Tuple2_Int_Int(node_memory_point[current_side], Counter + 3);
|
|
189
|
+
Counter++;
|
|
190
|
+
node_outX(node_memory_point[current_side], &node_memory_outX[current_side]);
|
|
191
|
+
Counter++;
|
|
192
|
+
node_outY(node_memory_point[current_side], &node_memory_outY[current_side]);
|
|
193
|
+
Counter++;
|
|
194
|
+
Output(&node_memory_outX[current_side], &node_memory_outY[current_side]);
|
|
195
|
+
refreshMark();
|
|
196
|
+
current_side ^= 1;
|
|
197
|
+
last_side ^= 1;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module MostDistantPoint
|
|
2
|
+
in
|
|
3
|
+
inX : Int, inY : Int
|
|
4
|
+
out
|
|
5
|
+
outX, outY
|
|
6
|
+
use
|
|
7
|
+
Std
|
|
8
|
+
|
|
9
|
+
#@ :assert-equals 2, distant2((1, 1), (2, 2))
|
|
10
|
+
func distant2(pointA, pointB) = {
|
|
11
|
+
dx = pointA.fst - pointB.fst
|
|
12
|
+
dy = pointA.snd - pointB.snd
|
|
13
|
+
dx * dx + dy * dy
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
node init[(0, 0)] (outX, outY) as point = {
|
|
17
|
+
d1 = distant2((0, 0), point@last)
|
|
18
|
+
d2 = distant2((0, 0), (inX, inY))
|
|
19
|
+
if d1 < d2 then (inX, inY) else point@last
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#@ :assert-module
|
|
23
|
+
#- 0, 0 => 0, 0
|
|
24
|
+
#@ : 1, 1 => 1, 1
|
|
25
|
+
#@ : 0, 0 => 1, 1
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#include "MostDistantPoint.h"
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
|
|
4
|
+
void Input(int* inX, int* inY) {
|
|
5
|
+
scanf("%d %d", inX, inY);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
void Output(int* outX, int* outY) {
|
|
9
|
+
printf("%d %d\n", *outX, *outY);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
int main() {
|
|
13
|
+
ActivateMostDistantPoint();
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
digraph MostDistantPoint {
|
|
2
|
+
inX [label = "inX : Int", shape = "invhouse"];
|
|
3
|
+
inY [label = "inY : Int", shape = "invhouse"];
|
|
4
|
+
point [label = "point : Tuple2[Int, Int]"];
|
|
5
|
+
outX [label = "outX : Int", style = filled, fillcolor = "#e4e4e4"];
|
|
6
|
+
outY [label = "outY : Int", style = filled, fillcolor = "#e4e4e4"];
|
|
7
|
+
point -> outX;
|
|
8
|
+
inX -> point;
|
|
9
|
+
inY -> point;
|
|
10
|
+
point -> point [style = dashed];
|
|
11
|
+
point -> outY;
|
|
12
|
+
}
|
|
Binary file
|
|
@@ -0,0 +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
|
|
@@ -0,0 +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
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
module Emfrp
|
|
2
|
+
class CodegenContext
|
|
3
|
+
SymbolToStr = {
|
|
4
|
+
"!" => "_exclamation_",
|
|
5
|
+
"#" => "_hash_",
|
|
6
|
+
"$" => "_dollar_",
|
|
7
|
+
"%" => "_parcent_",
|
|
8
|
+
"&" => "_anpersand",
|
|
9
|
+
"*" => "_asterisk_",
|
|
10
|
+
"+" => "_plus_",
|
|
11
|
+
"." => "_dot_",
|
|
12
|
+
"/" => "_slash_",
|
|
13
|
+
"<" => "_lt_",
|
|
14
|
+
"=" => "_eq_",
|
|
15
|
+
">" => "_gt_",
|
|
16
|
+
"?" => "_question_",
|
|
17
|
+
"@" => "_at_",
|
|
18
|
+
"\\" => "_backslash_",
|
|
19
|
+
"^" => "_caret_",
|
|
20
|
+
"|" => "_vertial_",
|
|
21
|
+
"-" => "_minus_",
|
|
22
|
+
"~" => "_tilde_"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
def initialize(top)
|
|
26
|
+
@top = top
|
|
27
|
+
@global_vars = []
|
|
28
|
+
@funcs = []
|
|
29
|
+
@structs = []
|
|
30
|
+
@protos = []
|
|
31
|
+
@static_protos = []
|
|
32
|
+
@macros = []
|
|
33
|
+
@init_stmts = []
|
|
34
|
+
@templates = []
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def code_generate(c_output, h_output, main_output, name)
|
|
38
|
+
# generate header-file
|
|
39
|
+
h_output << "#ifndef #{name.upcase}_H\n"
|
|
40
|
+
h_output << "#define #{name.upcase}_H\n\n"
|
|
41
|
+
@protos.each do |x|
|
|
42
|
+
h_output.puts x.to_s
|
|
43
|
+
end
|
|
44
|
+
h_output << "\n#endif /* end of include guard */\n"
|
|
45
|
+
# generate library-file
|
|
46
|
+
c_output.puts "#include \"#{name}.h\""
|
|
47
|
+
c_output.puts "/* Primitive functions (Macros) */"
|
|
48
|
+
@macros.each do |x|
|
|
49
|
+
c_output.puts x.to_s
|
|
50
|
+
end
|
|
51
|
+
c_output.puts "/* Data types */"
|
|
52
|
+
@structs.each do |x|
|
|
53
|
+
c_output.puts x.to_s
|
|
54
|
+
end
|
|
55
|
+
c_output.puts "/* Global variables */"
|
|
56
|
+
@global_vars.each do |x|
|
|
57
|
+
c_output.puts x.to_s
|
|
58
|
+
end
|
|
59
|
+
c_output.puts "/* Static prototypes */"
|
|
60
|
+
@static_protos.each do |x|
|
|
61
|
+
c_output.puts x.to_s
|
|
62
|
+
end
|
|
63
|
+
c_output.puts "/* Functions, Constructors, GCMarkers, etc... */"
|
|
64
|
+
@funcs.each do |x|
|
|
65
|
+
c_output.puts x.to_s
|
|
66
|
+
end
|
|
67
|
+
# generate main-file
|
|
68
|
+
main_output << "#include \"#{name}.h\"\n\n"
|
|
69
|
+
main_output << "void Input(#{@top[:inputs].map{|x| "#{tref(x)}* #{x[:name][:desc]}"}.join(", ")}) {\n /* Your code goes here... */\n}\n"
|
|
70
|
+
main_output << "void Output(#{@top[:outputs].map{|x| "#{tref(x)}* #{x[:name][:desc]}"}.join(", ")}) {\n /* Your code goes here... */\n}\n"
|
|
71
|
+
main_output << "int main() {\n Activate#{@top[:module_name][:desc]}();\n}\n"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def init_stmts
|
|
75
|
+
@init_stmts
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def func_name(name, ret_utype, arg_utypes)
|
|
79
|
+
case f = @top[:dict][:func_space][name].get
|
|
80
|
+
when PrimFuncDef
|
|
81
|
+
f.func_name(self)
|
|
82
|
+
when FuncDef
|
|
83
|
+
key = [ret_utype, *arg_utypes].map(&:to_uniq_str) + [name]
|
|
84
|
+
@top[:dict][:ifunc_space][key].get.func_name(self)
|
|
85
|
+
else
|
|
86
|
+
raise "Assertion error: unexpected func type #{f.class}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def constructor_name(name, utype)
|
|
91
|
+
@top[:dict][:itype_space][utype.to_uniq_str].get[:tvalues].each do |tval|
|
|
92
|
+
if tval[:name][:desc] == name
|
|
93
|
+
return tval.constructor_name(self)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
raise "Assertion error: #{name} is not found"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def escape_name(name)
|
|
100
|
+
rexp = Regexp.new("[" + Regexp.escape(SymbolToStr.keys.join) + "]")
|
|
101
|
+
name.gsub(rexp, SymbolToStr)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def tdef(x)
|
|
105
|
+
case x
|
|
106
|
+
when Typing::UnionType
|
|
107
|
+
key = x.to_uniq_str
|
|
108
|
+
if @top[:dict][:type_space][key] && @top[:dict][:type_space][key].get.is_a?(PrimTypeDef)
|
|
109
|
+
@top[:dict][:type_space][key].get
|
|
110
|
+
elsif @top[:dict][:itype_space][key]
|
|
111
|
+
@top[:dict][:itype_space][key].get
|
|
112
|
+
else
|
|
113
|
+
raise "Assertion error: itype #{x.to_uniq_str} is undefined"
|
|
114
|
+
end
|
|
115
|
+
when Syntax
|
|
116
|
+
tdef(x[:typing])
|
|
117
|
+
else
|
|
118
|
+
raise "Assertion error"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def tref(x)
|
|
123
|
+
tdef(x).ref_name(self)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def serial(key, id)
|
|
127
|
+
@serials ||= Hash.new{|h, k| h[k] = []}
|
|
128
|
+
@serials[key] << id unless @serials[key].find{|x| x == id}
|
|
129
|
+
return @serials[key].index{|x| x == id}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def uniq_id_gen
|
|
133
|
+
@uniq_ids ||= (0..1000).to_a
|
|
134
|
+
@uniq_ids.shift
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def define_global_var(type_str, name_str, initial_value_str=nil)
|
|
138
|
+
@global_vars << "#{type_str} #{name_str}" + (initial_value_str ? " = #{initial_value_str}" : "") + ";"
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def define_macro(name_str, params, body_str)
|
|
142
|
+
@macros << "#define #{name_str}(#{params.join(", ")}) (#{body_str})"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def define_func(type_str, name_str, params, accessor=:static, with_proto=true, &block)
|
|
146
|
+
elements = []
|
|
147
|
+
proc.call(elements)
|
|
148
|
+
case accessor
|
|
149
|
+
when :none then deco = ""
|
|
150
|
+
when :static then deco = "static "
|
|
151
|
+
end
|
|
152
|
+
define_proto(type_str, name_str, params.map(&:first), accessor) if with_proto
|
|
153
|
+
@funcs << Block.new("#{deco}#{type_str} #{name_str}(#{params.map{|a, b| "#{a} #{b}"}.join(", ")}) {", elements, "}")
|
|
154
|
+
return nil
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def define_proto(type_str, name_str, param_types, accessor=:static)
|
|
158
|
+
case accessor
|
|
159
|
+
when :none then deco = ""
|
|
160
|
+
when :static then deco = "static "
|
|
161
|
+
when :extern then deco = "extern "
|
|
162
|
+
end
|
|
163
|
+
proto = "#{deco}#{type_str} #{name_str}(#{param_types.join(", ")});"
|
|
164
|
+
if accessor == :static || accessor == :extern
|
|
165
|
+
@static_protos << proto
|
|
166
|
+
else
|
|
167
|
+
@protos << proto
|
|
168
|
+
end
|
|
169
|
+
return nil
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def define_init_stmt(stmt)
|
|
173
|
+
@init_stmts << stmt
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def define_struct(kind_str, name_str, var_name_str)
|
|
177
|
+
elements = []
|
|
178
|
+
proc.call(elements)
|
|
179
|
+
x = Block.new("#{kind_str} #{name_str}{", elements, "}#{var_name_str};")
|
|
180
|
+
if name_str
|
|
181
|
+
@structs << x
|
|
182
|
+
return nil
|
|
183
|
+
else
|
|
184
|
+
return x
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def make_block(head_str, elements, foot_str)
|
|
189
|
+
Block.new(head_str, elements, foot_str)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
class Block
|
|
193
|
+
T = (0..20).map{|i| " " * i}
|
|
194
|
+
def initialize(head_str, elements, foot_str)
|
|
195
|
+
@head_str = head_str
|
|
196
|
+
@elements = elements
|
|
197
|
+
@foot_str = foot_str
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def to_s(t=0)
|
|
201
|
+
res = ""
|
|
202
|
+
res << T[t] + @head_str + "\n"
|
|
203
|
+
@elements.each do |e|
|
|
204
|
+
case e
|
|
205
|
+
when Block
|
|
206
|
+
res << e.to_s(t+1) + "\n"
|
|
207
|
+
when String
|
|
208
|
+
res << T[t+1] + e + "\n"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
res << T[t] + @foot_str
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|