loxxy 0.2.02 → 0.3.00
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 +59 -0
- data/README.md +19 -2
- data/lib/loxxy/ast/all_lox_nodes.rb +0 -1
- data/lib/loxxy/ast/ast_builder.rb +27 -4
- data/lib/loxxy/ast/ast_visitee.rb +53 -0
- data/lib/loxxy/ast/ast_visitor.rb +2 -10
- data/lib/loxxy/ast/lox_assign_expr.rb +1 -5
- data/lib/loxxy/ast/lox_binary_expr.rb +1 -6
- data/lib/loxxy/ast/lox_block_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_call_expr.rb +1 -5
- data/lib/loxxy/ast/lox_class_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_fun_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_get_expr.rb +1 -6
- data/lib/loxxy/ast/lox_grouping_expr.rb +1 -5
- data/lib/loxxy/ast/lox_if_stmt.rb +2 -6
- data/lib/loxxy/ast/lox_literal_expr.rb +1 -5
- data/lib/loxxy/ast/lox_logical_expr.rb +1 -6
- data/lib/loxxy/ast/lox_node.rb +9 -1
- data/lib/loxxy/ast/lox_print_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_return_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_seq_decl.rb +1 -5
- data/lib/loxxy/ast/lox_set_expr.rb +1 -5
- data/lib/loxxy/ast/lox_super_expr.rb +2 -6
- data/lib/loxxy/ast/lox_this_expr.rb +1 -5
- data/lib/loxxy/ast/lox_unary_expr.rb +1 -6
- data/lib/loxxy/ast/lox_var_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_variable_expr.rb +1 -5
- data/lib/loxxy/ast/lox_while_stmt.rb +2 -6
- data/lib/loxxy/back_end/engine.rb +28 -26
- data/lib/loxxy/back_end/lox_instance.rb +1 -1
- data/lib/loxxy/back_end/resolver.rb +17 -21
- data/lib/loxxy/datatype/number.rb +19 -4
- data/lib/loxxy/front_end/parser.rb +1 -1
- data/lib/loxxy/front_end/scanner.rb +11 -10
- data/lib/loxxy/version.rb +1 -1
- data/spec/back_end/environment_spec.rb +0 -14
- data/spec/back_end/symbol_table_spec.rb +0 -19
- data/spec/back_end/variable_spec.rb +0 -35
- data/spec/front_end/scanner_spec.rb +35 -7
- data/spec/interpreter_spec.rb +36 -0
- metadata +3 -3
- data/lib/loxxy/ast/lox_for_stmt.rb +0 -41
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 231fc227cc66ebd0b4f47a00f9fe7260146d70e64cea3581df6cfc5c71937bef
|
|
4
|
+
data.tar.gz: cd8117dc8ae9b631ad0d7bef34ee972bdcaa8c758045637bae2f3ea0ed25bb79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ca714bbd5fa4fcbae67548cdae0d8c43236b02f30adc45e939c0e1dcd3e6694471ea429f902d5e1a7335d4a4cf9779d167a9387b0f4f0732325bd31237630e8d
|
|
7
|
+
data.tar.gz: '008526b6d9a2e9f5cf27a68f796e53aa5312d67523a53d8c8682cf944ee6cd990adf3928a3af7fb66e056bca4fc6e45fc11119ffcab1dda4d41fb2ca1c1207be'
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,62 @@
|
|
|
1
|
+
## [0.3.00] - 2021-05-07
|
|
2
|
+
- Milestone: `Loxxy` passes all reference test suite.
|
|
3
|
+
|
|
4
|
+
### Fixed
|
|
5
|
+
- Method `BackEdn::Resolver#before_variable_expr`: Standard `Lox` allows re-declaration of a variable at top-level scope
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## [0.2.06] - 2021-05-04
|
|
9
|
+
- Nearly passing the 'official' test suite, fixing non-compliant behavior, specialized exceptions for errors
|
|
10
|
+
|
|
11
|
+
### New
|
|
12
|
+
- Module `LoxFileTester` module that hosts methods that simplify the tests of `Lox` source file.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Folder `test_suite` vastly reorganized. Sub-folder `baseline` contains spec files testing the `Lox` files from official implementation
|
|
16
|
+
- Class `BackEnd::Engine` replaced most `StandardError` by `Loxxy::RuntimeError` exception.
|
|
17
|
+
- Class `BackEnd::Resolver` replaced most `StandardError` by `Loxxy::RuntimeError` exception.
|
|
18
|
+
- Method `Datatype::Number#/` now handles correctly expression like `0/0` (integer divide)
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- `0/0` expression results in a ZeroDivisionError exception, in Lox this result to a NaN (Not a Number). Now, `Loxxy` is aligned to standard `Lox`
|
|
22
|
+
- `FrontEnd::Scanner` now always treats expression like `-123` as the unary or binary minus operator applied to a positive number.
|
|
23
|
+
|
|
24
|
+
## [0.2.05] - 2021-04-26
|
|
25
|
+
- `Loxxy` now transforms for loops into while loops (desugaring), fix in Scanner class
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- Method `Ast::ASTBuilder#reduce_for_stmt` converts 'for' loops into 'while' loops
|
|
29
|
+
- Method `Ast::ASTBuilder#reduce_for_control takes care of case for(expr1;;expr2) now test expression is set to true
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- Method `FrontEnd::Scanner#next_token` keyword recognition was case insensitive
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
- Method `Ast::Visitor#visitor_for_stmt`
|
|
36
|
+
- Method `BackEnd::Engine#after_for_stmt`
|
|
37
|
+
- Method `BackEnd::Resolver#before_for_stmt`
|
|
38
|
+
- Method `BackEnd::Resolver#after_for_stmt`
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## [0.2.04] - 2021-04-25
|
|
42
|
+
- `Loxxy` passes the test suite for `for` statements
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
- Method `BackEnd::Engine#after_for_stmt` now a for(;;) executes the body once; a for without test will execute forever
|
|
46
|
+
- Method `BackEnd::Resolver#after_for_stmt now accepts nil test expression
|
|
47
|
+
|
|
48
|
+
## [0.2.03] - 2021-04-24
|
|
49
|
+
- Fixes for the set (field) expressions, `accept` methods for AST nodes are meta-programmed
|
|
50
|
+
|
|
51
|
+
### New
|
|
52
|
+
- Module `Ast::Visitee` provides the `define_accept` method that generate `accept` method with meta-programming
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
- Method `BackEnd::Engine#before_set_expr` methos method that ensure that the receiver is evaluated first, then the assigned value
|
|
56
|
+
- Method `BackEnd::Engine#after_set_expr` now pushes the value assigned to the field also onto the stack
|
|
57
|
+
- Class `BackEnd::Engine` a number of StnadardError exceptions are replaced by Loxxy::RuntimeError
|
|
58
|
+
|
|
59
|
+
|
|
1
60
|
## [0.2.02] - 2021-04-21
|
|
2
61
|
- Improvements in the scanner class (escape sequence for quotes and newlines), error messages closer to jlox.
|
|
3
62
|
|
data/README.md
CHANGED
|
@@ -19,20 +19,37 @@ Although __Lox__ is fairly simple, it is far from being a toy language:
|
|
|
19
19
|
### Loxxy gem features
|
|
20
20
|
- Complete tree-walking interpreter including lexer, parser and resolver
|
|
21
21
|
- 100% pure Ruby with clean design (not a port from some other language)
|
|
22
|
+
- Passes the `jox` (THE reference `Lox` implementation) test suite
|
|
22
23
|
- Minimal runtime dependency (Rley gem). Won't drag a bunch of gems...
|
|
23
24
|
- Ruby API for integrating a Lox interpreter with your code.
|
|
24
25
|
- A command-line interpreter `loxxy`
|
|
25
|
-
- Open for your language extensions
|
|
26
|
+
- Open for your language extensions...
|
|
27
|
+
|
|
28
|
+
### Why `Loxxy` ?
|
|
29
|
+
- If programming languages are one of your subject interest...
|
|
30
|
+
- ... and you wanted learn how to implement one in Ruby...
|
|
31
|
+
- ... then `Loxxy` can help to understand and experiment in this rewarding craft.
|
|
26
32
|
|
|
27
33
|
## How to start in 1, 2, 3...?
|
|
28
34
|
... in less than 3 minutes...
|
|
29
35
|
|
|
30
36
|
### 1. Installing
|
|
31
|
-
|
|
37
|
+
__Loxxy__'s installation is pretty standard:
|
|
32
38
|
|
|
33
39
|
|
|
34
40
|
$ gem install loxxy
|
|
35
41
|
|
|
42
|
+
Alternatively, you can install `loxxy` with Bundler.
|
|
43
|
+
Add this line to your application's Gemfile:
|
|
44
|
+
|
|
45
|
+
gem 'loxxy'
|
|
46
|
+
|
|
47
|
+
And then execute:
|
|
48
|
+
|
|
49
|
+
$ bundle
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
36
53
|
### 2. Your first `Lox` program
|
|
37
54
|
Create a text file and enter the following lines:
|
|
38
55
|
```javascript
|
|
@@ -19,7 +19,6 @@ require_relative 'lox_while_stmt'
|
|
|
19
19
|
require_relative 'lox_return_stmt'
|
|
20
20
|
require_relative 'lox_print_stmt'
|
|
21
21
|
require_relative 'lox_if_stmt'
|
|
22
|
-
require_relative 'lox_for_stmt'
|
|
23
22
|
require_relative 'lox_var_stmt'
|
|
24
23
|
require_relative 'lox_class_stmt'
|
|
25
24
|
require_relative 'lox_seq_decl'
|
|
@@ -225,16 +225,39 @@ module Loxxy
|
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
# rule('forStmt' => 'FOR LEFT_PAREN forControl RIGHT_PAREN statement')
|
|
228
|
-
def reduce_for_stmt(_production, _range,
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
def reduce_for_stmt(_production, _range, tokens, theChildren)
|
|
229
|
+
# Following 'Crafting Interpreters', we replace the for statement by a while loop
|
|
230
|
+
return theChildren[4] if theChildren[2].compact.empty? # for(;;) => execute body once
|
|
231
|
+
|
|
232
|
+
(init, test, update) = theChildren[2]
|
|
233
|
+
if update
|
|
234
|
+
new_body = LoxSeqDecl.new(tokens[0].position, [theChildren[4], update])
|
|
235
|
+
stmt = Ast::LoxBlockStmt.new(tokens[1].position, new_body)
|
|
236
|
+
else
|
|
237
|
+
stmt = theChildren[4]
|
|
238
|
+
end
|
|
239
|
+
while_stmt = Ast::LoxWhileStmt.new(tokens[0].position, test, stmt)
|
|
240
|
+
|
|
241
|
+
if init
|
|
242
|
+
block_body = LoxSeqDecl.new(tokens[0].position, [init, while_stmt])
|
|
243
|
+
for_stmt = Ast::LoxBlockStmt.new(tokens[1].position, block_body)
|
|
244
|
+
else
|
|
245
|
+
for_stmt = while_stmt
|
|
246
|
+
end
|
|
247
|
+
|
|
231
248
|
for_stmt
|
|
232
249
|
end
|
|
233
250
|
|
|
234
251
|
# rule('forControl' => 'forInitialization forTest forUpdate')
|
|
235
252
|
def reduce_for_control(_production, _range, tokens, theChildren)
|
|
236
253
|
(init, test, update) = theChildren
|
|
237
|
-
|
|
254
|
+
if test.nil? && update
|
|
255
|
+
# when test expr is nil but update expr is not, then force test to be true
|
|
256
|
+
test = LoxLiteralExpr.new(tokens[0].position, Datatype::True.instance)
|
|
257
|
+
[init, test, update]
|
|
258
|
+
else
|
|
259
|
+
theChildren
|
|
260
|
+
end
|
|
238
261
|
end
|
|
239
262
|
|
|
240
263
|
# rule('forInitialization' => 'SEMICOLON')
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Loxxy
|
|
4
|
+
module Ast
|
|
5
|
+
# Mix-in module that relies on meta-programming to add a method
|
|
6
|
+
# called `accept` to the host class (an AST node).
|
|
7
|
+
# That method fulfills the expected behavior of the `visitee` in
|
|
8
|
+
# the Visitor design pattern.
|
|
9
|
+
module ASTVisitee
|
|
10
|
+
# Convert the input string into a snake case string.
|
|
11
|
+
# Example: ClassExpr => class_expr
|
|
12
|
+
# @param aName [String] input name to convert
|
|
13
|
+
# @return [String] the name converted into snake case
|
|
14
|
+
def snake_case(aName)
|
|
15
|
+
converted = +''
|
|
16
|
+
down = false
|
|
17
|
+
aName.each_char do |ch|
|
|
18
|
+
lower = ch.downcase
|
|
19
|
+
if lower == ch
|
|
20
|
+
converted << ch
|
|
21
|
+
down = true
|
|
22
|
+
else
|
|
23
|
+
converted << '_' if down && converted[-1] != '_'
|
|
24
|
+
converted << lower
|
|
25
|
+
down = false
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
converted
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# This method adds a method named `accept` that takes a visitor
|
|
33
|
+
# The visitor is expected to implement a method named:
|
|
34
|
+
# visit + class name (without the Lox prefix) in snake case
|
|
35
|
+
# Example: class name = LoxClassStmt => visit method = visit_class_stmt
|
|
36
|
+
def define_accept
|
|
37
|
+
return if instance_methods(false).include?(:accept)
|
|
38
|
+
|
|
39
|
+
base_name = name.split('::').last
|
|
40
|
+
name_suffix = snake_case(base_name).sub(/^lox/, '')
|
|
41
|
+
accept_body = <<-MTH_END
|
|
42
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
|
43
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
|
44
|
+
def accept(aVisitor)
|
|
45
|
+
aVisitor.visit#{name_suffix}(self)
|
|
46
|
+
end
|
|
47
|
+
MTH_END
|
|
48
|
+
|
|
49
|
+
class_eval(accept_body)
|
|
50
|
+
end
|
|
51
|
+
end # module
|
|
52
|
+
end # module
|
|
53
|
+
end # module
|
|
@@ -75,14 +75,6 @@ module Loxxy
|
|
|
75
75
|
broadcast(:after_class_stmt, aClassStmt, self)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
# Visit event. The visitor is about to visit a for statement.
|
|
79
|
-
# @param aForStmt [AST::LOXForStmt] the for statement node to visit
|
|
80
|
-
def visit_for_stmt(aForStmt)
|
|
81
|
-
broadcast(:before_for_stmt, aForStmt)
|
|
82
|
-
traverse_subnodes(aForStmt) # The condition is visited/evaluated here...
|
|
83
|
-
broadcast(:after_for_stmt, aForStmt, self)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
78
|
# Visit event. The visitor is about to visit a if statement.
|
|
87
79
|
# @param anIfStmt [AST::LOXIfStmt] the if statement node to visit
|
|
88
80
|
def visit_if_stmt(anIfStmt)
|
|
@@ -111,7 +103,7 @@ module Loxxy
|
|
|
111
103
|
# @param aWhileStmt [AST::LOXWhileStmt] the while statement node to visit
|
|
112
104
|
def visit_while_stmt(aWhileStmt)
|
|
113
105
|
broadcast(:before_while_stmt, aWhileStmt)
|
|
114
|
-
traverse_subnodes(aWhileStmt) # The condition is visited/evaluated here...
|
|
106
|
+
traverse_subnodes(aWhileStmt) if aWhileStmt.condition # The condition is visited/evaluated here...
|
|
115
107
|
broadcast(:after_while_stmt, aWhileStmt, self)
|
|
116
108
|
end
|
|
117
109
|
|
|
@@ -133,7 +125,7 @@ module Loxxy
|
|
|
133
125
|
|
|
134
126
|
# @param aSetExpr [AST::LOXGetExpr] the get expression node to visit
|
|
135
127
|
def visit_set_expr(aSetExpr)
|
|
136
|
-
broadcast(:before_set_expr, aSetExpr)
|
|
128
|
+
broadcast(:before_set_expr, aSetExpr, self)
|
|
137
129
|
traverse_subnodes(aSetExpr)
|
|
138
130
|
broadcast(:after_set_expr, aSetExpr, self)
|
|
139
131
|
end
|
|
@@ -17,11 +17,7 @@ module Loxxy
|
|
|
17
17
|
@name = aName
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
22
|
-
def accept(visitor)
|
|
23
|
-
visitor.visit_assign_expr(self)
|
|
24
|
-
end
|
|
20
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
25
21
|
end # class
|
|
26
22
|
end # module
|
|
27
23
|
end # module
|
|
@@ -16,12 +16,7 @@ module Loxxy
|
|
|
16
16
|
@operator = anOperator
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
#
|
|
20
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
21
|
-
def accept(visitor)
|
|
22
|
-
visitor.visit_binary_expr(self)
|
|
23
|
-
end
|
|
24
|
-
|
|
19
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
25
20
|
alias operands subnodes
|
|
26
21
|
end # class
|
|
27
22
|
end # module
|
|
@@ -15,11 +15,7 @@ module Loxxy
|
|
|
15
15
|
subnodes.size == 1 && subnodes[0].nil?
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
20
|
-
def accept(visitor)
|
|
21
|
-
visitor.visit_block_stmt(self)
|
|
22
|
-
end
|
|
18
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
23
19
|
end # class
|
|
24
20
|
end # module
|
|
25
21
|
end # module
|
|
@@ -15,11 +15,7 @@ module Loxxy
|
|
|
15
15
|
@arguments = argList
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
20
|
-
def accept(visitor)
|
|
21
|
-
visitor.visit_call_expr(self)
|
|
22
|
-
end
|
|
18
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
23
19
|
end # class
|
|
24
20
|
end # module
|
|
25
21
|
end # module
|
|
@@ -24,11 +24,7 @@ module Loxxy
|
|
|
24
24
|
@body = theMethods
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
#
|
|
28
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
29
|
-
def accept(visitor)
|
|
30
|
-
visitor.visit_class_stmt(self)
|
|
31
|
-
end
|
|
27
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
32
28
|
end # class
|
|
33
29
|
end # module
|
|
34
30
|
end # module
|
|
@@ -23,11 +23,7 @@ module Loxxy
|
|
|
23
23
|
@is_method = false
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
#
|
|
27
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
28
|
-
def accept(visitor)
|
|
29
|
-
visitor.visit_fun_stmt(self)
|
|
30
|
-
end
|
|
26
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
31
27
|
end # class
|
|
32
28
|
# rubocop: enable Style/AccessorGrouping
|
|
33
29
|
end # module
|
|
@@ -18,12 +18,7 @@ module Loxxy
|
|
|
18
18
|
@property = aPropertyName
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
#
|
|
22
|
-
# @param visitor [ASTVisitor] the visitor
|
|
23
|
-
def accept(visitor)
|
|
24
|
-
visitor.visit_get_expr(self)
|
|
25
|
-
end
|
|
26
|
-
|
|
21
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
27
22
|
alias callee= object=
|
|
28
23
|
end # class
|
|
29
24
|
end # module
|
|
@@ -11,11 +11,7 @@ module Loxxy
|
|
|
11
11
|
super(aPosition, [subExpr])
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
#
|
|
15
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
16
|
-
def accept(visitor)
|
|
17
|
-
visitor.visit_grouping_expr(self)
|
|
18
|
-
end
|
|
14
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
19
15
|
end # class
|
|
20
16
|
end # module
|
|
21
17
|
end # module
|
|
@@ -21,17 +21,13 @@ module Loxxy
|
|
|
21
21
|
@else_stmt = elseStmt
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# Part of the 'visitee' role in Visitor design pattern.
|
|
25
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
26
|
-
def accept(visitor)
|
|
27
|
-
visitor.visit_if_stmt(self)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
24
|
# Accessor to the condition expression
|
|
31
25
|
# @return [LoxNode]
|
|
32
26
|
def condition
|
|
33
27
|
subnodes[0]
|
|
34
28
|
end
|
|
29
|
+
|
|
30
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
35
31
|
end # class
|
|
36
32
|
end # module
|
|
37
33
|
end # module
|
|
@@ -15,11 +15,7 @@ module Loxxy
|
|
|
15
15
|
@literal = aLiteral
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
# @param visitor [ASTVisitor] the visitor
|
|
20
|
-
def accept(visitor)
|
|
21
|
-
visitor.visit_literal_expr(self)
|
|
22
|
-
end
|
|
18
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
23
19
|
end # class
|
|
24
20
|
end # module
|
|
25
21
|
end # module
|
|
@@ -16,12 +16,7 @@ module Loxxy
|
|
|
16
16
|
@operator = anOperator
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
#
|
|
20
|
-
# @param visitor [Ast::ASTVisitor] the visitor
|
|
21
|
-
def accept(visitor)
|
|
22
|
-
visitor.visit_logical_expr(self)
|
|
23
|
-
end
|
|
24
|
-
|
|
19
|
+
define_accept # Add `accept` method as found in Visitor design pattern
|
|
25
20
|
alias operands subnodes
|
|
26
21
|
end # class
|
|
27
22
|
end # module
|
data/lib/loxxy/ast/lox_node.rb
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'ast_visitee'
|
|
4
|
+
|
|
3
5
|
module Loxxy
|
|
4
6
|
module Ast
|
|
7
|
+
# Abstract class.
|
|
8
|
+
# Instances of its subclasses represent nodes of an abstract syntax tree
|
|
9
|
+
# that is the product of the parse of an input text.
|
|
5
10
|
class LoxNode
|
|
11
|
+
# Let nodes take `visitee` role as defined in the Visitor design pattern
|
|
12
|
+
extend ASTVisitee
|
|
13
|
+
|
|
6
14
|
# return [Rley::Lexical::Position] Position of the entry in the input stream.
|
|
7
15
|
attr_reader :position
|
|
8
16
|
|
|
@@ -16,7 +24,7 @@ module Loxxy
|
|
|
16
24
|
# Default: do nothing ...
|
|
17
25
|
end
|
|
18
26
|
|
|
19
|
-
# Abstract method.
|
|
27
|
+
# Abstract method (must be overriden in subclasses).
|
|
20
28
|
# Part of the 'visitee' role in Visitor design pattern.
|
|
21
29
|
# @param _visitor [LoxxyTreeVisitor] the visitor
|
|
22
30
|
def accept(_visitor)
|