sfrp 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags +3 -0
  3. data/.editorconfig +9 -0
  4. data/.gitignore +14 -0
  5. data/.rubocop.yml +629 -0
  6. data/.travis.yml +12 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +28 -0
  9. data/README.md +34 -0
  10. data/Rakefile +1 -0
  11. data/base-library/Base.sfrp +81 -0
  12. data/base-library/IO/AVR/ATMEGA8.c +9 -0
  13. data/base-library/IO/AVR/ATMEGA8.h +6 -0
  14. data/base-library/IO/AVR/ATMEGA8.sfrp +4 -0
  15. data/base-library/IO/STDIO.c +40 -0
  16. data/base-library/IO/STDIO.h +13 -0
  17. data/base-library/IO/STDIO.sfrp +10 -0
  18. data/bin/sfrp +7 -0
  19. data/lib/sfrp.rb +2 -0
  20. data/lib/sfrp/command.rb +73 -0
  21. data/lib/sfrp/compiler.rb +94 -0
  22. data/lib/sfrp/error.rb +4 -0
  23. data/lib/sfrp/file.rb +18 -0
  24. data/lib/sfrp/flat/dsl.rb +33 -0
  25. data/lib/sfrp/flat/elements.rb +90 -0
  26. data/lib/sfrp/flat/exception.rb +45 -0
  27. data/lib/sfrp/flat/expression.rb +125 -0
  28. data/lib/sfrp/flat/set.rb +61 -0
  29. data/lib/sfrp/input/exception.rb +16 -0
  30. data/lib/sfrp/input/parser.rb +417 -0
  31. data/lib/sfrp/input/set.rb +29 -0
  32. data/lib/sfrp/input/transformer.rb +219 -0
  33. data/lib/sfrp/low/dsl.rb +126 -0
  34. data/lib/sfrp/low/element.rb +126 -0
  35. data/lib/sfrp/low/set.rb +62 -0
  36. data/lib/sfrp/mono/dsl.rb +120 -0
  37. data/lib/sfrp/mono/environment.rb +26 -0
  38. data/lib/sfrp/mono/exception.rb +21 -0
  39. data/lib/sfrp/mono/expression.rb +124 -0
  40. data/lib/sfrp/mono/function.rb +86 -0
  41. data/lib/sfrp/mono/memory.rb +32 -0
  42. data/lib/sfrp/mono/node.rb +125 -0
  43. data/lib/sfrp/mono/pattern.rb +69 -0
  44. data/lib/sfrp/mono/set.rb +151 -0
  45. data/lib/sfrp/mono/type.rb +210 -0
  46. data/lib/sfrp/mono/vconst.rb +134 -0
  47. data/lib/sfrp/output/set.rb +33 -0
  48. data/lib/sfrp/poly/dsl.rb +171 -0
  49. data/lib/sfrp/poly/elements.rb +168 -0
  50. data/lib/sfrp/poly/exception.rb +42 -0
  51. data/lib/sfrp/poly/expression.rb +170 -0
  52. data/lib/sfrp/poly/monofier.rb +73 -0
  53. data/lib/sfrp/poly/set.rb +90 -0
  54. data/lib/sfrp/poly/typing.rb +197 -0
  55. data/lib/sfrp/raw/dsl.rb +41 -0
  56. data/lib/sfrp/raw/elements.rb +164 -0
  57. data/lib/sfrp/raw/exception.rb +40 -0
  58. data/lib/sfrp/raw/expression.rb +168 -0
  59. data/lib/sfrp/raw/namespace.rb +30 -0
  60. data/lib/sfrp/raw/set.rb +109 -0
  61. data/lib/sfrp/version.rb +3 -0
  62. data/sfrp.gemspec +40 -0
  63. data/spec/sfrp/Test.sfrp +4 -0
  64. data/spec/sfrp/compiler_spec.rb +17 -0
  65. data/spec/sfrp/flat/set_spec.rb +40 -0
  66. data/spec/sfrp/input/parse_test.sfrp +20 -0
  67. data/spec/sfrp/input/set_spec.rb +18 -0
  68. data/spec/sfrp/low/set_spec.rb +20 -0
  69. data/spec/sfrp/mono/expected.yml +295 -0
  70. data/spec/sfrp/mono/set_spec.rb +152 -0
  71. data/spec/sfrp/output/set_spec.rb +29 -0
  72. data/spec/sfrp/poly/set_spec.rb +290 -0
  73. data/spec/sfrp/raw/set_spec.rb +38 -0
  74. data/spec/spec_helper.rb +16 -0
  75. data/test/IntTest/Main.c +5 -0
  76. data/test/IntTest/Main.h +6 -0
  77. data/test/IntTest/Main.sfrp +10 -0
  78. data/test/IntTest/in.txt +3 -0
  79. data/test/IntTest/out.txt +4 -0
  80. data/test/MaybeTest/Main.sfrp +8 -0
  81. data/test/MaybeTest/SubDir/Lib.sfrp +9 -0
  82. data/test/MaybeTest/in.txt +6 -0
  83. data/test/MaybeTest/out.txt +6 -0
  84. data/test/Rakefile +15 -0
  85. metadata +290 -0
