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,125 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Mono
|
3
|
+
class Node
|
4
|
+
NodeRef = Struct.new(:node_str, :last)
|
5
|
+
|
6
|
+
attr_reader :str
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
str, type_str, node_refs, eval_func_str, init_func_str = nil
|
10
|
+
)
|
11
|
+
@str = str
|
12
|
+
@type_str = type_str
|
13
|
+
@node_refs = node_refs
|
14
|
+
@eval_func_str = eval_func_str
|
15
|
+
@init_func_str = init_func_str
|
16
|
+
end
|
17
|
+
|
18
|
+
def comp
|
19
|
+
[@str, @type_str, @node_refs, @eval_func_str, @init_func_str]
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
comp == other.comp
|
24
|
+
end
|
25
|
+
|
26
|
+
# Is this node initialized?
|
27
|
+
def initialized?
|
28
|
+
@init_func_str
|
29
|
+
end
|
30
|
+
|
31
|
+
# Name of variable to hold current and last evaluated value of this node.
|
32
|
+
def low_node_str
|
33
|
+
@str
|
34
|
+
end
|
35
|
+
|
36
|
+
def memory_used_to_eval_node(set)
|
37
|
+
set.func(@eval_func_str).memory(set)
|
38
|
+
end
|
39
|
+
|
40
|
+
def memory_used_to_init_node(set)
|
41
|
+
return Memory.empty unless initialized?
|
42
|
+
set.func(@init_func_str).memory(set)
|
43
|
+
end
|
44
|
+
|
45
|
+
def memory_used_to_hold_node(set)
|
46
|
+
set.type(@type_str).memory(set)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return referrence name of current evaluated value of this node.
|
50
|
+
def low_node_ref_current_str
|
51
|
+
index = (initialized? ? 'c' : '0')
|
52
|
+
"#{low_node_str}[#{index}]"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Return referrence name of last evaluated value of this node.
|
56
|
+
def low_node_ref_last_str
|
57
|
+
"#{low_node_str}[l]"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return a list of nodes sorted by evaluation-order including this node.
|
61
|
+
# The list includes only nodes (recursively) depended by this node.
|
62
|
+
# So if you want to get a list including all nodes, you must call this
|
63
|
+
# method for an output node.
|
64
|
+
def sorted_node_strs(set)
|
65
|
+
cur = current_referred_node_strs(set)
|
66
|
+
last = last_referred_node_strs(set)
|
67
|
+
cur + (last - cur)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Generate a statement of initialization if needed.
|
71
|
+
def gen_initialize_stmt(set, stmts)
|
72
|
+
return unless initialized?
|
73
|
+
call_exp = set.func(@init_func_str).low_call_exp([])
|
74
|
+
stmts << L.stmt("#{low_node_str}[l] = #{call_exp}")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Generate declaration for variable to hold value of node.
|
78
|
+
def gen_node_var_declaration(set, stmts)
|
79
|
+
type = set.type(@type_str)
|
80
|
+
size = (initialized? ? '2' : '1')
|
81
|
+
stmts << L.stmt("#{type.low_type_str} #{low_node_str}[#{size}]")
|
82
|
+
end
|
83
|
+
|
84
|
+
# Generate ststement to evaluate this node.
|
85
|
+
def gen_evaluate_stmt(set, stmts)
|
86
|
+
arg_exps = @node_refs.map do |node_ref|
|
87
|
+
n = set.node(node_ref.node_str)
|
88
|
+
node_ref.last ? n.low_node_ref_last_str : n.low_node_ref_current_str
|
89
|
+
end
|
90
|
+
call_exp = set.func(@eval_func_str).low_call_exp(arg_exps)
|
91
|
+
stmts << L.stmt("#{low_node_ref_current_str} = #{call_exp}")
|
92
|
+
end
|
93
|
+
|
94
|
+
# Generate statement to mark node[l].
|
95
|
+
def gen_node_var_mark_stmt(set, stmts)
|
96
|
+
return unless initialized?
|
97
|
+
return unless set.type(@type_str).need_mark?(set)
|
98
|
+
mark_func_str = set.type(@type_str).low_mark_func_str
|
99
|
+
stmts << L.stmt("#{mark_func_str}(#{low_node_str}[l])")
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
# Return a list of (recursively) current-referred nodes including myself.
|
105
|
+
def current_referred_node_strs(set, visited = {})
|
106
|
+
return [] if visited.key?(@str)
|
107
|
+
visited[@str] = true
|
108
|
+
prereq_node_strs = @node_refs.reject(&:last).flat_map do |r|
|
109
|
+
set.node(r.node_str).current_referred_node_strs(set, visited)
|
110
|
+
end
|
111
|
+
prereq_node_strs + [@str]
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return a list of (recursively) last-referred nodes.
|
115
|
+
def last_referred_node_strs(set, visited = {})
|
116
|
+
return [] if visited.key?(@str)
|
117
|
+
visited[@str] = true
|
118
|
+
rec = @node_refs.reject(&:last).flat_map do |r|
|
119
|
+
set.node(r.node_str).last_referred_node_strs(set, visited)
|
120
|
+
end
|
121
|
+
(@node_refs.select(&:last).map(&:node_str) + rec).uniq
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Mono
|
3
|
+
class Pattern
|
4
|
+
PatternExample = Struct.new(:vconst_str, :args)
|
5
|
+
|
6
|
+
def initialize(type_str, vconst_str, ref_var_str, arg_patterns)
|
7
|
+
@type_str = type_str
|
8
|
+
@vconst_str = vconst_str
|
9
|
+
@ref_var_str = ref_var_str
|
10
|
+
@arg_patterns = arg_patterns
|
11
|
+
end
|
12
|
+
|
13
|
+
def comp
|
14
|
+
[@type_str, @vconst_str, @ref_var_str, @arg_patterns]
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
comp == other.comp
|
19
|
+
end
|
20
|
+
|
21
|
+
def any?
|
22
|
+
@vconst_str.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def named?
|
26
|
+
@ref_var_str
|
27
|
+
end
|
28
|
+
|
29
|
+
def accept?(pattern_example)
|
30
|
+
return true if any?
|
31
|
+
return false unless pattern_example.vconst_str == @vconst_str
|
32
|
+
@arg_patterns.zip(pattern_example.args).all? do |pat, pat_exam|
|
33
|
+
pat.accept?(pat_exam)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return whole conditional-low-exps for the pattern-matching.
|
38
|
+
def low_cond_exps(set, receiver_exp)
|
39
|
+
return [] if any?
|
40
|
+
vconst = set.vconst(@vconst_str)
|
41
|
+
children = @arg_patterns.each_with_index.flat_map do |pat, mem_id|
|
42
|
+
new_receiver = child_receiver_exp(set, receiver_exp, mem_id)
|
43
|
+
pat.low_cond_exps(set, new_receiver)
|
44
|
+
end
|
45
|
+
vconst.low_compare_exps(set, receiver_exp) + children
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return whole let-low-exps for the pattern-matching.
|
49
|
+
def low_let_exps(set, receiver_exp, env)
|
50
|
+
env.add_var(@ref_var_str, @type_str) if named?
|
51
|
+
lets = (named? ? ["#{@ref_var_str} = (#{receiver_exp})"] : [])
|
52
|
+
return lets if any?
|
53
|
+
children = @arg_patterns.each_with_index.flat_map do |pat, mem_id|
|
54
|
+
new_receiver = child_receiver_exp(set, receiver_exp, mem_id)
|
55
|
+
pat.low_let_exps(set, new_receiver, env)
|
56
|
+
end
|
57
|
+
lets + children
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def child_receiver_exp(set, parent_receiver_exp, member_id)
|
63
|
+
type = set.type(@type_str)
|
64
|
+
terms_str = type.terms_access_str(parent_receiver_exp)
|
65
|
+
"#{terms_str}.term#{type.term_id(@vconst_str)}.member#{member_id}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'sfrp/mono/environment'
|
2
|
+
require 'sfrp/mono/expression'
|
3
|
+
require 'sfrp/mono/function'
|
4
|
+
require 'sfrp/mono/memory'
|
5
|
+
require 'sfrp/mono/node'
|
6
|
+
require 'sfrp/mono/pattern'
|
7
|
+
require 'sfrp/mono/type'
|
8
|
+
require 'sfrp/mono/vconst'
|
9
|
+
require 'sfrp/mono/dsl'
|
10
|
+
|
11
|
+
module SFRP
|
12
|
+
module Mono
|
13
|
+
class Set
|
14
|
+
def initialize(&block)
|
15
|
+
@func_h = {}
|
16
|
+
@node_h = {}
|
17
|
+
@type_h = {}
|
18
|
+
@vconst_h = {}
|
19
|
+
@output_node_strs = []
|
20
|
+
@init_func_strs = []
|
21
|
+
@type_alias_h = {}
|
22
|
+
@constructor_alias_h = {}
|
23
|
+
block.call(self) if block
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_low(include_file_strs = [])
|
27
|
+
Low::Set.new do |low_set|
|
28
|
+
include_file_strs.each { |s| low_set << L.include_dq(s) }
|
29
|
+
@type_alias_h.each do |alias_str, original_str|
|
30
|
+
low_set << type(original_str).low_typedef_for_alias(alias_str)
|
31
|
+
end
|
32
|
+
@constructor_alias_h.each do |alias_str, original_str|
|
33
|
+
low_set << vconst(original_str).low_macro_for_alias(alias_str)
|
34
|
+
end
|
35
|
+
@func_h.values.each { |func| func.gen(self, low_set) }
|
36
|
+
@type_h.values.each { |type| type.gen(self, low_set) }
|
37
|
+
gen_main_func(low_set)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def check
|
42
|
+
# TODO: Check that all init_func does not waste any memory.
|
43
|
+
# TODO: Check completeness of pattern matchings.
|
44
|
+
end
|
45
|
+
|
46
|
+
def memory(type_str)
|
47
|
+
@memory ||= begin
|
48
|
+
to_init_nodes = nodes.reduce(Memory.empty) do |m, node|
|
49
|
+
m.and(node.memory_used_to_init_node(self))
|
50
|
+
end
|
51
|
+
to_hold_memoized_nodes = nodes.reduce(Memory.empty) do |m, node|
|
52
|
+
node.initialized? ? m.and(node.memory_used_to_hold_node(self)) : m
|
53
|
+
end
|
54
|
+
to_eval_nodes = nodes.reduce(Memory.empty) do |m, node|
|
55
|
+
m.and(node.memory_used_to_eval_node(self))
|
56
|
+
end
|
57
|
+
to_hold_memoized_nodes.and(to_eval_nodes).or(to_init_nodes)
|
58
|
+
end
|
59
|
+
@memory.count(type_str)
|
60
|
+
end
|
61
|
+
|
62
|
+
def <<(element)
|
63
|
+
case element
|
64
|
+
when Function
|
65
|
+
@func_h[element.str] = element
|
66
|
+
when Node
|
67
|
+
@node_h[element.str] = element
|
68
|
+
when Type
|
69
|
+
@type_h[element.str] = element
|
70
|
+
when VConst
|
71
|
+
@vconst_h[element.str] = element
|
72
|
+
else
|
73
|
+
raise
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def append_output_node_str(output_node_str)
|
78
|
+
@output_node_strs << output_node_str
|
79
|
+
end
|
80
|
+
|
81
|
+
def append_init_func_str(init_func_str)
|
82
|
+
@init_func_strs << init_func_str
|
83
|
+
end
|
84
|
+
|
85
|
+
def func(func_str)
|
86
|
+
raise func_str unless @func_h.key?(func_str)
|
87
|
+
@func_h[func_str]
|
88
|
+
end
|
89
|
+
|
90
|
+
def node(node_str)
|
91
|
+
raise node_str unless @node_h.key?(node_str)
|
92
|
+
@node_h[node_str]
|
93
|
+
end
|
94
|
+
|
95
|
+
def type(type_str)
|
96
|
+
raise type_str unless @type_h.key?(type_str)
|
97
|
+
@type_h[type_str]
|
98
|
+
end
|
99
|
+
|
100
|
+
def vconst(vconst_str)
|
101
|
+
raise vconst_str unless @vconst_h.key?(vconst_str)
|
102
|
+
@vconst_h[vconst_str]
|
103
|
+
end
|
104
|
+
|
105
|
+
def funcs
|
106
|
+
@func_h.values
|
107
|
+
end
|
108
|
+
|
109
|
+
def nodes
|
110
|
+
@node_h.values
|
111
|
+
end
|
112
|
+
|
113
|
+
def types
|
114
|
+
@type_h.values
|
115
|
+
end
|
116
|
+
|
117
|
+
def vconsts
|
118
|
+
@vconst_h.values
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
# All used nodes.
|
124
|
+
def used_nodes
|
125
|
+
node_strs = @output_node_strs.flat_map do |node_str|
|
126
|
+
node(node_str).sorted_node_strs(self)
|
127
|
+
end
|
128
|
+
node_strs.uniq.map { |node_str| node(node_str) }
|
129
|
+
end
|
130
|
+
|
131
|
+
# Generate the main-function.
|
132
|
+
def gen_main_func(dest_set)
|
133
|
+
dest_set << L.function('main', 'int') do |f|
|
134
|
+
f << L.stmt('int c = 0, l = 1')
|
135
|
+
used_nodes.each { |node| node.gen_node_var_declaration(self, f) }
|
136
|
+
@init_func_strs.each do |func_str|
|
137
|
+
f << L.stmt(func(func_str).low_call_exp([]))
|
138
|
+
end
|
139
|
+
used_nodes.each { |node| node.gen_initialize_stmt(self, f) }
|
140
|
+
f << L.while('1') do |wh|
|
141
|
+
@type_h.values.each { |type| type.gen_mark_cleanup_stmt(self, wh) }
|
142
|
+
used_nodes.each { |node| node.gen_node_var_mark_stmt(self, wh) }
|
143
|
+
used_nodes.each { |node| node.gen_evaluate_stmt(self, wh) }
|
144
|
+
wh << L.stmt('c ^= 1, l ^= 1')
|
145
|
+
end
|
146
|
+
f << L.stmt('return 0')
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Mono
|
3
|
+
class Type
|
4
|
+
attr_reader :str
|
5
|
+
|
6
|
+
def initialize(str, vconst_strs = nil, static = false, native_str = nil)
|
7
|
+
@str = str
|
8
|
+
@vconst_strs = vconst_strs
|
9
|
+
@static = static
|
10
|
+
@native_str = native_str
|
11
|
+
end
|
12
|
+
|
13
|
+
def comp
|
14
|
+
[@str, @vconst_strs, @static, @native_str]
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
comp == other.comp
|
19
|
+
end
|
20
|
+
|
21
|
+
# Are objects of this type passed through value?
|
22
|
+
# Defalut is passing through referrence.
|
23
|
+
def static?
|
24
|
+
@static
|
25
|
+
end
|
26
|
+
|
27
|
+
# Does this type has infinite amount of vconsts?
|
28
|
+
def infinite?
|
29
|
+
@vconst_strs.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Is this type native type?
|
33
|
+
def native?
|
34
|
+
@native_str
|
35
|
+
end
|
36
|
+
|
37
|
+
# Does this type has single vconst of native type parameters
|
38
|
+
# e.g. Tuple3(Int, Int, Int)
|
39
|
+
def linear?(set)
|
40
|
+
single_vconst? && set.vconst(@vconst_strs[0]).native_args?(set)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Does this type has only one vconst?
|
44
|
+
def single_vconst?
|
45
|
+
!infinite? && @vconst_strs.size == 1
|
46
|
+
end
|
47
|
+
|
48
|
+
# Do objects of this type need to be passed to mark-function?
|
49
|
+
def need_mark?(set)
|
50
|
+
return true unless static?
|
51
|
+
return false if infinite?
|
52
|
+
@vconst_strs.any? { |v_str| set.vconst(v_str).param_needing_mark?(set) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def has_meta_in_struct?
|
56
|
+
!(static? && single_vconst?)
|
57
|
+
end
|
58
|
+
|
59
|
+
def all_pattern_examples(set)
|
60
|
+
return [Pattern::PatternExample.new(nil, [])] if infinite?
|
61
|
+
@vconst_strs.flat_map do |vc_str|
|
62
|
+
set.vconst(vc_str).all_pattern_examples(set)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return max memory size to hold an instance of this type.
|
67
|
+
def memory(set)
|
68
|
+
return Memory.one(@str) if infinite?
|
69
|
+
x = @vconst_strs.reduce(Memory.empty) do |m, v_str|
|
70
|
+
m.or(set.vconst(v_str).memory(set))
|
71
|
+
end
|
72
|
+
Memory.one(@str).and(x)
|
73
|
+
end
|
74
|
+
|
75
|
+
def low_typedef_for_alias(alias_str)
|
76
|
+
L.typedef("#{low_type_str} #{alias_str}")
|
77
|
+
end
|
78
|
+
|
79
|
+
def low_type_str
|
80
|
+
@native_str ? @native_str : @str
|
81
|
+
end
|
82
|
+
|
83
|
+
def low_allocator_str
|
84
|
+
"alloc_#{@str}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def low_mark_func_str
|
88
|
+
"mark_#{@str}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def meta_access_str(receiver_str)
|
92
|
+
"#{receiver_str}#{static? ? '.' : '->'}meta"
|
93
|
+
end
|
94
|
+
|
95
|
+
def terms_access_str(receiver_str)
|
96
|
+
"#{receiver_str}#{static? ? '.' : '->'}terms"
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return term-id of given vconst of this type.
|
100
|
+
def term_id(vconst_str)
|
101
|
+
raise "#{@str} is infinite" if infinite?
|
102
|
+
res = @vconst_strs.index(vconst_str)
|
103
|
+
raise "#{vconst_str} is not a vconst of #{@str}" unless res
|
104
|
+
res
|
105
|
+
end
|
106
|
+
|
107
|
+
def low_member_pointers_for_single_vconst(set, receiver_str)
|
108
|
+
raise unless single_vconst?
|
109
|
+
set.vconst(@vconst_strs[0]).low_member_pointers(self, receiver_str)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Generate C's elements for this type.
|
113
|
+
def gen(src_set, dest_set)
|
114
|
+
gen_struct(src_set, dest_set)
|
115
|
+
gen_typedef(src_set, dest_set)
|
116
|
+
gen_constructor(src_set, dest_set)
|
117
|
+
gen_allocator(src_set, dest_set)
|
118
|
+
gen_mark_function(src_set, dest_set)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Generate statement to clean up objects of this types.
|
122
|
+
def gen_mark_cleanup_stmt(src_set, stmts)
|
123
|
+
return unless need_mark?(src_set)
|
124
|
+
return if src_set.memory(@str) == 0
|
125
|
+
stmts << L.stmt("#{low_allocator_str}(1)")
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
# Generate struct for this type.
|
131
|
+
def gen_struct(src_set, dest_set)
|
132
|
+
return if native? || infinite?
|
133
|
+
dest_set << L.struct(@str) do |top|
|
134
|
+
if has_meta_in_struct?
|
135
|
+
top << L.member_structure('struct', 'meta') do |meta|
|
136
|
+
meta << L.member('unsigned char term_id : 7')
|
137
|
+
meta << L.member('unsigned char mark : 1')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
top << L.member_structure('union', 'terms') do |terms|
|
141
|
+
@vconst_strs.each_with_index do |v_str, term_id|
|
142
|
+
vconst = src_set.vconst(v_str)
|
143
|
+
vconst.gen_term_definition(src_set, term_id, terms)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Generate typedef for this type.
|
150
|
+
def gen_typedef(_src_set, dest_set)
|
151
|
+
return if native?
|
152
|
+
asta = static? ? '' : '*'
|
153
|
+
dest_set << L.typedef("struct #{@str}#{asta} #{@str}")
|
154
|
+
end
|
155
|
+
|
156
|
+
# Generate constructor-functions for vconsts.
|
157
|
+
def gen_constructor(src_set, dest_set)
|
158
|
+
return if infinite?
|
159
|
+
@vconst_strs.each_with_index do |v_str, term_id|
|
160
|
+
src_set.vconst(v_str).gen_constructor(src_set, term_id, dest_set)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Generate allocator-function for type.
|
165
|
+
def gen_allocator(src_set, dest_set)
|
166
|
+
return if static?
|
167
|
+
count = src_set.memory(@str)
|
168
|
+
memory_var = "memory_#{low_type_str}"
|
169
|
+
dest_set << L.function(low_allocator_str, low_type_str) do |f|
|
170
|
+
f.append_param('int', 'clean_up')
|
171
|
+
f << L.stmt('static int i = 0')
|
172
|
+
f << L.stmt("static struct #{low_type_str} #{memory_var}[#{count}]")
|
173
|
+
f << L.if_stmt('clean_up') do |if_stmts|
|
174
|
+
e = "#{memory_var}[i].meta.mark = 0"
|
175
|
+
if_stmts << L.stmt("for (i = 0; i < #{count}; i++) #{e}")
|
176
|
+
if_stmts << L.stmt('i = 0')
|
177
|
+
if_stmts << L.stmt('return 0')
|
178
|
+
end
|
179
|
+
f << L.stmt("while (#{memory_var}[i++].meta.mark)")
|
180
|
+
f << L.stmt("return #{memory_var} + (i - 1)")
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Generate mark function for this type.
|
185
|
+
def gen_mark_function(src_set, dest_set)
|
186
|
+
return unless need_mark?(src_set)
|
187
|
+
dest_set << L.function(low_mark_func_str, 'int') do |f|
|
188
|
+
f.append_param(low_type_str, 'target')
|
189
|
+
f << L.stmt("#{meta_access_str('target')}.mark = 1") unless static?
|
190
|
+
@vconst_strs.each_with_index do |v_str, term_id|
|
191
|
+
vconst = src_set.vconst(v_str)
|
192
|
+
cond_exps = vconst.low_compare_exps(src_set, 'target')
|
193
|
+
mark_exps = vconst.low_mark_element_exps(src_set, term_id, 'target')
|
194
|
+
next if mark_exps.empty?
|
195
|
+
mark_stmt = L.stmt(mark_exps.join(', '))
|
196
|
+
if cond_exps.empty?
|
197
|
+
f << mark_stmt
|
198
|
+
else
|
199
|
+
cond_exp = cond_exps.reduce { |a, e| "#{a} && #{e}" }
|
200
|
+
f << L.if_stmt(cond_exp) do |i|
|
201
|
+
i << mark_stmt
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
f << L.stmt('return 0')
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|