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,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,6 @@
1
+ #ifndef MOSTDISTANTPOINT_H
2
+ #define MOSTDISTANTPOINT_H
3
+
4
+ void ActivateMostDistantPoint();
5
+
6
+ #endif /* end of include guard */
@@ -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