sfrp 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.ctags +3 -0
- data/.editorconfig +9 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +629 -0
- data/.travis.yml +12 -0
- data/Gemfile +2 -0
- data/LICENSE +28 -0
- data/README.md +34 -0
- data/Rakefile +1 -0
- data/base-library/Base.sfrp +81 -0
- data/base-library/IO/AVR/ATMEGA8.c +9 -0
- data/base-library/IO/AVR/ATMEGA8.h +6 -0
- data/base-library/IO/AVR/ATMEGA8.sfrp +4 -0
- data/base-library/IO/STDIO.c +40 -0
- data/base-library/IO/STDIO.h +13 -0
- data/base-library/IO/STDIO.sfrp +10 -0
- data/bin/sfrp +7 -0
- data/lib/sfrp.rb +2 -0
- data/lib/sfrp/command.rb +73 -0
- data/lib/sfrp/compiler.rb +94 -0
- data/lib/sfrp/error.rb +4 -0
- data/lib/sfrp/file.rb +18 -0
- data/lib/sfrp/flat/dsl.rb +33 -0
- data/lib/sfrp/flat/elements.rb +90 -0
- data/lib/sfrp/flat/exception.rb +45 -0
- data/lib/sfrp/flat/expression.rb +125 -0
- data/lib/sfrp/flat/set.rb +61 -0
- data/lib/sfrp/input/exception.rb +16 -0
- data/lib/sfrp/input/parser.rb +417 -0
- data/lib/sfrp/input/set.rb +29 -0
- data/lib/sfrp/input/transformer.rb +219 -0
- data/lib/sfrp/low/dsl.rb +126 -0
- data/lib/sfrp/low/element.rb +126 -0
- data/lib/sfrp/low/set.rb +62 -0
- data/lib/sfrp/mono/dsl.rb +120 -0
- data/lib/sfrp/mono/environment.rb +26 -0
- data/lib/sfrp/mono/exception.rb +21 -0
- data/lib/sfrp/mono/expression.rb +124 -0
- data/lib/sfrp/mono/function.rb +86 -0
- data/lib/sfrp/mono/memory.rb +32 -0
- data/lib/sfrp/mono/node.rb +125 -0
- data/lib/sfrp/mono/pattern.rb +69 -0
- data/lib/sfrp/mono/set.rb +151 -0
- data/lib/sfrp/mono/type.rb +210 -0
- data/lib/sfrp/mono/vconst.rb +134 -0
- data/lib/sfrp/output/set.rb +33 -0
- data/lib/sfrp/poly/dsl.rb +171 -0
- data/lib/sfrp/poly/elements.rb +168 -0
- data/lib/sfrp/poly/exception.rb +42 -0
- data/lib/sfrp/poly/expression.rb +170 -0
- data/lib/sfrp/poly/monofier.rb +73 -0
- data/lib/sfrp/poly/set.rb +90 -0
- data/lib/sfrp/poly/typing.rb +197 -0
- data/lib/sfrp/raw/dsl.rb +41 -0
- data/lib/sfrp/raw/elements.rb +164 -0
- data/lib/sfrp/raw/exception.rb +40 -0
- data/lib/sfrp/raw/expression.rb +168 -0
- data/lib/sfrp/raw/namespace.rb +30 -0
- data/lib/sfrp/raw/set.rb +109 -0
- data/lib/sfrp/version.rb +3 -0
- data/sfrp.gemspec +40 -0
- data/spec/sfrp/Test.sfrp +4 -0
- data/spec/sfrp/compiler_spec.rb +17 -0
- data/spec/sfrp/flat/set_spec.rb +40 -0
- data/spec/sfrp/input/parse_test.sfrp +20 -0
- data/spec/sfrp/input/set_spec.rb +18 -0
- data/spec/sfrp/low/set_spec.rb +20 -0
- data/spec/sfrp/mono/expected.yml +295 -0
- data/spec/sfrp/mono/set_spec.rb +152 -0
- data/spec/sfrp/output/set_spec.rb +29 -0
- data/spec/sfrp/poly/set_spec.rb +290 -0
- data/spec/sfrp/raw/set_spec.rb +38 -0
- data/spec/spec_helper.rb +16 -0
- data/test/IntTest/Main.c +5 -0
- data/test/IntTest/Main.h +6 -0
- data/test/IntTest/Main.sfrp +10 -0
- data/test/IntTest/in.txt +3 -0
- data/test/IntTest/out.txt +4 -0
- data/test/MaybeTest/Main.sfrp +8 -0
- data/test/MaybeTest/SubDir/Lib.sfrp +9 -0
- data/test/MaybeTest/in.txt +6 -0
- data/test/MaybeTest/out.txt +6 -0
- data/test/Rakefile +15 -0
- 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
|
data/lib/sfrp/low/dsl.rb
ADDED
@@ -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
|