sfrp 1.1.0
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.
- 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
data/lib/sfrp/raw/dsl.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Raw
|
3
|
+
extend SFRP::R = self
|
4
|
+
|
5
|
+
def r(rname, qualifier = nil)
|
6
|
+
Ref.new(rname, qualifier)
|
7
|
+
end
|
8
|
+
|
9
|
+
def t(tconst_ref, args, sp = nil)
|
10
|
+
TypeAnnotationType.new(tconst_ref, args, sp)
|
11
|
+
end
|
12
|
+
|
13
|
+
def tv(var_str, sp = nil)
|
14
|
+
TypeAnnotationVar.new(var_str, sp)
|
15
|
+
end
|
16
|
+
|
17
|
+
def ft(ret_t, arg_ts)
|
18
|
+
FuncTypeAnnotation.new(ret_t, arg_ts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def v_e(var_str, sp = nil)
|
22
|
+
VarRefExp.new(var_str, sp)
|
23
|
+
end
|
24
|
+
|
25
|
+
def nr_e(node_ref, last, sp = nil)
|
26
|
+
NodeRefExp.new(node_ref, last, sp)
|
27
|
+
end
|
28
|
+
|
29
|
+
def call_e(func_ref, args, sp = nil)
|
30
|
+
FuncCallExp.new(func_ref, args, sp)
|
31
|
+
end
|
32
|
+
|
33
|
+
def vc_call_e(vconst_ref, args, sp = nil)
|
34
|
+
VConstCallExp.new(vconst_ref, args, sp)
|
35
|
+
end
|
36
|
+
|
37
|
+
def seq_e(exps, func_refs, sp = nil)
|
38
|
+
SequenceExp.new(exps, func_refs, sp)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Raw
|
3
|
+
class Function < Struct.new(:rname, :ns, :ret_ta, :pstrs, :ptas, :exp, :ffi_str, :effect, :sp)
|
4
|
+
def absolute_name
|
5
|
+
ns.absolute_name(rname)
|
6
|
+
end
|
7
|
+
|
8
|
+
def vconst_refs
|
9
|
+
exp ? exp.vconst_refs : []
|
10
|
+
end
|
11
|
+
|
12
|
+
def gen_flat(src_set, dest_set)
|
13
|
+
exp.blame_side_effect if exp && !effect
|
14
|
+
flat_exp = exp && exp.to_flat(src_set, ns)
|
15
|
+
flat_ret_ta = ret_ta && ret_ta.to_flat(src_set, ns)
|
16
|
+
flat_ptas = ptas.map { |ta| ta && ta.to_flat(src_set, ns) }
|
17
|
+
dest_set << Flat::Function.new(
|
18
|
+
absolute_name, flat_ret_ta, pstrs, flat_ptas, flat_exp, ffi_str, sp
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class TConst < Struct.new(:rname, :ns, :pstrs, :vconsts, :native_str, :static, :sp)
|
24
|
+
def absolute_name
|
25
|
+
ns.absolute_name(rname)
|
26
|
+
end
|
27
|
+
|
28
|
+
def gen_flat(_src_set, dest_set)
|
29
|
+
vconst_strs = vconsts.map(&:absolute_name)
|
30
|
+
dest_set << Flat::TConst.new(absolute_name, pstrs, vconst_strs, native_str, static, sp)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class VConst < Struct.new(:rname, :tconst_rname, :ns, :native_str, :param_tas, :sp)
|
35
|
+
def absolute_name
|
36
|
+
ns.absolute_name(rname)
|
37
|
+
end
|
38
|
+
|
39
|
+
def gen_flat(src_set, dest_set)
|
40
|
+
tconst_str = src_set.tconst(ns, Ref.new(tconst_rname), sp).absolute_name
|
41
|
+
flat_param_tas = param_tas.map { |ta| ta.to_flat(src_set, ns) }
|
42
|
+
dest_set << Flat::VConst.new(absolute_name, tconst_str, native_str, flat_param_tas, sp)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class PrimTConst < Struct.new(:rname, :ns, :native_str, :pat, :rep, :sp)
|
47
|
+
def absolute_name
|
48
|
+
ns.absolute_name(rname)
|
49
|
+
end
|
50
|
+
|
51
|
+
def vconst_match?(vconst_str)
|
52
|
+
pat.match(vconst_str)
|
53
|
+
end
|
54
|
+
|
55
|
+
def make_vconst(vconst_str)
|
56
|
+
raise vconst_str unless vconst_match?(vconst_str)
|
57
|
+
VConst.new(vconst_str, rname, ns, vconst_str.gsub(pat, rep), [], sp)
|
58
|
+
end
|
59
|
+
|
60
|
+
def gen_flat(_src_set, dest_set)
|
61
|
+
dest_set << Flat::TConst.new(absolute_name, [], nil, native_str, true, sp)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Init < Struct.new(:ns, :func_ref, :arg_exps, :line_number)
|
66
|
+
def func_rname
|
67
|
+
"%init#{line_number}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def function
|
71
|
+
exp = FuncCallExp.new(func_ref, arg_exps, true)
|
72
|
+
Function.new(func_rname, ns, nil, [], [], exp, nil, true)
|
73
|
+
end
|
74
|
+
|
75
|
+
def gen_flat(src_set, dest_set)
|
76
|
+
function.gen_flat(src_set, dest_set)
|
77
|
+
dest_set.append_init_func_str(function.absolute_name)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Node < Struct.new(:rname, :ns, :ta, :exp, :init_exp, :sp)
|
82
|
+
def absolute_name
|
83
|
+
ns.absolute_name(rname)
|
84
|
+
end
|
85
|
+
|
86
|
+
def vconst_refs
|
87
|
+
[exp, init_exp].reject(&:nil?).flat_map(&:vconst_refs)
|
88
|
+
end
|
89
|
+
|
90
|
+
def gen_flat(src_set, dest_set)
|
91
|
+
exp.blame_side_effect
|
92
|
+
flat_ta = ta && ta.to_flat(src_set, ns)
|
93
|
+
flat_init_exp = init_exp && init_exp.to_flat(src_set, ns)
|
94
|
+
flat_exp = exp && exp.to_flat(src_set, ns)
|
95
|
+
dest_set << Flat::Node.new(absolute_name, flat_ta, flat_exp, flat_init_exp, sp)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class Output < Struct.new(:ns, :exps, :func_ref, :line_number, :sp)
|
100
|
+
def rname
|
101
|
+
"%output_line#{line_number}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def absolute_name
|
105
|
+
ns.absolute_name(rname)
|
106
|
+
end
|
107
|
+
|
108
|
+
def convert
|
109
|
+
exp = FuncCallExp.new(func_ref, exps, false, sp)
|
110
|
+
ta = TypeAnnotationType.new(Ref.new('Unit'), [])
|
111
|
+
Node.new(rname, ns, ta, exp, nil, sp)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class Input < Struct.new(:rname, :ns, :ta, :arg_exps, :init_exp, :func_ref, :sp)
|
116
|
+
def convert
|
117
|
+
exp = FuncCallExp.new(func_ref, arg_exps, false, sp)
|
118
|
+
Node.new(rname, ns, ta, exp, init_exp, sp)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class Infix < Struct.new(:ns, :func_ref, :priority, :direction, :sp)
|
123
|
+
LEFT, RIGHT, NONE = :left, :right, :none
|
124
|
+
|
125
|
+
def absolute_func_name(set)
|
126
|
+
func_name = set.func(ns, func_ref, sp).absolute_name
|
127
|
+
raise NameError.new(func_ref.to_s, sp) unless func_name
|
128
|
+
func_name
|
129
|
+
end
|
130
|
+
|
131
|
+
def absolute_priority(position)
|
132
|
+
case direction
|
133
|
+
when LEFT
|
134
|
+
[priority, 1000 - position]
|
135
|
+
when RIGHT
|
136
|
+
[priority, position]
|
137
|
+
when NONE
|
138
|
+
[priority, 0]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class FuncTypeAnnotation < Struct.new(:ret_ta, :arg_tas, :sp)
|
144
|
+
def to_flat(set, ns)
|
145
|
+
flat_arg_tas = arg_tas.map { |ta| ta.to_flat(set, ns) }
|
146
|
+
Flat::FuncTypeAnnotation.new(ret_ta.to_flat(set, ns), flat_arg_tas, sp)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class TypeAnnotationType < Struct.new(:tconst_ref, :arg_tas, :sp)
|
151
|
+
def to_flat(set, ns)
|
152
|
+
ab_tc_name = set.tconst(ns, tconst_ref, sp).absolute_name
|
153
|
+
flat_arg_tas = arg_tas.map { |ta| ta.to_flat(set, ns) }
|
154
|
+
Flat::TypeAnnotationType.new(ab_tc_name, flat_arg_tas, sp)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
class TypeAnnotationVar < Struct.new(:var_str, :sp)
|
159
|
+
def to_flat(_set, _ns)
|
160
|
+
Flat::TypeAnnotationVar.new(var_str, sp)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'sfrp/error'
|
2
|
+
|
3
|
+
module SFRP
|
4
|
+
module Raw
|
5
|
+
class NameError < CompileError
|
6
|
+
def initialize(target_str, source_position)
|
7
|
+
@target_str = target_str
|
8
|
+
@source_position = source_position
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
"Cannot resolve '#{@target_str}'"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class AmbiguousNameError < CompileError
|
17
|
+
def initialize(target_str, selection_strs, source_position)
|
18
|
+
@target_str = target_str
|
19
|
+
@selection_strs = selection_strs
|
20
|
+
@source_position = source_position
|
21
|
+
end
|
22
|
+
|
23
|
+
def message
|
24
|
+
"Ambiguous name '#{@target_str}':\n" +
|
25
|
+
@selection_strs.map { |s| ' ' + s }.join("\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class IllegalSideEffectError < CompileError
|
30
|
+
def initialize(target_str, source_position)
|
31
|
+
@target_str = target_str
|
32
|
+
@source_position = source_position
|
33
|
+
end
|
34
|
+
|
35
|
+
def message
|
36
|
+
"Don't call side-effect function '#{@target_str}'"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Raw
|
3
|
+
class FuncCallExp < Struct.new(:func_ref, :arg_exps, :effect, :sp)
|
4
|
+
def vconst_refs
|
5
|
+
arg_exps.flat_map(&:vconst_refs)
|
6
|
+
end
|
7
|
+
|
8
|
+
def blame_side_effect
|
9
|
+
raise IllegalSideEffectError.new(func_ref.to_s, sp) if effect
|
10
|
+
arg_exps.each(&:blame_side_effect)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_flat(set, ns)
|
14
|
+
ab_func_name = set.func(ns, func_ref, sp).absolute_name
|
15
|
+
args = arg_exps.map { |e| e.to_flat(set, ns) }
|
16
|
+
Flat::FuncCallExp.new(ab_func_name, args, sp)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class VConstCallExp < Struct.new(:vconst_ref, :arg_exps, :sp)
|
21
|
+
def vconst_refs
|
22
|
+
[vconst_ref, *arg_exps.flat_map(&:vconst_refs)]
|
23
|
+
end
|
24
|
+
|
25
|
+
def blame_side_effect
|
26
|
+
arg_exps.each(&:blame_side_effect)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_flat(set, ns)
|
30
|
+
ab_vc_name = set.vconst(ns, vconst_ref, sp).absolute_name
|
31
|
+
args = arg_exps.map { |e| e.to_flat(set, ns) }
|
32
|
+
Flat::VConstCallExp.new(ab_vc_name, args, sp)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class NodeRefExp < Struct.new(:node_ref, :last, :sp)
|
37
|
+
def vconst_refs
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
|
41
|
+
def blame_side_effect
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_flat(set, ns)
|
46
|
+
ab_node_name = set.node(ns, node_ref, sp).absolute_name
|
47
|
+
Flat::NodeRefExp.new(ab_node_name, last)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class MatchExp < Struct.new(:left_exp, :cases, :sp)
|
52
|
+
Case = Struct.new(:pattern, :exp)
|
53
|
+
|
54
|
+
class Pattern < Struct.new(:vconst_ref, :ref_var_str, :args, :sp)
|
55
|
+
def vconst_refs
|
56
|
+
(vconst_ref ? [vconst_ref] : []) + args.flat_map(&:vconst_refs)
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_flat(set, ns)
|
60
|
+
flat_args = args.map { |a| a.to_flat(set, ns) }
|
61
|
+
if vconst_ref
|
62
|
+
ab_vc_name = set.vconst(ns, vconst_ref, sp).absolute_name
|
63
|
+
Flat::MatchExp::Pattern.new(ab_vc_name, ref_var_str, flat_args, sp)
|
64
|
+
else
|
65
|
+
Flat::MatchExp::Pattern.new(nil, ref_var_str, flat_args, sp)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def vconst_refs
|
71
|
+
[left_exp, *cases.map(&:pattern), *cases.map(&:exp)].flat_map(&:vconst_refs)
|
72
|
+
end
|
73
|
+
|
74
|
+
def blame_side_effect
|
75
|
+
left_exp.blame_side_effect
|
76
|
+
cases.map(&:exp).each(&:blame_side_effect)
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_flat(set, ns)
|
80
|
+
flat_cases = cases.map do |c|
|
81
|
+
flat_pattern = c.pattern.to_flat(set, ns)
|
82
|
+
Flat::MatchExp::Case.new(flat_pattern, c.exp.to_flat(set, ns))
|
83
|
+
end
|
84
|
+
Flat::MatchExp.new(left_exp.to_flat(set, ns), flat_cases, sp)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class VarRefExp < Struct.new(:var_str, :sp)
|
89
|
+
def vconst_refs
|
90
|
+
[]
|
91
|
+
end
|
92
|
+
|
93
|
+
def blame_side_effect
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_flat(_set, _ns)
|
98
|
+
Flat::VarRefExp.new(var_str, sp)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class SequenceExp < Struct.new(:exps, :func_refs, :sp)
|
103
|
+
def vconst_refs
|
104
|
+
exps.flat_map(&:vconst_refs)
|
105
|
+
end
|
106
|
+
|
107
|
+
def blame_side_effect
|
108
|
+
exps.each { |e| e.blame_side_effect }
|
109
|
+
end
|
110
|
+
|
111
|
+
def convert(set, ns)
|
112
|
+
return exps[0] if exps.size == 1
|
113
|
+
pos = set.weakest_op_position(ns, func_refs, sp)
|
114
|
+
lseq = SequenceExp.new(exps.take(pos + 1), func_refs.take(pos), sp)
|
115
|
+
rseq = SequenceExp.new(exps.drop(pos + 1), func_refs.drop(pos + 1), sp)
|
116
|
+
args = [lseq.convert(set, ns), rseq.convert(set, ns)]
|
117
|
+
FuncCallExp.new(func_refs[pos], args, false, sp)
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_flat(set, ns)
|
121
|
+
convert(set, ns).to_flat(set, ns)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
module SugarExp
|
126
|
+
def vconst_refs
|
127
|
+
convert.vconst_refs
|
128
|
+
end
|
129
|
+
|
130
|
+
def blame_side_effect
|
131
|
+
convert.blame_side_effect
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_flat(set, ns)
|
135
|
+
convert.to_flat(set, ns)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class IfExp < Struct.new(:cond_exp, :then_exp, :else_exp, :sp)
|
140
|
+
include SugarExp
|
141
|
+
|
142
|
+
def convert
|
143
|
+
cases = [
|
144
|
+
MatchExp::Case.new(
|
145
|
+
MatchExp::Pattern.new(Ref.new('True'), nil, [], sp), then_exp
|
146
|
+
),
|
147
|
+
MatchExp::Case.new(
|
148
|
+
MatchExp::Pattern.new(Ref.new('False'), nil, [], sp), else_exp
|
149
|
+
)
|
150
|
+
]
|
151
|
+
MatchExp.new(cond_exp, cases, sp)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class LetExp < Struct.new(:exp, :assignments, :sp)
|
156
|
+
include SugarExp
|
157
|
+
|
158
|
+
Assignment = Struct.new(:pattern, :exp)
|
159
|
+
|
160
|
+
def convert
|
161
|
+
raise if assignments.empty?
|
162
|
+
assignments.reverse.reduce(exp) do |e, ass|
|
163
|
+
MatchExp.new(ass.exp, [MatchExp::Case.new(ass.pattern, e)], sp)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SFRP
|
2
|
+
module Raw
|
3
|
+
class Ref < Struct.new(:relative_name, :qualifier_name, :sp)
|
4
|
+
def to_s
|
5
|
+
return relative_name if qualifier_name.nil?
|
6
|
+
qualifier_name + '.' + relative_name
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Import < Struct.new(:absolute_namespace_name, :qualifier_name)
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class Namespace
|
15
|
+
def initialize(absolute_namespace_name, imports)
|
16
|
+
@absolute_namespace_name = absolute_namespace_name
|
17
|
+
@imports = [Import.new(absolute_namespace_name, nil), *imports]
|
18
|
+
end
|
19
|
+
|
20
|
+
def absolute_name(relative_name)
|
21
|
+
@absolute_namespace_name + '.' + relative_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def search_for_absolute_names(ref)
|
25
|
+
@imports.select { |i| i.qualifier_name == ref.qualifier_name }
|
26
|
+
.map { |i| i.absolute_namespace_name + '.' + ref.relative_name }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|