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,134 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Mono
|
3
|
+
class VConst
|
4
|
+
attr_reader :str
|
5
|
+
|
6
|
+
def initialize(str, type_str, arg_type_strs, native_str = nil)
|
7
|
+
@str = str
|
8
|
+
@type_str = type_str
|
9
|
+
@arg_type_strs = arg_type_strs
|
10
|
+
@native_str = native_str
|
11
|
+
end
|
12
|
+
|
13
|
+
def comp
|
14
|
+
[@str, @type_str, @arg_type_strs, @native_str]
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
comp == other.comp
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return max memory size to hold an instance of this vconst.
|
22
|
+
def memory(set)
|
23
|
+
@arg_type_strs.reduce(Memory.empty) do |m, t_str|
|
24
|
+
m.and(set.type(t_str).memory(set))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Is this vconst expressed in native C value?
|
29
|
+
def native?
|
30
|
+
@native_str
|
31
|
+
end
|
32
|
+
|
33
|
+
def native_args?(set)
|
34
|
+
@arg_type_strs.all? { |s| set.type(s).native? }
|
35
|
+
end
|
36
|
+
|
37
|
+
def all_pattern_examples(set)
|
38
|
+
return [Pattern::PatternExample.new(@str, [])] if @arg_type_strs.empty?
|
39
|
+
head, *tail = @arg_type_strs.map do |type_str|
|
40
|
+
set.type(type_str).all_pattern_examples(set)
|
41
|
+
end
|
42
|
+
head.product(*tail).map do |args|
|
43
|
+
Pattern::PatternExample.new(@str, args)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Generate a struct-element of term for this vconst.
|
48
|
+
def gen_term_definition(set, term_id, terms)
|
49
|
+
return if native?
|
50
|
+
terms << L.member_structure('struct', "term#{term_id}") do |term|
|
51
|
+
@arg_type_strs.each_with_index do |t_str, idx|
|
52
|
+
low_type_str = set.type(t_str).low_type_str
|
53
|
+
term << L.member("#{low_type_str} member#{idx}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Do elements of this vconst need marking?
|
59
|
+
def param_needing_mark?(set)
|
60
|
+
@arg_type_strs.any? { |type_str| set.type(type_str).need_mark?(set) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Generate constructor-function in C.
|
64
|
+
def gen_constructor(src_set, term_id, dest_set)
|
65
|
+
return if native?
|
66
|
+
type = src_set.type(@type_str)
|
67
|
+
dest_set << L.function(low_constructor_str, type.low_type_str) do |f|
|
68
|
+
@arg_type_strs.each_with_index.map do |t_str, mem_idx|
|
69
|
+
f.append_param(src_set.type(t_str).low_type_str, "member#{mem_idx}")
|
70
|
+
end
|
71
|
+
if type.static?
|
72
|
+
f << L.stmt("#{type.low_type_str} x")
|
73
|
+
else
|
74
|
+
f << L.stmt("#{type.low_type_str} x = #{type.low_allocator_str}(0)")
|
75
|
+
end
|
76
|
+
if type.has_meta_in_struct?
|
77
|
+
f << L.stmt("#{type.meta_access_str('x')}.term_id = #{term_id}")
|
78
|
+
end
|
79
|
+
@arg_type_strs.size.times do |mem_idx|
|
80
|
+
terms = type.terms_access_str('x')
|
81
|
+
m = "member#{mem_idx}"
|
82
|
+
f << L.stmt("#{terms}.term#{term_id}.#{m} = #{m}")
|
83
|
+
end
|
84
|
+
f << L.stmt('return x')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# return low-expression to make a new instance by this vconst
|
89
|
+
def low_constructor_call_exp(low_arg_exps)
|
90
|
+
return @native_str if native?
|
91
|
+
"#{low_constructor_str}(#{low_arg_exps.join(', ')})"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Return conditional-low-exps to match this vconst and receiver-exp.
|
95
|
+
def low_compare_exps(set, receiver_exp)
|
96
|
+
type = set.type(@type_str)
|
97
|
+
return [] if type.single_vconst?
|
98
|
+
return ["#{receiver_exp} == #{@native_str}"] if native?
|
99
|
+
meta = type.meta_access_str(receiver_exp)
|
100
|
+
term_id = type.term_id(@str)
|
101
|
+
["#{meta}.term_id == #{term_id}"]
|
102
|
+
end
|
103
|
+
|
104
|
+
# name of constructor-function in C for this vconst
|
105
|
+
def low_constructor_str
|
106
|
+
'VC_' + @str
|
107
|
+
end
|
108
|
+
|
109
|
+
# Return alias of the constructor of this vconst.
|
110
|
+
def low_macro_for_alias(alias_str)
|
111
|
+
arg = ('a'..'z').take(@arg_type_strs.size).join(', ')
|
112
|
+
L.macro("#{alias_str}(#{arg}) #{low_constructor_str}(#{arg})")
|
113
|
+
end
|
114
|
+
|
115
|
+
# Return low-exp to mark elements of this vconst.
|
116
|
+
def low_mark_element_exps(set, term_id, receiver_str)
|
117
|
+
types = @arg_type_strs.map { |t_str| set.type(t_str) }
|
118
|
+
types_needing_mark = types.select { |t| t.need_mark?(set) }
|
119
|
+
types_needing_mark.each_with_index.map do |type, mem_idx|
|
120
|
+
term_access = "#{type.terms_access_str(receiver_str)}.term#{term_id}"
|
121
|
+
"#{type.low_mark_func_str}(#{term_access}.member#{mem_idx})"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def low_member_pointers(type, receiver_str)
|
126
|
+
term_id = type.term_id(@str)
|
127
|
+
terms_access = "#{type.terms_access_str(receiver_str)}.term#{term_id}"
|
128
|
+
@arg_type_strs.each_with_index.map do |_, mem_idx|
|
129
|
+
"&#{terms_access}.member#{mem_idx}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'sfrp/file'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module SFRP
|
5
|
+
module Output
|
6
|
+
class Set
|
7
|
+
attr_reader :virtual_files
|
8
|
+
|
9
|
+
def initialize(&block)
|
10
|
+
@virtual_files = []
|
11
|
+
block.call(self) if block
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate!(output_dir_path, other_virtual_files = [])
|
15
|
+
unless File.directory?(output_dir_path)
|
16
|
+
FileUtils.mkdir_p(output_dir_path)
|
17
|
+
end
|
18
|
+
FileUtils.cd(output_dir_path) do
|
19
|
+
(@virtual_files + other_virtual_files).each do |vf|
|
20
|
+
relative_path = vf.fmodule_uri.gsub('.', '/') + '.' + vf.file_ext
|
21
|
+
dirname = File.dirname(relative_path)
|
22
|
+
FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
|
23
|
+
File.open(relative_path, 'w') { |f| f.write(vf.content) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_file(relative_position, file_ext, content)
|
29
|
+
@virtual_files << VirtualFile.new(relative_position, file_ext, content)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Poly
|
3
|
+
module DSL
|
4
|
+
extend SFRP::P = self
|
5
|
+
|
6
|
+
def tconst(tconst_str, var_strs, static, native_str, infinite, &block)
|
7
|
+
tp = TConstProxy.new(tconst_str, var_strs, infinite)
|
8
|
+
block.call(tp) if block
|
9
|
+
argc = var_strs.size
|
10
|
+
TConst.new(tconst_str, argc, tp.vconst_strs, static, native_str)
|
11
|
+
end
|
12
|
+
|
13
|
+
def func(func_str, ret_type_annot = nil, &block)
|
14
|
+
fp = FuncProxy.new(func_str, ret_type_annot)
|
15
|
+
block.call(fp) if block
|
16
|
+
fp.to_func
|
17
|
+
end
|
18
|
+
|
19
|
+
def node(node_str, type_annot = nil, &block)
|
20
|
+
np = NodeProxy.new(node_str, type_annot)
|
21
|
+
block.call(np) if block
|
22
|
+
np.to_node
|
23
|
+
end
|
24
|
+
|
25
|
+
def t(tconst_str, *args)
|
26
|
+
TypeAnnotationType.new(tconst_str, args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def tv(var_str)
|
30
|
+
TypeAnnotationVar.new(var_str)
|
31
|
+
end
|
32
|
+
|
33
|
+
def match_e(left_exp, &block)
|
34
|
+
cp = CaseProxy.new
|
35
|
+
block.call(cp) if block
|
36
|
+
MatchExp.new(left_exp, cp.to_a)
|
37
|
+
end
|
38
|
+
|
39
|
+
def call_e(func_str, *arg_exps)
|
40
|
+
FuncCallExp.new(func_str, arg_exps)
|
41
|
+
end
|
42
|
+
|
43
|
+
def vc_call_e(vconst_str, *arg_exps)
|
44
|
+
VConstCallExp.new(vconst_str, arg_exps)
|
45
|
+
end
|
46
|
+
|
47
|
+
def v_e(var_str)
|
48
|
+
VarRefExp.new(var_str)
|
49
|
+
end
|
50
|
+
|
51
|
+
def pat(vconst_str, *arg_patterns)
|
52
|
+
Pattern.new(vconst_str, nil, arg_patterns)
|
53
|
+
end
|
54
|
+
|
55
|
+
def pref(vconst_str, ref_var_str, *arg_patterns)
|
56
|
+
Pattern.new(vconst_str, ref_var_str, arg_patterns)
|
57
|
+
end
|
58
|
+
|
59
|
+
def pany(ref_var_str = nil)
|
60
|
+
Pattern.new(nil, ref_var_str, [])
|
61
|
+
end
|
62
|
+
|
63
|
+
class TConstProxy
|
64
|
+
def initialize(tconst_str, var_strs, infinite)
|
65
|
+
args = var_strs.map { |v| TypeAnnotationVar.new(v) }
|
66
|
+
@ret_type_annot = TypeAnnotationType.new(tconst_str, args)
|
67
|
+
@var_strs = var_strs
|
68
|
+
@infinite = infinite
|
69
|
+
@vconst_strs = []
|
70
|
+
end
|
71
|
+
|
72
|
+
def vconst(vconst_str, arg_type_annots, native_str = nil)
|
73
|
+
ftype_annot = FuncTypeAnnotation.new(@ret_type_annot, arg_type_annots)
|
74
|
+
@vconst_strs << vconst_str
|
75
|
+
VConst.new(vconst_str, @var_strs, ftype_annot, native_str)
|
76
|
+
end
|
77
|
+
|
78
|
+
def vconst_strs
|
79
|
+
@infinite ? nil : @vconst_strs
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class FuncProxy
|
84
|
+
def initialize(func_str, ret_type_annot = nil)
|
85
|
+
@func_str = func_str
|
86
|
+
@ret_type_annot = ret_type_annot || DSL.tv('%a0')
|
87
|
+
@param_strs = []
|
88
|
+
@type_annots = []
|
89
|
+
end
|
90
|
+
|
91
|
+
def param(param_str, type_annot = nil)
|
92
|
+
@param_strs << param_str
|
93
|
+
@type_annots << (type_annot || DSL.tv('%a' + @param_strs.size.to_s))
|
94
|
+
end
|
95
|
+
|
96
|
+
def ffi_str(str)
|
97
|
+
@ffi_str = str
|
98
|
+
end
|
99
|
+
|
100
|
+
def exp(&block)
|
101
|
+
@exp = block.call
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_func
|
105
|
+
ftype_annot = FuncTypeAnnotation.new(@ret_type_annot, @type_annots)
|
106
|
+
Function.new(@func_str, @param_strs, ftype_annot, @exp, @ffi_str)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class NodeProxy
|
111
|
+
def initialize(node_str, type_annot)
|
112
|
+
@node_str = node_str
|
113
|
+
@type_annot = type_annot || TypeAnnotationVar.new('%a0')
|
114
|
+
@node_refs = []
|
115
|
+
@type_annots = []
|
116
|
+
end
|
117
|
+
|
118
|
+
def c(node_str)
|
119
|
+
dep(node_str, false)
|
120
|
+
end
|
121
|
+
|
122
|
+
def l(node_str)
|
123
|
+
dep(node_str, true)
|
124
|
+
end
|
125
|
+
|
126
|
+
def dep(node_str, last)
|
127
|
+
@node_refs << Node::NodeRef.new(node_str, last)
|
128
|
+
@type_annots << TypeAnnotationVar.new('%a' + @node_refs.size.to_s)
|
129
|
+
end
|
130
|
+
|
131
|
+
def eval_func(func_str, ret_type_annot = nil, &block)
|
132
|
+
@eval_func_str = func_str
|
133
|
+
DSL.func(func_str, ret_type_annot, &block)
|
134
|
+
end
|
135
|
+
|
136
|
+
def init_func(func_str, ret_type_annot = nil, &block)
|
137
|
+
@init_func_str = func_str
|
138
|
+
DSL.func(func_str, ret_type_annot, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
def eval_func_str(func_str)
|
142
|
+
@eval_func_str = func_str
|
143
|
+
end
|
144
|
+
|
145
|
+
def init_func_str(func_str)
|
146
|
+
@init_func_str = func_str
|
147
|
+
end
|
148
|
+
|
149
|
+
def to_node
|
150
|
+
a = @node_refs.size.times.map { |i| TypeAnnotationVar.new("a#{i}") }
|
151
|
+
annot = FuncTypeAnnotation.new(@type_annot, a)
|
152
|
+
Node.new(@node_str, @node_refs, annot, @eval_func_str, @init_func_str)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
class CaseProxy
|
157
|
+
def initialize
|
158
|
+
@cases = []
|
159
|
+
end
|
160
|
+
|
161
|
+
def case(pattern, &exp_block)
|
162
|
+
@cases << MatchExp::Case.new(pattern, exp_block.call)
|
163
|
+
end
|
164
|
+
|
165
|
+
def to_a
|
166
|
+
@cases
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Poly
|
3
|
+
class Function
|
4
|
+
attr_reader :str
|
5
|
+
|
6
|
+
def initialize(str, param_strs, ftype_annot, exp = nil, ffi_str = nil)
|
7
|
+
raise ArgumentError if exp.nil? && ffi_str.nil?
|
8
|
+
@str = str
|
9
|
+
@param_strs = param_strs
|
10
|
+
@ftype_annot = ftype_annot
|
11
|
+
@exp = exp
|
12
|
+
@ffi_str = ffi_str
|
13
|
+
end
|
14
|
+
|
15
|
+
def ftyping(set)
|
16
|
+
@ftyping ||= @ftype_annot.to_ftyping.instance do |ft|
|
17
|
+
var_env = {}
|
18
|
+
@param_strs.zip(ft.params) { |str, typing| var_env[str] = typing }
|
19
|
+
ft.body.unify(@exp.typing(set, var_env)) if @exp
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def clone
|
24
|
+
exp = (@exp ? @exp.clone : nil)
|
25
|
+
Function.new(@str, @param_strs, @ftype_annot, exp, @ffi_str)
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_recursion(set, path = [])
|
29
|
+
return if @exp == nil
|
30
|
+
if path.include?(@str)
|
31
|
+
raise RecursiveError.new(path.drop_while { |s| s != @str })
|
32
|
+
end
|
33
|
+
@exp.called_func_strs.each do |str|
|
34
|
+
set.func(str).check_recursion(set, path + [@str])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_mono(monofier, mono_func_str)
|
39
|
+
raise UndeterminableTypeError.new(@str, @ftyping) unless @ftyping.mono?
|
40
|
+
mono_type_str = monofier.use_type(@ftyping.body)
|
41
|
+
M.func(mono_type_str, mono_func_str) do |f|
|
42
|
+
@param_strs.zip(@ftyping.params) do |str, typing|
|
43
|
+
f.param(monofier.use_type(typing), str)
|
44
|
+
end
|
45
|
+
f.exp { @exp.to_mono(monofier) } if @exp
|
46
|
+
f.ffi_str(@ffi_str) if @ffi_str
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Node
|
52
|
+
attr_reader :str
|
53
|
+
|
54
|
+
NodeRef = Struct.new(:node_str, :last)
|
55
|
+
|
56
|
+
def initialize(
|
57
|
+
str, node_refs, ftype_annot, eval_func_str, init_func_str = nil
|
58
|
+
)
|
59
|
+
@str = str
|
60
|
+
@node_refs = node_refs
|
61
|
+
@ftype_annot = ftype_annot
|
62
|
+
@eval_func_str = eval_func_str
|
63
|
+
@init_func_str = init_func_str
|
64
|
+
end
|
65
|
+
|
66
|
+
def typing(set)
|
67
|
+
return @typing if @typing
|
68
|
+
@typing = Typing.new
|
69
|
+
@ftyping = set.func(@eval_func_str).ftyping(set).instance do |eval_ft|
|
70
|
+
@node_refs.zip(eval_ft.params) do |node_ref, typing|
|
71
|
+
set.node(node_ref.node_str).typing(set).unify(typing)
|
72
|
+
end
|
73
|
+
next unless @init_func_str
|
74
|
+
@init_ftyping = set.func(@init_func_str).ftyping(set).instance do |ft|
|
75
|
+
raise unless ft.params.empty?
|
76
|
+
ft.body.unify(eval_ft.body)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
@ftyping.unify(@ftype_annot.to_ftyping).body.unify(@typing)
|
80
|
+
end
|
81
|
+
|
82
|
+
def check_recursion(set, path = [])
|
83
|
+
if path.include?(@str)
|
84
|
+
raise RecursiveError.new(path.drop_while { |s| s != @str })
|
85
|
+
end
|
86
|
+
@node_refs.each do |nr|
|
87
|
+
next if nr.last
|
88
|
+
set.node(nr.node_str).check_recursion(set, path + [@str])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_mono(monofier)
|
93
|
+
raise UndeterminableTypeError.new(@str, @typing) unless @typing.mono?
|
94
|
+
type_str = monofier.use_type(@typing)
|
95
|
+
node_str = monofier.use_node(@str)
|
96
|
+
eval_func_str = monofier.use_func(@eval_func_str, @ftyping)
|
97
|
+
if @init_func_str
|
98
|
+
init_func_str = monofier.use_func(@init_func_str, @init_ftyping)
|
99
|
+
else
|
100
|
+
init_func_str = nil
|
101
|
+
end
|
102
|
+
M.node(type_str, node_str, eval_func_str, init_func_str) do |n|
|
103
|
+
@node_refs.each do |node_ref|
|
104
|
+
node_str = monofier.use_node(node_ref.node_str)
|
105
|
+
node_ref.last ? n.l(node_str) : n.c(node_str)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class TConst
|
112
|
+
attr_reader :str
|
113
|
+
|
114
|
+
def initialize(
|
115
|
+
str, paramc, vconst_strs = nil, static = false, native_str = nil
|
116
|
+
)
|
117
|
+
@str = str
|
118
|
+
@paramc = paramc
|
119
|
+
@vconst_strs = vconst_strs
|
120
|
+
@static = static
|
121
|
+
@native_str = native_str
|
122
|
+
end
|
123
|
+
|
124
|
+
def typing
|
125
|
+
@typing ||= Typing.new(@str, Array.new(@paramc) { Typing.new })
|
126
|
+
end
|
127
|
+
|
128
|
+
def clone
|
129
|
+
TConst.new(@str, @paramc, @vconst_strs, @static, @native_str)
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_mono(monofier)
|
133
|
+
raise UndeterminableTypeError.new(@str, @typing) unless @typing.mono?
|
134
|
+
type_str = monofier.use_type(@typing)
|
135
|
+
return M.type(type_str, nil, @static, @native_str) unless @vconst_strs
|
136
|
+
vconst_strs = @vconst_strs.map { |s| monofier.use_vconst(s, @typing) }
|
137
|
+
M.type(type_str, vconst_strs, @static, @native_str)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class VConst
|
142
|
+
attr_reader :str
|
143
|
+
|
144
|
+
def initialize(str, annot_vars, ftype_annot, native_str = nil)
|
145
|
+
@str = str
|
146
|
+
@annot_vars = annot_vars
|
147
|
+
@ftype_annot = ftype_annot
|
148
|
+
@native_str = native_str
|
149
|
+
end
|
150
|
+
|
151
|
+
def ftyping
|
152
|
+
@ftyping ||= @ftype_annot.to_ftyping(@annot_vars)
|
153
|
+
end
|
154
|
+
|
155
|
+
def clone
|
156
|
+
VConst.new(@str, @annot_vars, @ftype_annot, @native_str)
|
157
|
+
end
|
158
|
+
|
159
|
+
def to_mono(monofier)
|
160
|
+
raise UndeterminableTypeError.new(@str, @ftyping) unless @ftyping.mono?
|
161
|
+
type_str = monofier.use_type(@ftyping.body)
|
162
|
+
vconst_str = monofier.use_vconst(@str, @ftyping.body)
|
163
|
+
arg_type_strs = @ftyping.params.map { |t| monofier.use_type(t) }
|
164
|
+
M.vconst(type_str, vconst_str, arg_type_strs, @native_str)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|