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
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
|