highway 0.0.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/highway.rb +8 -4
- data/lib/highway/compiler/analyze/analyzer.rb +249 -0
- data/lib/highway/compiler/analyze/tree/root.rb +95 -0
- data/lib/highway/compiler/analyze/tree/segments/text.rb +36 -0
- data/lib/highway/compiler/analyze/tree/segments/variable.rb +43 -0
- data/lib/highway/compiler/analyze/tree/stage.rb +48 -0
- data/lib/highway/compiler/analyze/tree/step.rb +69 -0
- data/lib/highway/compiler/analyze/tree/values/array.rb +45 -0
- data/lib/highway/compiler/analyze/tree/values/base.rb +67 -0
- data/lib/highway/compiler/analyze/tree/values/hash.rb +45 -0
- data/lib/highway/compiler/analyze/tree/values/primitive.rb +43 -0
- data/lib/highway/compiler/analyze/tree/variable.rb +48 -0
- data/lib/highway/compiler/build/builder.rb +154 -0
- data/lib/highway/compiler/build/output/invocation.rb +70 -0
- data/lib/highway/compiler/build/output/manifest.rb +52 -0
- data/lib/highway/compiler/parse/parser.rb +92 -0
- data/lib/highway/compiler/parse/tree/root.rb +73 -0
- data/lib/highway/compiler/parse/tree/step.rb +62 -0
- data/lib/highway/compiler/parse/tree/variable.rb +48 -0
- data/lib/highway/compiler/parse/versions/v1.rb +110 -0
- data/lib/highway/compiler/suite.rb +56 -0
- data/lib/highway/environment.rb +282 -0
- data/lib/highway/fastlane/action.rb +67 -0
- data/lib/highway/interface.rb +135 -0
- data/lib/highway/main.rb +173 -0
- data/lib/highway/runtime/context.rb +229 -0
- data/lib/highway/runtime/report.rb +80 -0
- data/lib/highway/runtime/runner.rb +286 -0
- data/lib/highway/steps/infrastructure.rb +20 -0
- data/lib/highway/steps/library/action.rb +42 -0
- data/lib/highway/steps/library/appcenter.rb +106 -0
- data/lib/highway/steps/library/appstore.rb +137 -0
- data/lib/highway/steps/library/carthage.rb +67 -0
- data/lib/highway/steps/library/cocoapods.rb +76 -0
- data/lib/highway/steps/library/copy_artifacts.rb +36 -0
- data/lib/highway/steps/library/lane.rb +42 -0
- data/lib/highway/steps/library/sh.rb +36 -0
- data/lib/highway/steps/library/slack.rb +381 -0
- data/lib/highway/steps/library/testflight.rb +105 -0
- data/lib/highway/steps/library/xcode_archive.rb +162 -0
- data/lib/highway/steps/library/xcode_test.rb +264 -0
- data/lib/highway/steps/parameters/base.rb +52 -0
- data/lib/highway/steps/parameters/compound.rb +141 -0
- data/lib/highway/steps/parameters/single.rb +74 -0
- data/lib/highway/steps/registry.rb +92 -0
- data/lib/highway/steps/step.rb +52 -0
- data/lib/highway/steps/types/any.rb +65 -0
- data/lib/highway/steps/types/anyof.rb +64 -0
- data/lib/highway/steps/types/array.rb +44 -0
- data/lib/highway/steps/types/bool.rb +36 -0
- data/lib/highway/steps/types/enum.rb +44 -0
- data/lib/highway/steps/types/hash.rb +45 -0
- data/lib/highway/steps/types/number.rb +38 -0
- data/lib/highway/steps/types/set.rb +39 -0
- data/lib/highway/steps/types/string.rb +47 -0
- data/lib/highway/steps/types/url.rb +35 -0
- data/lib/highway/utilities.rb +51 -0
- data/lib/highway/version.rb +9 -1
- metadata +194 -22
- data/.gitignore +0 -4
- data/Gemfile +0 -4
- data/Rakefile +0 -1
- data/highway.gemspec +0 -24
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e7516548771a99c73bea486d466a28a3019e93729955a359a6cc004d2336b6f
|
4
|
+
data.tar.gz: '083baad25067f0dd1c23194c04fec6ec53e7478a6aca9e79d40661d5e99c9447'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db98b371c18cb00198ff871ee8730373d90544bf880a2ccbccb361f1e9603363e6a48372882f1c966f5e413942841d9a53a6472da204338a04e5ad1a4d51e701
|
7
|
+
data.tar.gz: 37d1df04101159db5b871ef8144f857fd79f1499f8795fb42135dd0f141fefa2c60eceb3d59780c091fc1eea74085fdd1b0ddae8eb26e63b74e849342f9d82a4
|
data/lib/highway.rb
CHANGED
@@ -0,0 +1,249 @@
|
|
1
|
+
#
|
2
|
+
# analyzer.rb
|
3
|
+
# Copyright © 2019 Netguru S.A. All rights reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
require "highway/compiler/analyze/tree/root"
|
7
|
+
require "highway/utilities"
|
8
|
+
|
9
|
+
module Highway
|
10
|
+
module Compiler
|
11
|
+
module Analyze
|
12
|
+
|
13
|
+
# This class is responsible for semantic analysis of a parse tree. This is
|
14
|
+
# the second phase of the compiler.
|
15
|
+
class Analyzer
|
16
|
+
|
17
|
+
public
|
18
|
+
|
19
|
+
# Initialize an instance.
|
20
|
+
#
|
21
|
+
# @param registry [Highway::Steps::Registry] The steps registry.
|
22
|
+
# @param reporter [Highway::Interface] The interface.
|
23
|
+
def initialize(registry:, interface:)
|
24
|
+
@registry = registry
|
25
|
+
@interface = interface
|
26
|
+
end
|
27
|
+
|
28
|
+
# Analyze the parse tree.
|
29
|
+
#
|
30
|
+
# The semantic analyzer validates the parse tree in terms of content,
|
31
|
+
# performs segmentation of values and resolves steps against the
|
32
|
+
# registry.
|
33
|
+
#
|
34
|
+
# The semantic analyzer produces a semantic tree which is then used by
|
35
|
+
# build phase to generate a manifest.
|
36
|
+
#
|
37
|
+
# @param parse_tree [Highway::Compiler::Parse::Tree::Root] The parse tree.
|
38
|
+
#
|
39
|
+
# @return [Highway::Compiler::Analyze::Tree::Root]
|
40
|
+
def analyze(parse_tree:)
|
41
|
+
|
42
|
+
sema_tree = Analyze::Tree::Root.new()
|
43
|
+
|
44
|
+
sema_tree.add_stage(index: 0, name: "bootstrap", policy: :normal, )
|
45
|
+
sema_tree.add_stage(index: 1, name: "test", policy: :normal)
|
46
|
+
sema_tree.add_stage(index: 2, name: "deploy", policy: :normal)
|
47
|
+
sema_tree.add_stage(index: 3, name: "report", policy: :always)
|
48
|
+
|
49
|
+
sema_tree.default_preset = "default"
|
50
|
+
|
51
|
+
validate_preset_names(parse_tree: parse_tree)
|
52
|
+
validate_variable_names(parse_tree: parse_tree)
|
53
|
+
validate_variable_values(parse_tree: parse_tree)
|
54
|
+
validate_step_names(parse_tree: parse_tree)
|
55
|
+
validate_step_parameter_values(parse_tree: parse_tree)
|
56
|
+
|
57
|
+
resolve_variables(parse_tree: parse_tree, sema_tree: sema_tree)
|
58
|
+
resolve_steps(parse_tree: parse_tree, sema_tree: sema_tree)
|
59
|
+
|
60
|
+
validate_variable_references(sema_tree: sema_tree)
|
61
|
+
|
62
|
+
sema_tree
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def validate_preset_names(parse_tree:)
|
69
|
+
parse_tree.variables.each do |variable|
|
70
|
+
assert_preset_name_valid(variable.preset, keypath: ["variables"])
|
71
|
+
end
|
72
|
+
parse_tree.steps.each do |step|
|
73
|
+
assert_preset_name_valid(step.preset, keypath: [step.stage])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def validate_variable_names(parse_tree:)
|
78
|
+
parse_tree.variables.each do |variable|
|
79
|
+
assert_variable_name_valid(variable.name, keypath: ["variables", variable.preset])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_variable_values(parse_tree:)
|
84
|
+
parse_tree.variables.each do |variable|
|
85
|
+
assert_variable_value_valid(variable.value, keypath: ["variables", variable.preset, variable.name])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_step_names(parse_tree:)
|
90
|
+
parse_tree.steps.each do |step|
|
91
|
+
assert_step_exists(step.name, keypath: [step.stage, step.preset])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_step_parameter_values(parse_tree:)
|
96
|
+
parse_tree.steps.each do |step|
|
97
|
+
step.parameters.each_pair do |param_name, param_value|
|
98
|
+
assert_step_parameter_value_valid(param_value, keypath: [step.stage, step.preset, step.name, param_name])
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def validate_variable_references(sema_tree:)
|
104
|
+
sema_tree.variables.each do |variable|
|
105
|
+
variable.value.select_variable_segments_with_scope(:static).each do |segment|
|
106
|
+
unless (ref_variable = find_referenced_variable(sema_tree: sema_tree, name: segment.name, preset: variable.preset))
|
107
|
+
@interface.fatal!("Unknown variable: '#{segment.name}' referenced from: '#{Utilities::keypath_to_s(["variables", variable.preset, variable.name])}'.")
|
108
|
+
end
|
109
|
+
if ref_variable.value.select_variable_segments_with_scope(:static).any? { |other| other.name == variable.name }
|
110
|
+
@interface.fatal!("Detected a reference cycle between: '#{Utilities::keypath_to_s(["variables", variable.preset, variable.name])}' and '#{Utilities::keypath_to_s(["variables", ref_variable.preset, ref_variable.name])}'.")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
sema_tree.steps.each do |step|
|
115
|
+
step.parameters.children.each_pair do |name, value|
|
116
|
+
value.select_variable_segments_with_scope(:static).each do |segment|
|
117
|
+
unless find_referenced_variable(sema_tree: sema_tree, name: segment.name, preset: step.preset)
|
118
|
+
@interface.fatal!("Unknown variable: '#{segment.name}' referenced from: '#{Utilities::keypath_to_s([step.stage, step.preset, step.name, name])}'.")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def resolve_variables(parse_tree:, sema_tree:)
|
126
|
+
parse_tree.variables.each do |variable|
|
127
|
+
value = segmentize_value(variable.value)
|
128
|
+
sema_tree.add_variable(name: variable.name, value: value, preset: variable.preset)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def resolve_steps(parse_tree:, sema_tree:)
|
133
|
+
parse_tree.steps.each do |step|
|
134
|
+
klass = @registry.get_by_name(step.name)
|
135
|
+
parameters = segmentize_value(step.parameters)
|
136
|
+
sema_tree.add_step(index: step.index, name: step.name, step_class: klass, parameters: parameters, stage: step.stage, preset: step.preset)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def segmentize_value(value)
|
141
|
+
if value.is_a?(String)
|
142
|
+
Analyze::Tree::Values::Primitive.new(
|
143
|
+
value.to_enum(:scan, %r((?<!\\)\$\(([A-Z0-9:_]+)\)|((?:[^\\\$]|\\\$)+))).map { Regexp.last_match }.map { |match|
|
144
|
+
if match[1]
|
145
|
+
if match[1][0, 4] == "ENV:"
|
146
|
+
Analyze::Tree::Segments::Variable.new(match[1][4..-1], scope: :env)
|
147
|
+
else
|
148
|
+
Analyze::Tree::Segments::Variable.new(match[1], scope: :static)
|
149
|
+
end
|
150
|
+
elsif match[2]
|
151
|
+
Analyze::Tree::Segments::Text.new(match[2])
|
152
|
+
end
|
153
|
+
}
|
154
|
+
)
|
155
|
+
elsif value.is_a?(Array)
|
156
|
+
Analyze::Tree::Values::Array.new(
|
157
|
+
value.map { |element|
|
158
|
+
segmentize_value(element)
|
159
|
+
}
|
160
|
+
)
|
161
|
+
elsif value.is_a?(Hash)
|
162
|
+
Analyze::Tree::Values::Hash.new(
|
163
|
+
Utilities::hash_map(value) { |name, element|
|
164
|
+
[name, segmentize_value(element)]
|
165
|
+
}
|
166
|
+
)
|
167
|
+
elsif value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Numeric) || value.is_a?(NilClass)
|
168
|
+
Analyze::Tree::Values::Primitive.new(
|
169
|
+
[Analyze::Tree::Segments::Text.new(value.to_s)]
|
170
|
+
)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def find_referenced_variable(sema_tree:, name:, preset:)
|
175
|
+
sema_tree.variables.find do |variable|
|
176
|
+
variable.name == name && [preset, sema_tree.default_preset].include?(variable.preset)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def assert_preset_name_valid(value, keypath:)
|
181
|
+
unless %r(^[a-z_]*$) =~ value
|
182
|
+
@interface.fatal!("Invalid preset name: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def assert_variable_name_valid(value, keypath:)
|
187
|
+
unless %r(^[A-Z_][A-Z0-9_]*$) =~ value
|
188
|
+
@interface.fatal!("Invalid variable name: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def assert_variable_value_valid(value, keypath:)
|
193
|
+
if value.is_a?(String)
|
194
|
+
unless %r(^((?:[^\$]*(?:(?:\\\$)|(?<!\\)\$\((?:ENV:)?[A-Z_][A-Z0-9_]*\))*)*)$) =~ value
|
195
|
+
@interface.fatal!("Invalid variable value: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
196
|
+
end
|
197
|
+
elsif value.is_a?(Array) || value.is_a?(Hash)
|
198
|
+
@interface.fatal!("Invalid variable value: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
199
|
+
else
|
200
|
+
unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Numeric) || value.is_a?(NilClass)
|
201
|
+
@interface.fatal!("Invalid variable value: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def assert_step_exists(value, keypath:)
|
207
|
+
unless @registry.get_by_name(value)
|
208
|
+
@interface.fatal!("Unknown step: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def assert_step_parameter_name_valid(value, expected:, keypath:)
|
213
|
+
unless expected.include?(value)
|
214
|
+
expected_names = expected.map { |name| "'#{name}'" }.join(", ")
|
215
|
+
@interface.fatal!("Unknown step parameter: '#{value}' at '#{Utilities::keypath_to_s(keypath)}'. Expected one of: [#{expected_names}].")
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def assert_step_parameter_value_valid(value, keypath:)
|
220
|
+
if value.is_a?(String)
|
221
|
+
unless %r(^((?:[^\$]*(?:(?:\\\$)|(?<!\\)\$\((?:ENV:)?[A-Z_]+\))*)*)$) =~ value
|
222
|
+
@interface.fatal!("Invalid step parameter value: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
223
|
+
end
|
224
|
+
elsif value.is_a?(Array)
|
225
|
+
value.each_with_index do |single_value, index|
|
226
|
+
assert_step_parameter_value_valid(single_value, keypath: keypath + [index])
|
227
|
+
end
|
228
|
+
elsif value.is_a?(Hash)
|
229
|
+
value.each_pair do |key, single_value|
|
230
|
+
assert_step_parameter_value_valid(single_value, keypath: keypath + [key])
|
231
|
+
end
|
232
|
+
else
|
233
|
+
unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Numeric) || value.is_a?(NilClass)
|
234
|
+
@interface.fatal!("Invalid step parameter value: '#{value}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def assert_step_parameter_exists(value, expected:, keypath:)
|
240
|
+
unless value.include?(expected)
|
241
|
+
@interface.fatal!("Missing value for required step parameter: '#{expected}' at: '#{Utilities::keypath_to_s(keypath)}'.")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#
|
2
|
+
# root.rb
|
3
|
+
# Copyright © 2019 Netguru S.A. All rights reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
require "highway/compiler/analyze/tree/segments/text"
|
7
|
+
require "highway/compiler/analyze/tree/segments/variable"
|
8
|
+
require "highway/compiler/analyze/tree/stage"
|
9
|
+
require "highway/compiler/analyze/tree/step"
|
10
|
+
require "highway/compiler/analyze/tree/values/array"
|
11
|
+
require "highway/compiler/analyze/tree/values/hash"
|
12
|
+
require "highway/compiler/analyze/tree/values/primitive"
|
13
|
+
require "highway/compiler/analyze/tree/variable"
|
14
|
+
|
15
|
+
module Highway
|
16
|
+
module Compiler
|
17
|
+
module Analyze
|
18
|
+
module Tree
|
19
|
+
|
20
|
+
# This class represents a root node of a semantic tree. It contains
|
21
|
+
# other nodes, such as variables and steps.
|
22
|
+
class Root
|
23
|
+
|
24
|
+
public
|
25
|
+
|
26
|
+
# Initialize an instance.
|
27
|
+
def initialize()
|
28
|
+
@variables = Array.new()
|
29
|
+
@steps = Array.new()
|
30
|
+
@stages = Array.new()
|
31
|
+
end
|
32
|
+
|
33
|
+
# Name of the default preset.
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
attr_accessor :default_preset
|
37
|
+
|
38
|
+
# Variables in the tree.
|
39
|
+
#
|
40
|
+
# @return [Array<Highway::Compiler::Analyze::Tree::Variable>]
|
41
|
+
attr_reader :variables
|
42
|
+
|
43
|
+
# Steps in the tree.
|
44
|
+
#
|
45
|
+
# @return [Array<Highway::Compiler::Analyze::Tree::Step>]
|
46
|
+
attr_reader :steps
|
47
|
+
|
48
|
+
# Stages in the tree.
|
49
|
+
#
|
50
|
+
# @return [Array<Highway::Compiler::Analyze::Tree::Stage>]
|
51
|
+
attr_reader :stages
|
52
|
+
|
53
|
+
# Add a variable to the tree.
|
54
|
+
#
|
55
|
+
# @param name [String] Name of the variable.
|
56
|
+
# @param value [Highway::Compiler::Analyze::Tree::Values::*] Value of the variable.
|
57
|
+
# @param preset [String] Parent preset of the variable.
|
58
|
+
#
|
59
|
+
# @return [Void]
|
60
|
+
def add_variable(name:, value:, preset:)
|
61
|
+
@variables << Variable.new(name: name, value: value, preset: preset)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Add a step to the tree.
|
65
|
+
#
|
66
|
+
# @param index [Integer] Index of step in its scope.
|
67
|
+
# @param name [String] Name of the step.
|
68
|
+
# @param step_class [Class] Definition class of the step.
|
69
|
+
# @param parameters [Highway::Compiler::Analyze::Tree::Values::Hash] The hash value of step parameters.
|
70
|
+
# @param preset [String] Parent preset of the step.
|
71
|
+
# @param stage [String] Parent stage of the step.
|
72
|
+
#
|
73
|
+
# @return [Void]
|
74
|
+
def add_step(index:, name:, step_class:, parameters:, preset:, stage:)
|
75
|
+
@steps << Step.new(index: index, name: name, step_class: step_class, parameters: parameters, preset: preset, stage: stage)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Add a stage to the tree.
|
80
|
+
#
|
81
|
+
# @param index [Integer] Index of the stage.
|
82
|
+
# @param name [String] Name of the stage.
|
83
|
+
# @param policy [Symbol] Execution policy of the stage.
|
84
|
+
#
|
85
|
+
# @return [Void]
|
86
|
+
def add_stage(index:, name:, policy:)
|
87
|
+
@stages << Stage.new(index: index, name: name, policy: policy)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# text.rb
|
3
|
+
# Copyright © 2019 Netguru S.A. All rights reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Highway
|
7
|
+
module Compiler
|
8
|
+
module Analyze
|
9
|
+
module Tree
|
10
|
+
module Segments
|
11
|
+
|
12
|
+
# This class represents a text value segment in the semantic tree. It
|
13
|
+
# consists of a raw text value.
|
14
|
+
class Text
|
15
|
+
|
16
|
+
public
|
17
|
+
|
18
|
+
# Initialize an instance.
|
19
|
+
#
|
20
|
+
# @param value [String] The raw text value.
|
21
|
+
def initialize(value)
|
22
|
+
@value = value
|
23
|
+
end
|
24
|
+
|
25
|
+
# The raw text value.
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
attr_reader :value
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# variable.rb
|
3
|
+
# Copyright © 2019 Netguru S.A. All rights reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
module Highway
|
7
|
+
module Compiler
|
8
|
+
module Analyze
|
9
|
+
module Tree
|
10
|
+
module Segments
|
11
|
+
|
12
|
+
# This class represents a variable value segment in the semantic
|
13
|
+
# tree. It consists of a variable name and its lookup scope.
|
14
|
+
class Variable
|
15
|
+
|
16
|
+
public
|
17
|
+
|
18
|
+
# Initialize an instance.
|
19
|
+
#
|
20
|
+
# @param name [String] The variable name.
|
21
|
+
# @param scope [Symbol] The lookup scope of variable.
|
22
|
+
def initialize(name, scope:)
|
23
|
+
@name = name
|
24
|
+
@scope = scope
|
25
|
+
end
|
26
|
+
|
27
|
+
# The variable name.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
attr_reader :name
|
31
|
+
|
32
|
+
# The lookup scope of the variable.
|
33
|
+
#
|
34
|
+
# @return [Symbol]
|
35
|
+
attr_reader :scope
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|