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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47ae4c0af1698de7187c530ec5feec9390a664ff681aae6c47a36e351bda229d
4
- data.tar.gz: ff309645b8e71608e6a3801d4a4be558b8e86d59d658af4ec2eb796989e88455
3
+ metadata.gz: 2bf956c6e2d6736535acd1e9b0cb29df6b55a8d9002be073cb70bbf753fb06c9
4
+ data.tar.gz: 1f635dc69e588f01406cd988bf98d12b9ea398f36e249113a37b089788ef21cb
5
5
  SHA512:
6
- metadata.gz: 73bea958f39a8cb97ed2e59c049ab58006845519a642d20e72cbdd554be60cb3b553f84dcdd64a36410796f83e87bb3239eee9933148b821b074916f4198a810
7
- data.tar.gz: a3235fd86a5c99c0ecf581be106e53d59a0643b3ac6299fbd0eccd0f5eacc5a15b63df3a22fb4edef8b30314fa0360432b017d9a2417668e365e2b9dd3f8b2b8
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 a subset of __Lox__ language.
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 expected from most general-purpose
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 was not aimed to be a language used in real-world applications.
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, nil, or, print, true
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
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'loxxy'
5
+
6
+ if ARGV[0]
7
+ lox = Loxxy::Interpreter.new
8
+ File.open(ARGV[0], 'r') do |f|
9
+ lox.evaluate(f.read)
10
+ end
11
+ end
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('comparisonTest_plus' => 'comparisonTest term')
290
- def reduce_comparison_t_plus_end(production, range, tokens, theChildren)
291
- reduce_binary_plus_end(production, range, tokens, theChildren)
292
- end
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('factor' => 'multiplicative_plus')
310
- def reduce_factor_multiplicative(production, range, tokens, theChildren)
311
- reduce_binary_operator(production, range, tokens, theChildren)
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('multiplicative_plus' => 'multiplicative_plus multOp unary')
315
- def reduce_multiplicative_plus_more(production, range, tokens, theChildren)
316
- reduce_binary_plus_more(production, range, tokens, theChildren)
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('multiplicative_plus' => 'multOp unary')
320
- def reduce_multiplicative_plus_end(production, range, tokens, theChildren)
321
- reduce_binary_plus_end(production, range, tokens, theChildren)
322
- end
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
- # rule('unary' => 'unaryOp unary')
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 aRoot [AST::LoxNode] the parse tree to visit.
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 aPrintStmt [AST::LOXVarStmt] the variable declaration node to visit
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 aPrintStmt [AST::LOXVarStmt] the variable declaration node to visit
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 aLiteralExpr [AST::LoxAssignExpr] the variable assignment node to visit.
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 aBinaryExpr [AST::LOXBinaryExpr] the logical expression node to visit
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 aLiteralExpr [AST::LoxVariableExpr] the variable reference node to visit.
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 aNonTerminalNode [Ast::BuiltinDattype] the built-in datatype value
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(_non_terminal_node)
196
+ def visit_nonterminal(aNonTerminalNode)
181
197
  # Loxxy interpreter encountered a CST node (Concrete Syntax Tree)
182
198
  # that it cannot handle.
183
- raise NotImplementedError, 'Loxxy cannot execute this code yet.'
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