@@ -0,0 +1,29 @@
1
+ require 'sfrp/input/parser'
2
+ require 'sfrp/input/transformer'
3
+ require 'sfrp/file'
4
+
5
+ module SFRP
6
+ module Input
7
+ class Set
8
+ def initialize(&block)
9
+ @source_file_h = {}
10
+ block.call(self) if block
11
+ end
12
+
13
+ def to_raw
14
+ Raw::Set.new do |dest_set|
15
+ @source_file_h.values.each do |source_file|
16
+ Parser.parse(source_file).each do |element|
17
+ dest_set << element
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # Append a source file and return missing source file names.
24
+ def append_source_file(fmodule_uri, content)
25
+ @source_file_h[fmodule_uri] = SourceFile.new(fmodule_uri, content)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,219 @@
1
+ require 'parslet'
2
+ require 'sfrp/raw/set'
3
+
4
+ module SFRP
5
+ module Input
6
+ class Transformer < Parslet::Transform
7
+ rule(:file => subtree(:x)) {
8
+ x[:defs]
9
+ }
10
+ # toplevel definition
11
+ rule(:import_def => subtree(:x)) {
12
+ ab_ns_name = x[:path].map(&:to_s).join('.')
13
+ qualifier_name = x[:as_maybe] && x[:as_maybe][:qualifier_name].to_s
14
+ Raw::Import.new(ab_ns_name, qualifier_name)
15
+ }
16
+ rule(:init_def => subtree(:x)) {
17
+ Raw::Init.new(nil, x[:func_ref], x[:args], x[:key].line_and_column[0])
18
+ }
19
+ rule(:prim_type_def => subtree(:x)) {
20
+ rname = x[:tconst_str].to_s
21
+ native_str = x[:c_type_str]
22
+ pattern = Regexp.new(x[:rexp])
23
+ replace = x[:replace].to_s
24
+ Raw::PrimTConst.new(rname, nil, native_str, pattern, replace)
25
+ }
26
+ rule(:prim_enum_type_def => subtree(:x)) {
27
+ rname = x[:tconst_str].to_s
28
+ vconsts = x[:vconst_defs]
29
+ native_str = x[:c_type_str]
30
+ vconsts.each { |v| v.tconst_rname = rname }
31
+ Raw::TConst.new(rname, nil, [], vconsts, native_str, true)
32
+ }
33
+ rule(:prim_enum_vconst_def => subtree(:x)) {
34
+ rname = x[:vconst_str].to_s
35
+ native_str = x[:c_value_str]
36
+ Raw::VConst.new(rname, nil, nil, native_str, [])
37
+ }
38
+ rule(:type_def => subtree(:x)) {
39
+ rname = x[:tconst_name].to_s
40
+ pstrs = x[:params_maybe] ? x[:params_maybe][:params].map(&:to_s) : []
41
+ vconsts = x[:vconst_defs]
42
+ static = x[:modifier] && x[:modifier][:m].to_s == '+'
43
+ vconsts.each { |v| v.tconst_rname = rname }
44
+ Raw::TConst.new(rname, nil, pstrs, vconsts, nil, static)
45
+ }
46
+ rule(:vconst_def => subtree(:x)) {
47
+ rname = x[:vconst_name].to_s
48
+ ptas = x[:type_annots_maybe] ? x[:type_annots_maybe][:type_annots] : []
49
+ Raw::VConst.new(rname, nil, nil, nil, ptas)
50
+ }
51
+ rule(:foreign_func_def => subtree(:x)) {
52
+ rname = x[:func_name].to_s
53
+ ret_ta = x[:ret_type_annot]
54
+ pstrs = Array.new(x[:params].size)
55
+ ptas = x[:params]
56
+ ffi_str = x[:c_func_name].to_s
57
+ effect = rname[0] == '$'
58
+ Raw::Function.new(rname, nil, ret_ta, pstrs, ptas, nil, ffi_str, effect)
59
+ }
60
+ rule(:function_def => subtree(:x)) {
61
+ rname = x[:func_name].to_s
62
+ ret_ta = x[:ret_type_annot]
63
+ pstrs = x[:params].map { |a| a[:param_name].to_s }
64
+ ptas = x[:params].map { |a| a[:type_annot] }
65
+ exp = x[:exp]
66
+ effect = rname[0] == '$'
67
+ Raw::Function.new(rname, nil, ret_ta, pstrs, ptas, exp, nil, effect)
68
+ }
69
+ rule(:infix_def => subtree(:x)) {
70
+ priority = Integer(x[:priority].to_s)
71
+ direction =
72
+ case x[:direction]
73
+ when 'l' then Raw::Infix::LEFT
74
+ when 'r' then Raw::Infix::RIGHT
75
+ when '' then Raw::Infix::NONE
76
+ end
77
+ Raw::Infix.new(nil, x[:func_ref], priority, direction)
78
+ }
79
+ rule(:node_def => subtree(:x)) {
80
+ Raw::Node.new(
81
+ x[:node_name].to_s, nil, x[:type_annot], x[:eval_exp], x[:init_exp]
82
+ )
83
+ }
84
+ rule(:input_def => subtree(:x)) {
85
+ Raw::Input.new(
86
+ x[:node_name].to_s, nil, x[:type_annot], x[:args], x[:init_exp],
87
+ x[:func_ref]
88
+ )
89
+ }
90
+ rule(:output_def => subtree(:x)) {
91
+ Raw::Output.new(nil, x[:args], x[:func_ref], x[:key].line_and_column[0])
92
+ }
93
+ rule(:init_def_maybe => subtree(:x)) {
94
+ x && x[:init_exp]
95
+ }
96
+ rule(:foreign_str => subtree(:x)) {
97
+ x[:str].to_s
98
+ }
99
+
100
+ # type
101
+ rule(:type_annot_maybe => subtree(:x)) {
102
+ x
103
+ }
104
+ rule(:type_annot_type => subtree(:x)) {
105
+ args = (x[:args_maybe] == nil ? [] : x[:args_maybe][:args])
106
+ Raw::TypeAnnotationType.new(x[:tconst_ref], args)
107
+ }
108
+ rule(:type_annot_tuple => subtree(:x)) {
109
+ tconst_ref = Raw::Ref.new("Tuple#{x[:args].size}")
110
+ Raw::TypeAnnotationType.new(tconst_ref, x[:args])
111
+ }
112
+ rule(:type_annot_var => subtree(:x)){
113
+ Raw::TypeAnnotationVar.new(x.to_s)
114
+ }
115
+
116
+ # expression
117
+ rule(:where_exp => subtree(:x)) {
118
+ next x[:exp] if x[:where_clause_maybe].nil?
119
+ Raw::LetExp.new(x[:exp], x[:where_clause_maybe][:assignments])
120
+ }
121
+ rule(:seq_exp => subtree(:x)) {
122
+ next x[:exp] unless x.is_a?(Array)
123
+ exps = x.map { |a| a[:exp] }
124
+ func_refs = x.drop(1).map { |a| a[:func_ref] }
125
+ Raw::SequenceExp.new(exps, func_refs)
126
+ }
127
+
128
+ # ref-exp
129
+ rule(:node_last_ref_exp => subtree(:x)) {
130
+ Raw::NodeRefExp.new(x[:node_ref], true)
131
+ }
132
+ rule(:node_current_ref_exp => subtree(:x)) {
133
+ Raw::NodeRefExp.new(x[:node_ref], false)
134
+ }
135
+ rule(:var_ref_exp => subtree(:x)) {
136
+ Raw::VarRefExp.new(x.to_s)
137
+ }
138
+
139
+ # call-exp
140
+ rule(:func_call_exp => subtree(:x)) {
141
+ Raw::FuncCallExp.new(x[:func_ref], x[:args], false)
142
+ }
143
+ rule(:io_func_call_exp => subtree(:x)) {
144
+ Raw::FuncCallExp.new(x[:func_ref], x[:args], true)
145
+ }
146
+ rule(:vc_call_exp_with_paren => subtree(:x)) {
147
+ Raw::VConstCallExp.new(x[:vconst_ref], x[:args])
148
+ }
149
+ rule(:vc_call_exp_without_paren => subtree(:x)) {
150
+ Raw::VConstCallExp.new(x[:vconst_ref], [])
151
+ }
152
+ rule(:tuple_exp => subtree(:x)) {
153
+ vconst_ref = Raw::Ref.new("Tuple#{x[:args].size}")
154
+ Raw::VConstCallExp.new(vconst_ref, x[:args])
155
+ }
156
+
157
+ # if-exp
158
+ rule(:if_exp => subtree(:x)) {
159
+ Raw::IfExp.new(x[:cond_exp], x[:then_exp], x[:else_exp])
160
+ }
161
+
162
+ # let-exp
163
+ rule(:let_exp => subtree(:x)) {
164
+ Raw::LetExp.new(x[:in_exp], x[:assignments])
165
+ }
166
+ rule(:assign => subtree(:x)) {
167
+ Raw::LetExp::Assignment.new(x[:left_pattern], x[:right_exp])
168
+ }
169
+
170
+ # match-exp
171
+ rule(:match_exp => subtree(:x)) {
172
+ Raw::MatchExp.new(x[:left_exp], x[:cases])
173
+ }
174
+ rule(:match_case => subtree(:x)) {
175
+ Raw::MatchExp::Case.new(x[:pattern], x[:exp])
176
+ }
177
+
178
+ # unary op exp
179
+ rule(:unary_op_exp => subtree(:x)) {
180
+ func_ref = Raw::Ref.new(
181
+ "'" + x[:func_ref].relative_name, x[:func_ref].qualifier_name
182
+ )
183
+ Raw::FuncCallExp.new(func_ref, [x[:exp]], false)
184
+ }
185
+
186
+ # pattern
187
+ rule(:any_pattern => simple(:x)) {
188
+ Raw::MatchExp::Pattern.new(nil, x.to_s, [])
189
+ }
190
+ rule(:vc_pattern_with_paren => subtree(:x)) {
191
+ Raw::MatchExp::Pattern.new(x[:vconst_ref], x[:var_ref], x[:args])
192
+ }
193
+ rule(:vc_pattern_without_paren => subtree(:x)) {
194
+ Raw::MatchExp::Pattern.new(x[:vconst_ref], x[:var_ref], [])
195
+ }
196
+ rule(:tuple_pattern => subtree(:x)) {
197
+ vconst_ref = Raw::Ref.new("Tuple#{x[:args].size}")
198
+ Raw::MatchExp::Pattern.new(vconst_ref, x[:var_ref], x[:args])
199
+ }
200
+ rule(:as => subtree(:x)) {
201
+ x[:str].to_s
202
+ }
203
+
204
+ # others
205
+ rule(:name => subtree(:n), :qualifier => subtree(:q)) {
206
+ Raw::Ref.new(n.to_s, q && q[:str].to_s)
207
+ }
208
+ rule(:listing => subtree(:x)) {
209
+ (x.is_a?(Array) ? x : [x]).map { |a| a[:e] }
210
+ }
211
+ rule(:listing0 => subtree(:x)) {
212
+ x == nil ? [] : x
213
+ }
214
+ rule(:opt => subtree(:x)) {
215
+ x == nil ? nil : x[:entity]
216
+ }
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,126 @@
1
+ module SFRP
2
+ module Low
3
+ module DSL
4
+ SFRP::L = self
5
+ extend self
6
+
7
+ def include_ab(str)
8
+ Include.new("<#{str}>")
9
+ end
10
+
11
+ def include_dq(str)
12
+ Include.new('"' + str + '"')
13
+ end
14
+
15
+ def function(name_str, type_str, static = false, &block)
16
+ fp = FuncProxy.new
17
+ block.call(fp) if block
18
+ Function.new(static, name_str, type_str, fp.params, fp.stmts)
19
+ end
20
+
21
+ def typedef(str)
22
+ Typedef.new(str)
23
+ end
24
+
25
+ def macro(str)
26
+ Macro.new(str)
27
+ end
28
+
29
+ def struct(name_str, &block)
30
+ members = []
31
+ block.call(members) if block
32
+ Structure.new('struct', name_str, members)
33
+ end
34
+
35
+ def member_structure(kind_str, var_str, &block)
36
+ members = []
37
+ block.call(members) if block
38
+ MemberStructure.new(kind_str, var_str, members)
39
+ end
40
+
41
+ def member(str)
42
+ Member.new(str)
43
+ end
44
+
45
+ class FuncProxy
46
+ attr_reader :params, :stmts
47
+
48
+ def initialize
49
+ @params = []
50
+ @stmts = []
51
+ end
52
+
53
+ def append_param(type_str, var_str)
54
+ @params << Function::Param.new(type_str, var_str)
55
+ end
56
+
57
+ def <<(stmt)
58
+ @stmts << stmt
59
+ end
60
+ end
61
+
62
+ # --------------------------------------------------
63
+ # Statement
64
+ # --------------------------------------------------
65
+
66
+ def stmt(line)
67
+ Statement.new(line)
68
+ end
69
+
70
+ def while(cond_exp, &block)
71
+ stmts = []
72
+ block.call(stmts) if block
73
+ Block.new('while', cond_exp, stmts)
74
+ end
75
+
76
+ def if_stmt(cond_exp, &block)
77
+ stmts = []
78
+ block.call(stmts) if block
79
+ Block.new('if', cond_exp, stmts)
80
+ end
81
+
82
+ # --------------------------------------------------
83
+ # Expression (String)
84
+ # --------------------------------------------------
85
+
86
+ def call_exp(callee_str, arg_exps)
87
+ "#{callee_str}(#{arg_exps.map { |e| "(#{e})" }.join(', ')})"
88
+ end
89
+
90
+ def if_chain_exp(&block)
91
+ ip = IfChainProxy.new
92
+ block.call(ip)
93
+ ip.to_exp
94
+ end
95
+
96
+ class IfChainProxy
97
+ def initialize
98
+ @finised = false
99
+ @cond_exps = []
100
+ @exps = []
101
+ end
102
+
103
+ def finish(exp)
104
+ return if @finished
105
+ @exps << exp
106
+ @finised = true
107
+ end
108
+
109
+ def append_case(cond_exp, exp)
110
+ return if @finised
111
+ @cond_exps << cond_exp
112
+ @exps << exp
113
+ end
114
+
115
+ def to_exp
116
+ raise if @exps.empty?
117
+ @cond_exps.pop unless @finised
118
+ @finised = true
119
+ xs = @cond_exps.zip(@exps).map { |ce, e| "(#{ce}) ? (#{e}) :" }
120
+ last = "(#{@exps[-1]})"
121
+ (xs + [last]).join(' ')
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,126 @@
1
+ module SFRP
2
+ module Low
3
+ class Element
4
+ def to_s
5
+ pretty_code
6
+ end
7
+ end
8
+
9
+ class Statement < Element
10
+ def initialize(str)
11
+ @str = str
12
+ end
13
+
14
+ def pretty_code(indent = 0)
15
+ (' ' * indent) + @str + ';'
16
+ end
17
+ end
18
+
19
+ class Block < Element
20
+ def initialize(kind_str, cond_exp, stmts)
21
+ @kind_str = kind_str
22
+ @cond_exp = cond_exp
23
+ @stmts = stmts
24
+ end
25
+
26
+ def pretty_code(indent = 0)
27
+ inner = @stmts.map { |s| s.pretty_code(indent + 1) + "\n" }.join
28
+ space = ' ' * indent
29
+ "#{space}#{@kind_str} (#{@cond_exp}) {\n#{inner}#{space}}"
30
+ end
31
+ end
32
+
33
+ class Function < Element
34
+ Param = Struct.new(:type_str, :var_str)
35
+
36
+ def initialize(static, name_str, type_str, params, stmts)
37
+ @static = static
38
+ @name_str = name_str
39
+ @type_str = type_str
40
+ @params = params
41
+ @stmts = stmts
42
+ end
43
+
44
+ def static?
45
+ @static
46
+ end
47
+
48
+ def pretty_code
49
+ inner = @stmts.map { |s| s.pretty_code(1) + "\n" }.join
50
+ param = @params.map { |pa| "#{pa.type_str} #{pa.var_str}" }.join(', ')
51
+ "#{@type_str} #{@name_str}(#{param}) {\n#{inner}}"
52
+ end
53
+
54
+ def pretty_code_prototype
55
+ "#{@type_str} #{@name_str}(#{@params.map(&:type_str).join(', ')});"
56
+ end
57
+ end
58
+
59
+ class Structure < Element
60
+ def initialize(kind_str, name_str, members)
61
+ @kind_str = kind_str
62
+ @name_str = name_str
63
+ @members = members
64
+ end
65
+
66
+ def pretty_code
67
+ inner = @members.map { |m| m.pretty_code(1) + "\n" }.join
68
+ "#{@kind_str} #{@name_str} {\n#{inner}};"
69
+ end
70
+ end
71
+
72
+ class MemberStructure < Element
73
+ def initialize(kind_str, var_str, members)
74
+ @kind_str = kind_str
75
+ @var_str = var_str
76
+ @members = members
77
+ end
78
+
79
+ def pretty_code(indent = 0)
80
+ inner = @members.map { |m| m.pretty_code(indent + 1) + "\n" }.join
81
+ space = ' ' * indent
82
+ "#{space}#{@kind_str} {\n#{inner}#{space}} #{@var_str};"
83
+ end
84
+ end
85
+
86
+ class Member < Element
87
+ def initialize(str)
88
+ @str = str
89
+ end
90
+
91
+ def pretty_code(indent = 0)
92
+ ' ' * indent + @str + ';'
93
+ end
94
+ end
95
+
96
+ class Macro < Element
97
+ def initialize(str)
98
+ @str = str
99
+ end
100
+
101
+ def pretty_code
102
+ "#define #{@str}"
103
+ end
104
+ end
105
+
106
+ class Typedef < Element
107
+ def initialize(str)
108
+ @str = str
109
+ end
110
+
111
+ def pretty_code
112
+ "typedef #{@str};"
113
+ end
114
+ end
115
+
116
+ class Include < Element
117
+ def initialize(str)
118
+ @str = str
119
+ end
120
+
121
+ def pretty_code
122
+ "#include #{@str}"
123
+ end
124
+ end
125
+ end
126
+ end