loxxy 0.0.17 → 0.0.22
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 +4 -4
- data/CHANGELOG.md +61 -2
- data/README.md +164 -50
- data/lib/loxxy/ast/all_lox_nodes.rb +7 -1
- data/lib/loxxy/ast/ast_builder.rb +63 -3
- data/lib/loxxy/ast/ast_visitor.rb +68 -1
- data/lib/loxxy/ast/lox_grouping_expr.rb +23 -0
- data/lib/loxxy/ast/lox_if_stmt.rb +35 -0
- data/lib/loxxy/ast/lox_logical_expr.rb +28 -0
- data/lib/loxxy/ast/lox_seq_decl.rb +23 -0
- data/lib/loxxy/ast/lox_var_stmt.rb +28 -0
- data/lib/loxxy/ast/lox_variable_expr.rb +26 -0
- data/lib/loxxy/back_end/engine.rb +70 -1
- data/lib/loxxy/back_end/entry.rb +41 -0
- data/lib/loxxy/back_end/environment.rb +66 -0
- data/lib/loxxy/back_end/symbol_table.rb +135 -0
- data/lib/loxxy/back_end/variable.rb +25 -0
- data/lib/loxxy/datatype/builtin_datatype.rb +32 -5
- data/lib/loxxy/front_end/grammar.rb +9 -9
- data/lib/loxxy/interpreter.rb +1 -1
- data/lib/loxxy/version.rb +1 -1
- data/spec/back_end/engine_spec.rb +9 -0
- data/spec/back_end/environment_spec.rb +74 -0
- data/spec/back_end/symbol_table_spec.rb +142 -0
- data/spec/back_end/variable_spec.rb +79 -0
- data/spec/front_end/parser_spec.rb +25 -23
- data/spec/interpreter_spec.rb +110 -1
- metadata +18 -2
@@ -51,6 +51,30 @@ module Loxxy
|
|
51
51
|
broadcast(:after_ptree, aParseTree)
|
52
52
|
end
|
53
53
|
|
54
|
+
# Visit event. The visitor is about to visit a variable declaration statement.
|
55
|
+
# @param aPrintStmt [AST::LOXVarStmt] the variable declaration node to visit
|
56
|
+
def visit_seq_decl(aSeqDecls)
|
57
|
+
broadcast(:before_seq_decl, aSeqDecls)
|
58
|
+
traverse_subnodes(aSeqDecls)
|
59
|
+
broadcast(:after_seq_decl, aSeqDecls)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Visit event. The visitor is about to visit a variable declaration statement.
|
63
|
+
# @param aPrintStmt [AST::LOXVarStmt] the variable declaration node to visit
|
64
|
+
def visit_var_stmt(aVarStmt)
|
65
|
+
broadcast(:before_var_stmt, aVarStmt)
|
66
|
+
traverse_subnodes(aVarStmt)
|
67
|
+
broadcast(:after_var_stmt, aVarStmt)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Visit event. The visitor is about to visit a if statement.
|
71
|
+
# @param anIfStmt [AST::LOXIfStmt] the if statement node to visit
|
72
|
+
def visit_if_stmt(anIfStmt)
|
73
|
+
broadcast(:before_if_stmt, anIfStmt)
|
74
|
+
traverse_subnodes(anIfStmt) # The condition is visited/evaluated here...
|
75
|
+
broadcast(:after_if_stmt, anIfStmt, self)
|
76
|
+
end
|
77
|
+
|
54
78
|
# Visit event. The visitor is about to visit a print statement.
|
55
79
|
# @param aPrintStmt [AST::LOXPrintStmt] the print statement node to visit
|
56
80
|
def visit_print_stmt(aPrintStmt)
|
@@ -59,6 +83,20 @@ module Loxxy
|
|
59
83
|
broadcast(:after_print_stmt, aPrintStmt)
|
60
84
|
end
|
61
85
|
|
86
|
+
# Visit event. The visitor is about to visit a logical expression.
|
87
|
+
# Since logical expressions may take shorcuts by not evaluating all their
|
88
|
+
# sub-expressiosns, they are responsible for visiting or not their children.
|
89
|
+
# @param aBinaryExpr [AST::LOXBinaryExpr] the logical expression node to visit
|
90
|
+
def visit_logical_expr(aLogicalExpr)
|
91
|
+
broadcast(:before_logical_expr, aLogicalExpr)
|
92
|
+
|
93
|
+
# As logical connectors may take a shortcut only the first argument is visited
|
94
|
+
traverse_given_subnode(aLogicalExpr, 0)
|
95
|
+
|
96
|
+
# The second child could be visited: this action is deferred in handler
|
97
|
+
broadcast(:after_logical_expr, aLogicalExpr, self)
|
98
|
+
end
|
99
|
+
|
62
100
|
# Visit event. The visitor is about to visit a binary expression.
|
63
101
|
# @param aBinaryExpr [AST::LOXBinaryExpr] the binary expression node to visit
|
64
102
|
def visit_binary_expr(aBinaryExpr)
|
@@ -75,6 +113,14 @@ module Loxxy
|
|
75
113
|
broadcast(:after_unary_expr, anUnaryExpr)
|
76
114
|
end
|
77
115
|
|
116
|
+
# Visit event. The visitor is about to visit a grouping expression.
|
117
|
+
# @param aGroupingExpr [AST::LoxGroupingExpr] grouping expression to visit
|
118
|
+
def visit_grouping_expr(aGroupingExpr)
|
119
|
+
broadcast(:before_grouping_expr, aGroupingExpr)
|
120
|
+
traverse_subnodes(aGroupingExpr)
|
121
|
+
broadcast(:after_grouping_expr, aGroupingExpr)
|
122
|
+
end
|
123
|
+
|
78
124
|
# Visit event. The visitor is visiting the
|
79
125
|
# given terminal node containing a datatype object.
|
80
126
|
# @param aLiteralExpr [AST::LoxLiteralExpr] the leaf node to visit.
|
@@ -83,8 +129,15 @@ module Loxxy
|
|
83
129
|
broadcast(:after_literal_expr, aLiteralExpr)
|
84
130
|
end
|
85
131
|
|
132
|
+
# Visit event. The visitor is visiting a variable reference node
|
133
|
+
# @param aLiteralExpr [AST::LoxVariableExpr] the variable reference node to visit.
|
134
|
+
def visit_variable_expr(aVariableExpr)
|
135
|
+
broadcast(:before_variable_expr, aVariableExpr)
|
136
|
+
broadcast(:after_variable_expr, aVariableExpr, self)
|
137
|
+
end
|
138
|
+
|
86
139
|
# Visit event. The visitor is about to visit the given non terminal node.
|
87
|
-
# @param aNonTerminalNode [Rley::
|
140
|
+
# @param aNonTerminalNode [Rley::PTree::NonTerminalNode] the node to visit.
|
88
141
|
def visit_nonterminal(_non_terminal_node)
|
89
142
|
# Loxxy interpreter encountered a CST node (Concrete Syntax Tree)
|
90
143
|
# that it cannot handle.
|
@@ -106,6 +159,20 @@ module Loxxy
|
|
106
159
|
broadcast(:after_subnodes, aParentNode, subnodes)
|
107
160
|
end
|
108
161
|
|
162
|
+
# Visit event. The visitor is about to visit one given subnode of a non
|
163
|
+
# terminal node.
|
164
|
+
# @param aParentNode [Ast::LocCompoundExpr] the parent node.
|
165
|
+
# @param index [integer] index of child subnode
|
166
|
+
def traverse_given_subnode(aParentNode, index)
|
167
|
+
subnode = aParentNode.subnodes[index]
|
168
|
+
broadcast(:before_given_subnode, aParentNode, subnode)
|
169
|
+
|
170
|
+
# Now, let's proceed with the visit of that subnode
|
171
|
+
subnode.accept(self)
|
172
|
+
|
173
|
+
broadcast(:after_given_subnode, aParentNode, subnode)
|
174
|
+
end
|
175
|
+
|
109
176
|
# Send a notification to all subscribers.
|
110
177
|
# @param msg [Symbol] event to notify
|
111
178
|
# @param args [Array] arguments of the notification.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxGroupingExpr < LoxCompoundExpr
|
8
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
9
|
+
# @param subExpr [Loxxy::Ast::LoxNode]
|
10
|
+
def initialize(aPosition, subExpr)
|
11
|
+
super(aPosition, [subExpr])
|
12
|
+
end
|
13
|
+
|
14
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
15
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
16
|
+
def accept(visitor)
|
17
|
+
visitor.visit_grouping_expr(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
alias operands subnodes
|
21
|
+
end # class
|
22
|
+
end # module
|
23
|
+
end # module
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxIfStmt < LoxCompoundExpr
|
8
|
+
# @return [LoxNode] code of then branch
|
9
|
+
attr_reader :then_stmt
|
10
|
+
|
11
|
+
# @return [LoxNode, NilClass] code of else branch
|
12
|
+
attr_reader :else_stmt
|
13
|
+
|
14
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
15
|
+
# @param subExpr [Loxxy::Ast::LoxNode]
|
16
|
+
def initialize(aPosition, condExpr, thenStmt, elseStmt)
|
17
|
+
super(aPosition, [condExpr])
|
18
|
+
@then_stmt = thenStmt
|
19
|
+
@else_stmt = elseStmt
|
20
|
+
end
|
21
|
+
|
22
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
23
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
24
|
+
def accept(visitor)
|
25
|
+
visitor.visit_if_stmt(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Accessor to the condition expression
|
29
|
+
# @return [LoxNode]
|
30
|
+
def condition
|
31
|
+
subnodes[0]
|
32
|
+
end
|
33
|
+
end # class
|
34
|
+
end # module
|
35
|
+
end # module
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxLogicalExpr < LoxCompoundExpr
|
8
|
+
# @return [Symbol] message name to be sent to receiver
|
9
|
+
attr_reader :operator
|
10
|
+
|
11
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
12
|
+
# @param operand1 [Loxxy::Ast::LoxNode]
|
13
|
+
# @param operand2 [Loxxy::Ast::LoxNode]
|
14
|
+
def initialize(aPosition, anOperator, operand1, operand2)
|
15
|
+
super(aPosition, [operand1, operand2])
|
16
|
+
@operator = anOperator
|
17
|
+
end
|
18
|
+
|
19
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
20
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
21
|
+
def accept(visitor)
|
22
|
+
visitor.visit_logical_expr(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
alias operands subnodes
|
26
|
+
end # class
|
27
|
+
end # module
|
28
|
+
end # module
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxSeqDecl < LoxCompoundExpr
|
8
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
9
|
+
# @param declarations [Arrya<Loxxy::Ast::LoxNode>]
|
10
|
+
def initialize(aPosition, declarations)
|
11
|
+
super(aPosition, declarations)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
15
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
16
|
+
def accept(visitor)
|
17
|
+
visitor.visit_seq_decl(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
alias operands subnodes
|
21
|
+
end # class
|
22
|
+
end # module
|
23
|
+
end # module
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
# This AST node represents a variable declaration
|
8
|
+
class LoxVarStmt < LoxCompoundExpr
|
9
|
+
# @return [String] variable name
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
13
|
+
# @param aName [String] name of the variable
|
14
|
+
# @param aValue [Loxxy::Ast::LoxNode, NilClass] initial value for the variable
|
15
|
+
def initialize(aPosition, aName, aValue)
|
16
|
+
initial_value = aValue ? [aValue] : []
|
17
|
+
super(aPosition, initial_value)
|
18
|
+
@name = aName
|
19
|
+
end
|
20
|
+
|
21
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
22
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
23
|
+
def accept(visitor)
|
24
|
+
visitor.visit_var_stmt(self)
|
25
|
+
end
|
26
|
+
end # class
|
27
|
+
end # module
|
28
|
+
end # module
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_node'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
# This AST node represents a mention of a variable
|
8
|
+
class LoxVariableExpr < LoxNode
|
9
|
+
# @return [String] variable name
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
13
|
+
# @param aName [String] name of the variable
|
14
|
+
def initialize(aPosition, aName)
|
15
|
+
super(aPosition)
|
16
|
+
@name = aName
|
17
|
+
end
|
18
|
+
|
19
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
20
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
21
|
+
def accept(visitor)
|
22
|
+
visitor.visit_variable_expr(self)
|
23
|
+
end
|
24
|
+
end # class
|
25
|
+
end # module
|
26
|
+
end # module
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# Load all the classes implementing AST nodes
|
4
4
|
require_relative '../ast/all_lox_nodes'
|
5
|
+
require_relative 'symbol_table'
|
5
6
|
|
6
7
|
module Loxxy
|
7
8
|
module BackEnd
|
@@ -12,13 +13,17 @@ module Loxxy
|
|
12
13
|
# @return [Hash] A set of configuration options
|
13
14
|
attr_reader :config
|
14
15
|
|
15
|
-
# @return [
|
16
|
+
# @return [BackEnd::SymbolTable]
|
17
|
+
attr_reader :symbol_table
|
18
|
+
|
19
|
+
# @return [Array<Datatype::BuiltinDatatyp>] Stack for the values of expr
|
16
20
|
attr_reader :stack
|
17
21
|
|
18
22
|
# @param theOptions [Hash]
|
19
23
|
def initialize(theOptions)
|
20
24
|
@config = theOptions
|
21
25
|
@ostream = config.include?(:ostream) ? config[:ostream] : $stdout
|
26
|
+
@symbol_table = SymbolTable.new
|
22
27
|
@stack = []
|
23
28
|
end
|
24
29
|
|
@@ -33,13 +38,66 @@ module Loxxy
|
|
33
38
|
stack.empty? ? Datatype::Nil.instance : stack.pop
|
34
39
|
end
|
35
40
|
|
41
|
+
##########################################################################
|
36
42
|
# Visit event handling
|
43
|
+
##########################################################################
|
44
|
+
|
45
|
+
def after_seq_decl(aSeqDecls)
|
46
|
+
# Do nothing, subnodes were already evaluated
|
47
|
+
end
|
48
|
+
|
49
|
+
def after_var_stmt(aVarStmt)
|
50
|
+
new_var = Variable.new(aVarStmt.name, aVarStmt.subnodes[0])
|
51
|
+
symbol_table.insert(new_var)
|
52
|
+
end
|
53
|
+
|
54
|
+
def after_if_stmt(anIfStmt, aVisitor)
|
55
|
+
# Retrieve the result of the condition evaluation
|
56
|
+
condition = stack.pop
|
57
|
+
if condition.truthy?
|
58
|
+
result = anIfStmt.then_stmt.accept(aVisitor)
|
59
|
+
elsif anIfStmt.else_stmt
|
60
|
+
anIfStmt.else_stmt.accept(aVisitor)
|
61
|
+
end
|
62
|
+
end
|
37
63
|
|
38
64
|
def after_print_stmt(_printStmt)
|
39
65
|
tos = stack.pop
|
40
66
|
@ostream.print tos.to_str
|
41
67
|
end
|
42
68
|
|
69
|
+
def after_logical_expr(aLogicalExpr, visitor)
|
70
|
+
op = aLogicalExpr.operator
|
71
|
+
operand1 = stack.pop # only first operand was evaluated
|
72
|
+
result = nil
|
73
|
+
if ((op == :and) && operand1.falsey?) || ((op == :or) && operand1.truthy?)
|
74
|
+
result = operand1
|
75
|
+
else
|
76
|
+
raw_operand2 = aLogicalExpr.subnodes[1]
|
77
|
+
raw_operand2.accept(visitor) # Visit means operand2 is evaluated
|
78
|
+
operand2 = stack.pop
|
79
|
+
result = logical_2nd_arg(operand2)
|
80
|
+
end
|
81
|
+
|
82
|
+
stack.push result
|
83
|
+
end
|
84
|
+
|
85
|
+
def logical_2nd_arg(operand2)
|
86
|
+
case operand2
|
87
|
+
when false
|
88
|
+
False.instance # Convert to Lox equivalent
|
89
|
+
when nil
|
90
|
+
Nil.instance # Convert to Lox equivalent
|
91
|
+
when true
|
92
|
+
True.instance # Convert to Lox equivalent
|
93
|
+
when Proc
|
94
|
+
# Second operand wasn't yet evaluated...
|
95
|
+
operand2.call
|
96
|
+
else
|
97
|
+
operand2
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
43
101
|
def after_binary_expr(aBinaryExpr)
|
44
102
|
op = aBinaryExpr.operator
|
45
103
|
operand2 = stack.pop
|
@@ -63,6 +121,17 @@ module Loxxy
|
|
63
121
|
end
|
64
122
|
end
|
65
123
|
|
124
|
+
def after_grouping_expr(_groupingExpr)
|
125
|
+
# Do nothing: work was already done by visiting /evaluating the subexpression
|
126
|
+
end
|
127
|
+
|
128
|
+
def after_variable_expr(aVarExpr, aVisitor)
|
129
|
+
var_name = aVarExpr.name
|
130
|
+
var = symbol_table.lookup(var_name)
|
131
|
+
raise StandardError, "Unknown variable #{var_name}" unless var
|
132
|
+
var.value.accept(aVisitor) # Evaluate the variable value
|
133
|
+
end
|
134
|
+
|
66
135
|
# @param literalExpr [Ast::LoxLiteralExpr]
|
67
136
|
def before_literal_expr(literalExpr)
|
68
137
|
stack.push(literalExpr.literal)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Loxxy
|
4
|
+
module BackEnd
|
5
|
+
# Mix-in module that implements the expected common behaviour of entries
|
6
|
+
# placed in the symbol table.
|
7
|
+
module Entry
|
8
|
+
# @return [String] User-defined name of the entry.
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
=begin
|
12
|
+
# @return [String] Suffix for building the internal name of the entry.
|
13
|
+
attr_accessor :suffix
|
14
|
+
=end
|
15
|
+
|
16
|
+
# Initialize the entry with given name
|
17
|
+
# @param aName [String] The name of the entry
|
18
|
+
def init_name(aName)
|
19
|
+
@name = aName.dup
|
20
|
+
@name.freeze
|
21
|
+
end
|
22
|
+
=begin
|
23
|
+
# Return the internal name of the entry
|
24
|
+
# Internal names used to disambiguate entry names.
|
25
|
+
# There might be homonyns between variable because:
|
26
|
+
# - A child Scope may have a entry with same name as one of its
|
27
|
+
# ancestor(s).
|
28
|
+
# - Multiple calls to same defrel or procedure may imply multiple creation
|
29
|
+
# of a entry given name...
|
30
|
+
# @return [String] internal name
|
31
|
+
def i_name
|
32
|
+
if suffix =~ /^_/
|
33
|
+
label + suffix
|
34
|
+
else
|
35
|
+
(suffix.nil? || suffix.empty?) ? label : suffix
|
36
|
+
end
|
37
|
+
end
|
38
|
+
=end
|
39
|
+
end # module
|
40
|
+
end # module
|
41
|
+
end # module
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'variable'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module BackEnd
|
7
|
+
# A environment is a name space that corresponds either to a specific
|
8
|
+
# delimited region in Loxxy source code or to an activation record
|
9
|
+
# of a relation or a relation definition.
|
10
|
+
# It contains a map of names to the objects they name (e.g. logical var)
|
11
|
+
class Environment
|
12
|
+
# The parent (enclosing) environment.
|
13
|
+
# @return [Environment, NilClass]
|
14
|
+
attr_accessor :parent
|
15
|
+
|
16
|
+
# Mapping from user-defined name to related definition
|
17
|
+
# (say, a variable object)
|
18
|
+
# @return [Hash{String => Variable}] Pairs of the kind
|
19
|
+
attr_reader :defns
|
20
|
+
|
21
|
+
# Construct a environment instance.
|
22
|
+
# @param aParent [Environment, NilClass] Parent environment to this one.
|
23
|
+
def initialize(aParent = nil)
|
24
|
+
@parent = aParent
|
25
|
+
@defns = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Add a new variable to the environment.
|
29
|
+
# @param anEntry [BackEnd::Variable]
|
30
|
+
# @return [BackEnd::Variable] the variable
|
31
|
+
def insert(anEntry)
|
32
|
+
e = validated_entry(anEntry)
|
33
|
+
# e.suffix = default_suffix if e.kind_of?(BackEnd::Variable)
|
34
|
+
defns[e.name] = e
|
35
|
+
|
36
|
+
e
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns a string with a human-readable representation of the object.
|
40
|
+
# @return [String]
|
41
|
+
def inspect
|
42
|
+
+"#<#{self.class}:#{object_id.to_s(16)}>"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def validated_entry(anEntry)
|
48
|
+
name = anEntry.name
|
49
|
+
unless name.kind_of?(String) && !name.empty?
|
50
|
+
err_msg = 'Invalid variable name argument.'
|
51
|
+
raise StandardError, err_msg
|
52
|
+
end
|
53
|
+
if defns.include?(name) && !anEntry.kind_of?(Variable)
|
54
|
+
err_msg = "Variable with name '#{name}' already exists."
|
55
|
+
raise StandardError, err_msg
|
56
|
+
end
|
57
|
+
|
58
|
+
anEntry
|
59
|
+
end
|
60
|
+
|
61
|
+
# def default_suffix
|
62
|
+
# @default_suffix ||= "_#{object_id.to_s(16)}"
|
63
|
+
# end
|
64
|
+
end # class
|
65
|
+
end # module
|
66
|
+
end # module
|