loxxy 0.0.27 → 0.1.03
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 +64 -0
- data/README.md +56 -10
- data/bin/loxxy +11 -0
- data/lib/loxxy.rb +0 -2
- data/lib/loxxy/ast/all_lox_nodes.rb +2 -0
- data/lib/loxxy/ast/ast_builder.rb +56 -83
- data/lib/loxxy/ast/ast_visitor.rb +28 -10
- data/lib/loxxy/ast/lox_block_stmt.rb +5 -1
- data/lib/loxxy/ast/lox_call_expr.rb +25 -0
- data/lib/loxxy/ast/lox_for_stmt.rb +0 -1
- data/lib/loxxy/ast/lox_fun_stmt.rb +34 -0
- data/lib/loxxy/ast/lox_if_stmt.rb +3 -1
- data/lib/loxxy/back_end/binary_operator.rb +57 -0
- data/lib/loxxy/back_end/engine.rb +126 -5
- data/lib/loxxy/back_end/function.rb +44 -0
- data/lib/loxxy/back_end/unary_operator.rb +41 -0
- data/lib/loxxy/error.rb +9 -0
- data/lib/loxxy/front_end/grammar.rb +28 -28
- data/lib/loxxy/front_end/literal.rb +1 -1
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +2 -2
- data/spec/datatype/lx_string_spec.rb +2 -0
- data/spec/datatype/number_spec.rb +3 -1
- data/spec/front_end/scanner_spec.rb +2 -0
- data/spec/interpreter_spec.rb +45 -7
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bf956c6e2d6736535acd1e9b0cb29df6b55a8d9002be073cb70bbf753fb06c9
|
4
|
+
data.tar.gz: 1f635dc69e588f01406cd988bf98d12b9ea398f36e249113a37b089788ef21cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dce93451a9efc548df45683f5772a5d5509c25a57969465f3ff9f48f8b5adcc642b7bb92b25d43658869b5b62d3108796964226c35130cb1492335dc6eaf8fe1
|
7
|
+
data.tar.gz: 881dfd881db0d2ec3e56b91ad14bc6dd0e0b91ba3839fa1efe09c3636aac575856e3e8c4d4a64a55e913a757a4f1d275cc843734ceda3a23ef597591cb282f3f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,67 @@
|
|
1
|
+
## [0.1.03] - 2021-02-26
|
2
|
+
- Runtime argument chacking for arithmetic and comparison operators
|
3
|
+
|
4
|
+
### Added
|
5
|
+
- Test suite for arithmetic and comparison operators (in project repository)
|
6
|
+
- Class `BackEnd::UnaryOperator`: runtime argument validation
|
7
|
+
- Class `BackEnd::BinaryOperator`: runtime argument validation
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- File `console` renamed to `loxxy`. Very basic command-line interface.
|
11
|
+
- Custom exception classes
|
12
|
+
- File `README.md` updated list of supported `Lox` keywords.
|
13
|
+
|
14
|
+
|
15
|
+
## [0.1.02] - 2021-02-21
|
16
|
+
- Function definition and call documented in `README.md`
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
- File `README.md` updated description of function definition and function call.
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
- Method `BackEnd::Engine#after_print_stmt` now handles of empty stack or nil data.
|
23
|
+
- Method `BackEnd::Engine#after_call_expr` was pushing one spurious item onto data stack.
|
24
|
+
|
25
|
+
## [0.1.01] - 2021-02-20
|
26
|
+
### Fixed
|
27
|
+
- Fixed most offences for Rubocop.
|
28
|
+
|
29
|
+
|
30
|
+
## [0.1.00] - 2021-02-20
|
31
|
+
- Version number bumped, `Loxxy` supports function definitions
|
32
|
+
|
33
|
+
### Added
|
34
|
+
- Class `Ast::LoxFunStmt` a node that represents a function declaration
|
35
|
+
- Method `Ast::ASTBuilder#reduce_fun_decl`
|
36
|
+
- Method `Ast::ASTBuilder#reduce_function` creates a `LoxFunStmt` instance
|
37
|
+
- Method `Ast::ASTBuilder#reduce_parameters_plus_more` for dealing with function parameters
|
38
|
+
- Method `Ast::ASTBuilder#reduce_parameters_plus_end`
|
39
|
+
- Method `Ast::ASTVisitor#visit_fun_stmt` for visiting an `Ast::LoxFunStmt` node
|
40
|
+
- Method `Ast::LoxBlockStmt#empty?` returns true if the code block is empty
|
41
|
+
- Method `BackEnd::Engine#after_fun_stmt`
|
42
|
+
- Method `Backend::NativeFunction#call`
|
43
|
+
- Method `Backend::NativeFunction#to_str`
|
44
|
+
- Method `Backend::Function` implementation of a function object.
|
45
|
+
|
46
|
+
### Changed
|
47
|
+
- Method `BackEnd::Engine#after_call_expr`
|
48
|
+
|
49
|
+
### Fixed
|
50
|
+
- Fixed inconsistencies in documentation comments.
|
51
|
+
|
52
|
+
## [0.0.28] - 2021-02-15
|
53
|
+
- The interpreter implements function calls (to a native function).
|
54
|
+
|
55
|
+
### Added
|
56
|
+
- Class `Ast::LoxCallExpr` a node that represents a function call expression
|
57
|
+
- Method `Ast::ASTBuilder#reduce_call_expr`
|
58
|
+
- Method `Ast::ASTBuilder#reduce_refinement_plus_end`
|
59
|
+
- Method `Ast::ASTBuilder#reduce_call_arglist` creates a `LoxCallExpr` node
|
60
|
+
- Method `Ast::ASTBuilder#reduce_arguments_plus_more` builds the function argument array
|
61
|
+
- Method `Ast::ASTVisitor#visit_call_expr` for visiting an `Ast::LoxCallExpr` node
|
62
|
+
- Method `BackEnd::Engine#after_call_expr`implements the evaluation of a function call.
|
63
|
+
- Method `BackEnd::Engine#after_for_stmt` implements most of the `for` control flow
|
64
|
+
|
1
65
|
## [0.0.27] - 2021-01-24
|
2
66
|
- The interpreter implements `while` loops.
|
3
67
|
|
data/README.md
CHANGED
@@ -14,9 +14,12 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
|
|
14
14
|
|
15
15
|
### Current status
|
16
16
|
The project is still in inception and the interpreter is being implemented...
|
17
|
-
Currently it can execute
|
17
|
+
Currently it can execute all allowed __Lox__ expressions and statements except:
|
18
|
+
- Closures,
|
19
|
+
- Classes and objects.
|
20
|
+
|
21
|
+
These will be implemented soon.
|
18
22
|
|
19
|
-
But the __loxxy__ gem hosts also a parser class `RawPaser` that can parse, in principle, any valid Lox input.
|
20
23
|
|
21
24
|
## What's the fuss about Lox?
|
22
25
|
... Nothing...
|
@@ -32,11 +35,11 @@ Although __Lox__ is fairly simple, it is far from a toy language:
|
|
32
35
|
- Functions and closures
|
33
36
|
- Object-orientation (classes, methods, inheritance).
|
34
37
|
|
35
|
-
In other words, __Lox__ contains interesting features
|
38
|
+
In other words, __Lox__ contains interesting features found in most general-purpose
|
36
39
|
languages.
|
37
40
|
|
38
41
|
### What's missing in Lox?
|
39
|
-
__Lox__ was constrained by design and therefore
|
42
|
+
__Lox__ was constrained by design and was therefore not aimed to be a language used in real-world applications.
|
40
43
|
Here are some missing parts to make it a _practical_ language:
|
41
44
|
- Collections (arrays, maps, ...)
|
42
45
|
- Modules (importing stuff from other packages/files)
|
@@ -66,6 +69,23 @@ lox = Loxxy::Interpreter.new
|
|
66
69
|
lox.evaluate(lox_program) # Output: Hello, world!
|
67
70
|
```
|
68
71
|
|
72
|
+
## A function definition example
|
73
|
+
```ruby
|
74
|
+
require 'loxxy'
|
75
|
+
|
76
|
+
lox_program = <<LOX_END
|
77
|
+
fun add4(n) {
|
78
|
+
n + 4;
|
79
|
+
}
|
80
|
+
|
81
|
+
print add4(6); // Output: 10
|
82
|
+
LOX_END
|
83
|
+
|
84
|
+
lox = Loxxy::Interpreter.new
|
85
|
+
lox.evaluate(lox_program) # Output 10
|
86
|
+
```
|
87
|
+
|
88
|
+
|
69
89
|
## Retrieving the result from a Lox program
|
70
90
|
The __Loxxy__ interpreter returns the value of the last evaluated expression.
|
71
91
|
|
@@ -147,6 +167,7 @@ Here are the language features currently supported by the interpreter:
|
|
147
167
|
- [Print Statement](#print-statement)
|
148
168
|
- [While Statement](#while-statement)
|
149
169
|
- [Block Statement](#block-statement)
|
170
|
+
- [Function declaration](#func-statement)
|
150
171
|
|
151
172
|
### Comments
|
152
173
|
|
@@ -159,7 +180,8 @@ Loxxy supports single line C-style comments.
|
|
159
180
|
### Keywords
|
160
181
|
Loxxy implements the following __Lox__ reserved keywords:
|
161
182
|
```lang-none
|
162
|
-
and, false,
|
183
|
+
and, else, false, for, fun, if,
|
184
|
+
nil, or, print, true, var, while
|
163
185
|
```
|
164
186
|
|
165
187
|
### Datatypes
|
@@ -173,19 +195,21 @@ loxxy supports all the standard __Lox__ datatypes:
|
|
173
195
|
### Statements
|
174
196
|
|
175
197
|
Loxxy supports the following statements:
|
176
|
-
- [Expressions](#expressions)
|
198
|
+
- [Expressions](#expressions)
|
177
199
|
-[Arithmetic expressions](#arithmetic-expressions)
|
178
200
|
-[String concatenation](#string-concatenation)
|
179
201
|
-[Comparison expressions](#comparison-expressions)
|
180
202
|
-[Logical expressions](#logical-expressions)
|
181
203
|
-[Grouping expressions](#grouping-expressions)
|
182
|
-
-[Variable expressions and assignments](#variable-expressions)
|
183
|
-
|
204
|
+
-[Variable expressions and assignments](#variable-expressions)
|
205
|
+
-[Function call](#function-call)
|
206
|
+
|
184
207
|
-[Variable declarations](#var-statement)
|
185
208
|
-[If Statement](#if-statement)
|
186
209
|
-[Print Statement](#print-statement)
|
187
|
-
-[While Statement](#while-statement)
|
188
|
-
-[Block Statement](#block-statement)
|
210
|
+
-[While Statement](#while-statement)
|
211
|
+
-[Block Statement](#block-statement)
|
212
|
+
-[Function Declaration](#function-declaration)
|
189
213
|
|
190
214
|
#### Expressions
|
191
215
|
|
@@ -280,6 +304,15 @@ var iAmNil; // __Lox__ initializes variables to nil by default;
|
|
280
304
|
print iAmNil; // output: nil
|
281
305
|
```
|
282
306
|
|
307
|
+
#### Function call
|
308
|
+
``` javascript
|
309
|
+
// Calling a function without argument
|
310
|
+
print clock();
|
311
|
+
|
312
|
+
// Assumption: there exists a function `add` that takes two arguments
|
313
|
+
print add(2, 3);
|
314
|
+
```
|
315
|
+
|
283
316
|
#### For statement
|
284
317
|
|
285
318
|
Similar to the `for` statement in `C` language
|
@@ -358,6 +391,19 @@ var a = "outer";
|
|
358
391
|
print a; // output: outer
|
359
392
|
```
|
360
393
|
|
394
|
+
#### Function Declaration
|
395
|
+
The keyword `fun` is used to begin a function declaration.
|
396
|
+
In __Lox__ a function has a name and a body (which may be empty).
|
397
|
+
|
398
|
+
``` javascript
|
399
|
+
fun add4(n) // `add4` will be the name of the function
|
400
|
+
{
|
401
|
+
n + 4;
|
402
|
+
}
|
403
|
+
|
404
|
+
print add4(6); // output: 10
|
405
|
+
```
|
406
|
+
|
361
407
|
## Installation
|
362
408
|
|
363
409
|
Add this line to your application's Gemfile:
|
data/bin/loxxy
ADDED
data/lib/loxxy.rb
CHANGED
@@ -6,8 +6,6 @@ require_relative 'loxxy/front_end/raw_parser'
|
|
6
6
|
|
7
7
|
# Namespace for all classes and constants of __loxxy__ gem.
|
8
8
|
module Loxxy
|
9
|
-
class Error < StandardError; end
|
10
|
-
|
11
9
|
# Shorthand method. Returns the sole object that represents
|
12
10
|
# a Lox false literal.
|
13
11
|
# @return [Loxxy::Datatype::False]
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'lox_fun_stmt'
|
3
4
|
require_relative 'lox_variable_expr'
|
4
5
|
require_relative 'lox_literal_expr'
|
5
6
|
require_relative 'lox_noop_expr'
|
7
|
+
require_relative 'lox_call_expr'
|
6
8
|
require_relative 'lox_grouping_expr'
|
7
9
|
require_relative 'lox_unary_expr'
|
8
10
|
require_relative 'lox_binary_expr'
|
@@ -163,6 +163,11 @@ module Loxxy
|
|
163
163
|
[theChildren[0]]
|
164
164
|
end
|
165
165
|
|
166
|
+
# rule('funDecl' => 'FUN function')
|
167
|
+
def reduce_fun_decl(_production, _range, _tokens, theChildren)
|
168
|
+
theChildren[1]
|
169
|
+
end
|
170
|
+
|
166
171
|
# rule('exprStmt' => 'expression SEMICOLON')
|
167
172
|
def reduce_exprStmt(_production, range, tokens, theChildren)
|
168
173
|
return_first_child(range, tokens, theChildren) # Discard the semicolon
|
@@ -227,105 +232,46 @@ module Loxxy
|
|
227
232
|
Ast::LoxBlockStmt.new(tokens[1].position, decls)
|
228
233
|
end
|
229
234
|
|
235
|
+
# rule('block' => 'LEFT_BRACE RIGHT_BRACE').as 'block_empty'
|
236
|
+
def reduce_block_empty(_production, _range, tokens, _children)
|
237
|
+
Ast::LoxBlockStmt.new(tokens[0].position, nil)
|
238
|
+
end
|
239
|
+
|
230
240
|
# rule('assignment' => 'owner_opt IDENTIFIER EQUAL assignment')
|
231
241
|
def reduce_assign_expr(_production, _range, tokens, theChildren)
|
232
242
|
var_name = theChildren[1].token.lexeme.dup
|
233
243
|
Ast::LoxAssignExpr.new(tokens[1].position, var_name, theChildren[3])
|
234
244
|
end
|
235
245
|
|
236
|
-
# rule('logic_or' => 'logic_and disjunct_plus')
|
237
|
-
def reduce_logic_or_plus(production, range, tokens, theChildren)
|
238
|
-
reduce_logical_expr(production, range, tokens, theChildren)
|
239
|
-
end
|
240
|
-
|
241
|
-
# rule('disjunct_plus' => 'disjunct_plus OR logic_and')
|
242
|
-
def reduce_logic_or_plus_more(production, range, tokens, theChildren)
|
243
|
-
reduce_binary_plus_more(production, range, tokens, theChildren)
|
244
|
-
end
|
245
|
-
|
246
|
-
# rule('disjunct_plus' => 'OR logic_and')
|
247
|
-
def reduce_logic_or_plus_end(production, range, tokens, theChildren)
|
248
|
-
reduce_binary_plus_end(production, range, tokens, theChildren)
|
249
|
-
end
|
250
|
-
|
251
|
-
# rule('logic_and' => 'equality conjunct_plus')
|
252
|
-
def reduce_logic_and_plus(production, range, tokens, theChildren)
|
253
|
-
reduce_logical_expr(production, range, tokens, theChildren)
|
254
|
-
end
|
255
|
-
|
256
|
-
# rule('conjunct_plus' => 'conjunct_plus AND equality')
|
257
|
-
def reduce_logic_and_plus_more(production, range, tokens, theChildren)
|
258
|
-
reduce_binary_plus_more(production, range, tokens, theChildren)
|
259
|
-
end
|
260
|
-
|
261
|
-
# rule('conjunct_plus' => 'AND equality')
|
262
|
-
def reduce_logic_and_plus_end(production, range, tokens, theChildren)
|
263
|
-
reduce_binary_plus_end(production, range, tokens, theChildren)
|
264
|
-
end
|
265
|
-
|
266
|
-
# rule('equality' => 'comparison equalityTest_plus')
|
267
|
-
def reduce_equality_plus(production, range, tokens, theChildren)
|
268
|
-
reduce_binary_operator(production, range, tokens, theChildren)
|
269
|
-
end
|
270
|
-
|
271
|
-
# rule('equalityTest_plus' => 'equalityTest_plus equalityTest comparison')
|
272
|
-
def reduce_equality_t_plus_more(production, range, tokens, theChildren)
|
273
|
-
reduce_binary_plus_more(production, range, tokens, theChildren)
|
274
|
-
end
|
275
|
-
|
276
|
-
# rule('equalityTest_star' => 'equalityTest comparison')
|
277
|
-
def reduce_equality_t_plus_end(production, range, tokens, theChildren)
|
278
|
-
reduce_binary_plus_end(production, range, tokens, theChildren)
|
279
|
-
end
|
280
|
-
|
281
|
-
# rule('comparison' => 'term comparisonTest_plus')
|
282
|
-
def reduce_comparison_plus(production, range, tokens, theChildren)
|
283
|
-
reduce_binary_operator(production, range, tokens, theChildren)
|
284
|
-
end
|
285
|
-
|
286
246
|
# rule('comparisonTest_plus' => 'comparisonTest_plus comparisonTest term').as 'comparison_t_plus_more'
|
287
247
|
# TODO: is it meaningful to implement this rule?
|
288
248
|
|
289
|
-
# rule('
|
290
|
-
def
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
# rule('term' => 'factor additive_plus')
|
295
|
-
def reduce_term_additive(production, range, tokens, theChildren)
|
296
|
-
reduce_binary_operator(production, range, tokens, theChildren)
|
297
|
-
end
|
298
|
-
|
299
|
-
# rule('additive_star' => 'additive_star additionOp factor').as 'additionOp_expr'
|
300
|
-
def reduce_additive_plus_more(production, range, tokens, theChildren)
|
301
|
-
reduce_binary_plus_more(production, range, tokens, theChildren)
|
302
|
-
end
|
303
|
-
|
304
|
-
# rule('additive_plus' => 'additionOp factor')
|
305
|
-
def reduce_additive_plus_end(production, range, tokens, theChildren)
|
306
|
-
reduce_binary_plus_end(production, range, tokens, theChildren)
|
249
|
+
# rule('unary' => 'unaryOp unary')
|
250
|
+
def reduce_unary_expr(_production, _range, tokens, theChildren)
|
251
|
+
operator = Name2unary[theChildren[0].symbol.name].to_sym
|
252
|
+
operand = theChildren[1]
|
253
|
+
LoxUnaryExpr.new(tokens[0].position, operator, operand)
|
307
254
|
end
|
308
255
|
|
309
|
-
# rule('
|
310
|
-
def
|
311
|
-
|
256
|
+
# rule('call' => 'primary refinement_plus').as 'call_expr'
|
257
|
+
def reduce_call_expr(_production, _range, _tokens, theChildren)
|
258
|
+
theChildren[1].callee = theChildren[0]
|
259
|
+
theChildren[1]
|
312
260
|
end
|
313
261
|
|
314
|
-
# rule('
|
315
|
-
def
|
316
|
-
|
262
|
+
# rule('refinement_plus' => 'refinement').
|
263
|
+
def reduce_refinement_plus_end(_production, _range, _tokens, theChildren)
|
264
|
+
theChildren[0]
|
317
265
|
end
|
318
266
|
|
319
|
-
# rule('
|
320
|
-
def
|
321
|
-
|
322
|
-
|
267
|
+
# rule('refinement' => 'LEFT_PAREN arguments_opt RIGHT_PAREN')
|
268
|
+
def reduce_call_arglist(_production, _range, tokens, theChildren)
|
269
|
+
args = theChildren[1] || []
|
270
|
+
if args.size > 255
|
271
|
+
raise StandardError, "Can't have more than 255 arguments."
|
272
|
+
end
|
323
273
|
|
324
|
-
|
325
|
-
def reduce_unary_expr(_production, _range, tokens, theChildren)
|
326
|
-
operator = Name2unary[theChildren[0].symbol.name].to_sym
|
327
|
-
operand = theChildren[1]
|
328
|
-
LoxUnaryExpr.new(tokens[0].position, operator, operand)
|
274
|
+
LoxCallExpr.new(tokens[0].position, args)
|
329
275
|
end
|
330
276
|
|
331
277
|
# rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
|
@@ -347,6 +293,33 @@ module Loxxy
|
|
347
293
|
var_name = theChildren[0].token.lexeme
|
348
294
|
LoxVariableExpr.new(tokens[0].position, var_name)
|
349
295
|
end
|
296
|
+
|
297
|
+
# rule('function' => 'IDENTIFIER LEFT_PAREN params_opt RIGHT_PAREN block').as 'function'
|
298
|
+
def reduce_function(_production, _range, _tokens, theChildren)
|
299
|
+
first_child = theChildren.first
|
300
|
+
pos = first_child.token.position
|
301
|
+
LoxFunStmt.new(pos, first_child.token.lexeme, theChildren[2], theChildren[4])
|
302
|
+
end
|
303
|
+
|
304
|
+
# rule('parameters' => 'parameters COMMA IDENTIFIER')
|
305
|
+
def reduce_parameters_plus_more(_production, _range, _tokens, theChildren)
|
306
|
+
theChildren[0] << theChildren[2].token.lexeme
|
307
|
+
end
|
308
|
+
|
309
|
+
# rule('parameters' => 'IDENTIFIER')
|
310
|
+
def reduce_parameters_plus_end(_production, _range, _tokens, theChildren)
|
311
|
+
[theChildren[0].token.lexeme]
|
312
|
+
end
|
313
|
+
|
314
|
+
# rule('arguments' => 'arguments COMMA expression')
|
315
|
+
def reduce_arguments_plus_more(_production, _range, _tokens, theChildren)
|
316
|
+
theChildren[0] << theChildren[2]
|
317
|
+
end
|
318
|
+
|
319
|
+
# rule('arguments' => 'expression')
|
320
|
+
def reduce_arguments_plus_end(_production, _range, _tokens, theChildren)
|
321
|
+
theChildren
|
322
|
+
end
|
350
323
|
end # class
|
351
324
|
end # module
|
352
325
|
end # module
|
@@ -12,7 +12,7 @@ module Loxxy
|
|
12
12
|
# attr_reader(:runtime)
|
13
13
|
|
14
14
|
# Build a visitor for the given top.
|
15
|
-
# @param
|
15
|
+
# @param aTop [AST::LoxNode] the parse tree to visit.
|
16
16
|
def initialize(aTop)
|
17
17
|
raise StandardError if aTop.nil?
|
18
18
|
|
@@ -52,7 +52,7 @@ module Loxxy
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# Visit event. The visitor is about to visit a variable declaration statement.
|
55
|
-
# @param
|
55
|
+
# @param aSeqDecls [AST::LOXSeqDecl] the variable declaration node to visit
|
56
56
|
def visit_seq_decl(aSeqDecls)
|
57
57
|
broadcast(:before_seq_decl, aSeqDecls)
|
58
58
|
traverse_subnodes(aSeqDecls)
|
@@ -60,7 +60,7 @@ module Loxxy
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# Visit event. The visitor is about to visit a variable declaration statement.
|
63
|
-
# @param
|
63
|
+
# @param aVarStmt [AST::LOXVarStmt] the variable declaration node to visit
|
64
64
|
def visit_var_stmt(aVarStmt)
|
65
65
|
broadcast(:before_var_stmt, aVarStmt)
|
66
66
|
traverse_subnodes(aVarStmt)
|
@@ -103,12 +103,12 @@ module Loxxy
|
|
103
103
|
# @param aBlockStmt [AST::LOXBlockStmt] the print statement node to visit
|
104
104
|
def visit_block_stmt(aBlockStmt)
|
105
105
|
broadcast(:before_block_stmt, aBlockStmt)
|
106
|
-
traverse_subnodes(aBlockStmt)
|
106
|
+
traverse_subnodes(aBlockStmt) unless aBlockStmt.empty?
|
107
107
|
broadcast(:after_block_stmt, aBlockStmt)
|
108
108
|
end
|
109
109
|
|
110
110
|
# Visit event. The visitor is visiting an assignment node
|
111
|
-
# @param
|
111
|
+
# @param anAssignExpr [AST::LoxAssignExpr] the variable assignment node to visit.
|
112
112
|
def visit_assign_expr(anAssignExpr)
|
113
113
|
broadcast(:before_assign_expr, anAssignExpr)
|
114
114
|
traverse_subnodes(anAssignExpr)
|
@@ -118,7 +118,7 @@ module Loxxy
|
|
118
118
|
# Visit event. The visitor is about to visit a logical expression.
|
119
119
|
# Since logical expressions may take shorcuts by not evaluating all their
|
120
120
|
# sub-expressiosns, they are responsible for visiting or not their children.
|
121
|
-
# @param
|
121
|
+
# @param aLogicalExpr [AST::LOXLogicalExpr] the logical expression node to visit
|
122
122
|
def visit_logical_expr(aLogicalExpr)
|
123
123
|
broadcast(:before_logical_expr, aLogicalExpr)
|
124
124
|
|
@@ -145,6 +145,14 @@ module Loxxy
|
|
145
145
|
broadcast(:after_unary_expr, anUnaryExpr)
|
146
146
|
end
|
147
147
|
|
148
|
+
# Visit event. The visitor is about to visit a call expression.
|
149
|
+
# @param aCallExpr [AST::LoxCallExpr] call expression to visit
|
150
|
+
def visit_call_expr(aCallExpr)
|
151
|
+
broadcast(:before_call_expr, aCallExpr)
|
152
|
+
traverse_subnodes(aCallExpr)
|
153
|
+
broadcast(:after_call_expr, aCallExpr, self)
|
154
|
+
end
|
155
|
+
|
148
156
|
# Visit event. The visitor is about to visit a grouping expression.
|
149
157
|
# @param aGroupingExpr [AST::LoxGroupingExpr] grouping expression to visit
|
150
158
|
def visit_grouping_expr(aGroupingExpr)
|
@@ -162,25 +170,35 @@ module Loxxy
|
|
162
170
|
end
|
163
171
|
|
164
172
|
# Visit event. The visitor is visiting a variable usage node
|
165
|
-
# @param
|
173
|
+
# @param aVariableExpr [AST::LoxVariableExpr] the variable reference node to visit.
|
166
174
|
def visit_variable_expr(aVariableExpr)
|
167
175
|
broadcast(:before_variable_expr, aVariableExpr)
|
168
176
|
broadcast(:after_variable_expr, aVariableExpr, self)
|
169
177
|
end
|
170
178
|
|
171
179
|
# Visit event. The visitor is about to visit the given terminal datatype value.
|
172
|
-
# @param
|
180
|
+
# @param aValue [Ast::BuiltinDattype] the built-in datatype value
|
173
181
|
def visit_builtin(aValue)
|
174
182
|
broadcast(:before_visit_builtin, aValue)
|
175
183
|
broadcast(:after_visit_builtin, aValue)
|
176
184
|
end
|
177
185
|
|
186
|
+
# Visit event. The visitor is about to visit a function statement node.
|
187
|
+
# @param aFunStmt [AST::LoxFunStmt] function declaration to visit
|
188
|
+
def visit_fun_stmt(aFunStmt)
|
189
|
+
broadcast(:before_fun_stmt, aFunStmt)
|
190
|
+
traverse_subnodes(aFunStmt)
|
191
|
+
broadcast(:after_fun_stmt, aFunStmt, self)
|
192
|
+
end
|
193
|
+
|
178
194
|
# Visit event. The visitor is about to visit the given non terminal node.
|
179
195
|
# @param aNonTerminalNode [Rley::PTree::NonTerminalNode] the node to visit.
|
180
|
-
def visit_nonterminal(
|
196
|
+
def visit_nonterminal(aNonTerminalNode)
|
181
197
|
# Loxxy interpreter encountered a CST node (Concrete Syntax Tree)
|
182
198
|
# that it cannot handle.
|
183
|
-
|
199
|
+
symb = aNonTerminalNode.symbol.name
|
200
|
+
msg = "Loxxy cannot execute this code yet for non-terminal symbol '#{symb}'."
|
201
|
+
raise NotImplementedError, msg
|
184
202
|
end
|
185
203
|
|
186
204
|
private
|