loxxy 0.2.01 → 0.2.06
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -0
- data/README.md +25 -11
- data/bin/loxxy +9 -5
- 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 +16 -22
- data/lib/loxxy/datatype/number.rb +19 -4
- data/lib/loxxy/error.rb +3 -0
- data/lib/loxxy/front_end/parser.rb +1 -1
- data/lib/loxxy/front_end/scanner.rb +43 -17
- data/lib/loxxy/version.rb +1 -1
- data/spec/front_end/scanner_spec.rb +69 -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: cbb2f24e245891baabf20458e5b663784ba7f82ff902ab7892007d9b53d99347
|
4
|
+
data.tar.gz: eab4ede6f48470449f731e3074b2ac2fe72b53449c9471231ea64d0007a873ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8037d3c239e39d47554c4e7f7698e5908cdaa5e460c8972fe8dc5b58ee5fd59647c413db95250ff739c08f9ca891c8f576eb8d78aa63cf40039e8d1b3328e9a2
|
7
|
+
data.tar.gz: 795face50a76140ba2f6be2e6e6c44e671992baaea2ecade980acf1baed173dc59cbe7cd2ce419b509e8593068ffc3e637e0678dab2db72a96250d4e53ef0338
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,66 @@
|
|
1
|
+
## [0.2.06] - 2021-05-04
|
2
|
+
- Nearly passing the 'official' test suite, fixing non-compliant behavior, specialized exceptions for errors
|
3
|
+
|
4
|
+
### New
|
5
|
+
- Module `LoxFileTester` module that hosts methods that simplify the tests of `Lox` source file.
|
6
|
+
|
7
|
+
### Changed
|
8
|
+
- Folder `test_suite` vastly reorganized. Sub-folder `baseline` contains spec files testing the `Lox` files from official implementation
|
9
|
+
- Class `BackEnd::Engine` replaced most `StandardError` by `Loxxy::RuntimeError` exception.
|
10
|
+
- Class `BackEnd::Resolver` replaced most `StandardError` by `Loxxy::RuntimeError` exception.
|
11
|
+
- Method `Datatype::Number#/` now handles correctly expression like `0/0` (integer divide)
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
- `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`
|
15
|
+
- `FrontEnd::Scanner` now always treats expression like `-123` as the unary or binary minus operator applied to a positive number.
|
16
|
+
|
17
|
+
## [0.2.05] - 2021-04-26
|
18
|
+
- `Loxxy` now transforms for loops into while loops (desugaring), fix in Scanner class
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
- Method `Ast::ASTBuilder#reduce_for_stmt` converts 'for' loops into 'while' loops
|
22
|
+
- Method `Ast::ASTBuilder#reduce_for_control takes care of case for(expr1;;expr2) now test expression is set to true
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
- Method `FrontEnd::Scanner#next_token` keyword recognition was case insensitive
|
26
|
+
|
27
|
+
### Removed
|
28
|
+
- Method `Ast::Visitor#visitor_for_stmt`
|
29
|
+
- Method `BackEnd::Engine#after_for_stmt`
|
30
|
+
- Method `BackEnd::Resolver#before_for_stmt`
|
31
|
+
- Method `BackEnd::Resolver#after_for_stmt`
|
32
|
+
|
33
|
+
|
34
|
+
## [0.2.04] - 2021-04-25
|
35
|
+
- `Loxxy` passes the test suite for `for` statements
|
36
|
+
|
37
|
+
### Fixed
|
38
|
+
- Method `BackEnd::Engine#after_for_stmt` now a for(;;) executes the body once; a for without test will execute forever
|
39
|
+
- Method `BackEnd::Resolver#after_for_stmt now accepts nil test expression
|
40
|
+
|
41
|
+
## [0.2.03] - 2021-04-24
|
42
|
+
- Fixes for the set (field) expressions, `accept` methods for AST nodes are meta-programmed
|
43
|
+
|
44
|
+
### New
|
45
|
+
- Module `Ast::Visitee` provides the `define_accept` method that generate `accept` method with meta-programming
|
46
|
+
|
47
|
+
### Fixed
|
48
|
+
- Method `BackEnd::Engine#before_set_expr` methos method that ensure that the receiver is evaluated first, then the assigned value
|
49
|
+
- Method `BackEnd::Engine#after_set_expr` now pushes the value assigned to the field also onto the stack
|
50
|
+
- Class `BackEnd::Engine` a number of StnadardError exceptions are replaced by Loxxy::RuntimeError
|
51
|
+
|
52
|
+
|
53
|
+
## [0.2.02] - 2021-04-21
|
54
|
+
- Improvements in the scanner class (escape sequence for quotes and newlines), error messages closer to jlox.
|
55
|
+
|
56
|
+
### Changed
|
57
|
+
- File `loxxy` executable doesn't show a stack trace for scanner errors
|
58
|
+
- Class `ScannerError` is now a subclass of `Loxxy::Error`
|
59
|
+
- Class `Scanner` now returns a specific error message for unterminated strings
|
60
|
+
- Class `Scanner` error messages are closer to the ones from jlox
|
61
|
+
- Class `Scanner` supports now escape sequences \" for double quotes, \n for newlines
|
62
|
+
- File `README.md` Reshuffled some text
|
63
|
+
|
1
64
|
## [0.2.01] - 2021-04-18
|
2
65
|
- Minor improvements in CLI, starting re-documenting `README.md`.
|
3
66
|
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![Build status](https://ci.appveyor.com/api/projects/status/8e5p7dgjanm0qjkp?svg=true)](https://ci.appveyor.com/project/famished-tiger/loxxy)
|
4
4
|
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/famished-tiger/loxxy/blob/main/LICENSE.txt)
|
5
5
|
|
6
|
-
|
6
|
+
## What is loxxy?
|
7
7
|
A Ruby implementation of the [Lox programming language](https://craftinginterpreters.com/the-lox-language.html ),
|
8
8
|
a simple language defined in Bob Nystrom's excellent online book [Crafting Interpreters](https://craftinginterpreters.com/ ).
|
9
9
|
|
@@ -16,15 +16,34 @@ Although __Lox__ is fairly simple, it is far from being a toy language:
|
|
16
16
|
- Functions and closures
|
17
17
|
- Object-orientation (classes, methods, inheritance).
|
18
18
|
|
19
|
+
### Loxxy gem features
|
20
|
+
- Complete tree-walking interpreter including lexer, parser and resolver
|
21
|
+
- 100% pure Ruby with clean design (not a port from some other language)
|
22
|
+
- Minimal runtime dependency (Rley gem). Won't drag a bunch of gems...
|
23
|
+
- Ruby API for integrating a Lox interpreter with your code.
|
24
|
+
- A command-line interpreter `loxxy`
|
25
|
+
- Open for your language extensions...
|
26
|
+
|
19
27
|
## How to start in 1, 2, 3...?
|
20
28
|
... in less than 3 minutes...
|
21
29
|
|
22
30
|
### 1. Installing
|
23
|
-
|
31
|
+
__Loxxy__'s installation is pretty standard:
|
24
32
|
|
25
33
|
|
26
34
|
$ gem install loxxy
|
27
35
|
|
36
|
+
Alternatively, you can install `loxxy` with Bundler.
|
37
|
+
Add this line to your application's Gemfile:
|
38
|
+
|
39
|
+
gem 'loxxy'
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
|
43
|
+
$ bundle
|
44
|
+
|
45
|
+
|
46
|
+
|
28
47
|
### 2. Your first `Lox` program
|
29
48
|
Create a text file and enter the following lines:
|
30
49
|
```javascript
|
@@ -42,10 +61,11 @@ Lo and behold! The output device displays the famous greeting:
|
|
42
61
|
Hello, world.
|
43
62
|
|
44
63
|
|
45
|
-
Congrats! You ran your first `Lox` program
|
64
|
+
Congrats! You ran your first `Lox` program thanks __Loxxy__ gem.
|
65
|
+
For a less superficial encounter with the language jump to the next section.
|
46
66
|
|
47
|
-
|
48
|
-
Let's admit it, the hello world example was unimpressive.
|
67
|
+
## So you want something beefier?...
|
68
|
+
Let's admit it, the hello world example was unimpressive.
|
49
69
|
To a get a taste of `Lox` object-oriented capabilities, let's try another `Hello world` variant:
|
50
70
|
|
51
71
|
```javascript
|
@@ -172,12 +192,6 @@ Indeed, an open-source language that misses some features is an invitation for t
|
|
172
192
|
There are already a number of programming languages derived from `Lox`...
|
173
193
|
|
174
194
|
## Why `Loxxy`? What's in it for me?...
|
175
|
-
Features:
|
176
|
-
- Complete tree-walking interpreter including lexer, parser and resolver
|
177
|
-
- 100% pure Ruby with clean design (not a port from some other language)
|
178
|
-
- Ruby API for integrating a Lox interpreter with your code.
|
179
|
-
- Minimal runtime dependency (Rley gem). Won't drag a bunch of gems...
|
180
|
-
|
181
195
|
|
182
196
|
### Purpose of this project:
|
183
197
|
- To deliver an open source example of a programming language fully implemented in Ruby
|
data/bin/loxxy
CHANGED
@@ -17,11 +17,15 @@ class LoxxyRunner
|
|
17
17
|
return if file_names.nil? || file_names.empty?
|
18
18
|
|
19
19
|
lox = Loxxy::Interpreter.new
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
begin
|
21
|
+
file_names.each do |lox_file|
|
22
|
+
fname = validate_filename(lox_file)
|
23
|
+
next unless file_exist?(fname)
|
24
|
+
|
25
|
+
File.open(fname, 'r') { |f| lox.evaluate(f.read) }
|
26
|
+
end
|
27
|
+
rescue Loxxy::ScanError => e
|
28
|
+
$stderr.puts e.message
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
@@ -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
|