loxxy 0.0.19 → 0.0.24

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: eced55bddfd7918cbc7aea8eff5f7ecd37aa88baa6e5a6f7350f5bd7606e99af
4
- data.tar.gz: f9b8104a0f3a273466ff568a014e345437f4c568621828de8da44961fb52f0e5
3
+ metadata.gz: 6085bf18afb919e5ef4d327162470c9d5ca95dde67e00dce78bb26abd6563dec
4
+ data.tar.gz: f1c7732a34b6df2721c20d82404c6ce83bdc8a75b695e4bbe13c51f62d9ac371
5
5
  SHA512:
6
- metadata.gz: d5b23defe380228bda4e32d9cb94909767fdc42242111f00be214bfbead6323a5e6acda0d78dcaf4e1c2e1fa7d13cd0363661af959a62b093bfcc50c34c290a0
7
- data.tar.gz: 96a6a77824cd97b248ad6a78d66d4757c81549fa199021f446883d690f2702dbf4d9879950505d9aa54f45376bd7e6204be8b054e27b43a5576aca744be40047
6
+ metadata.gz: 7546a14b935700e5050411a7805c2b2d00ccfc99160e3241b512289a6cc1762df2f39b7c9845c6ffe7fb95f1412865ef373f5308c9cf333fd72e2025a4a17ed8
7
+ data.tar.gz: 3675956929831e52963759862e8f9d40e5ebd3df471dee87d82784c2d1230ce6057882368042c907741be1038d300b7c83c27ed4bb8d979f5efa2ac79eaa3b1a
@@ -1,16 +1,77 @@
1
- ## [0.0.18] - 2021-01-14
1
+ ## [0.0.24] - 2021-01-20
2
+ - The interpreter implements the assignment of variables.
3
+
4
+ ### Added
5
+ - Class `Ast::LoxAssignExpr` a node that represents the assignment of a value to a variable
6
+ - Method `Ast::ASTBuilder#reduce_assign_expr` creates an `Ast::LoxAssignExpr` node
7
+ - Method `Ast::ASTVisitor#visit_assign_expr` for visiting an `Ast::LoxAssignExpr` node
8
+ - Method `BackEnd::Engine#after_assign_expr` implementation of the assignment
9
+ - Method `BackEnd::Variable#assign` to assign a value to a variable
10
+
11
+ ## [0.0.23] - 2021-01-20
12
+ - Fix for variables without explicit initialization.
13
+
14
+ ### Added
15
+ - Method `Ast::ASTVisitor#visit_builtin` for visiting `Datatype::BuiltinDatatype` value.
16
+ - Method `BackEnd::Engine#before_visit_builtin` push the data value onto the stack.
17
+
18
+ ### Fixed
19
+ - Method `Ast::LoxVarStmt#initialize`: in case no explicit value provided then use `Datatype::Nil.instance`instead of Ruby `nil`
20
+
21
+ ## [0.0.22] - 2021-01-17
22
+ - The interpreter can retrieve the value of a variable.
23
+
24
+ ### Added
25
+ - Method `Ast::ASTBuilder#declaration_plus_more` and `Ast::ASTBuilder#declaration_plus_end` to allow multiple expressions/statements
26
+ - Method `Ast::ASTBuilder#reduce_var_expression` creates an `Ast::LoxVariableExpr` node
27
+ - Method `Ast::ASTVisitor#visit_var_expr` for visiting `Ast::LoxVariableExpr` nodes
28
+ - Class `Ast::LoxSeqDecl` a node that represents a sequence of declarations/statements
29
+ - Class `Ast::LoxVarExpr` a node that represents a variable occurrence in an expression
30
+ - Method `Engine::after_variable_expr`: retrieve the value of variable with given name
31
+
32
+ ### Changed
33
+ - Method `Ast::ASTBuilder#reduce_lox_program` to support multiple statements/declarations
34
+ - File `README.md` updated.
35
+
36
+ ## [0.0.21] - 2021-01-16
37
+ - The interpreter supports the declaration global variables.
38
+
39
+ ### Added
40
+ - Class `BackEnd::Entry`, mixin module for objects put in the symbol table
41
+ - Class `BackEnd::Environment` that keeps track of variables in a given context.
42
+ - Class `BackEnd::SymbolTable` that keeps track of environments.
43
+ - Class `BackEnd::Variable` internal representation of a `Lox` variable
44
+ - Method `Ast::ASTBuilder#reduce_var_declaration` and `Ast::ASTBuilder#reduce_var_declaration`
45
+ - Method `Ast::ASTVisitor#visit_var_stmt` for visiting `LoxVarStmt` nodes
46
+ - Attribute `Engine::symbol_table`for keeping track of variables
47
+ - Method `Engine::after_var_stmt` for the implementation of variable declarations
48
+
49
+ ## [0.0.20] - 2021-01-15
50
+ - The interpreter supports the `if` ... `else` statement.
51
+
52
+ ### Added
53
+ - Class `Ast::LoxItStmt`, AST node specific for `if` `else` statements
54
+ - Method `Ast::ASTBuilder#reduce_if_stmt` as semantic action for if ... else
55
+ - Method `Ast::ASTVisitor#visit_if_stmt` for visiting `LoxIfStmt` nodes
56
+ - Method `Engine::after_if_stmt` implementation of the control flow
57
+
58
+ ## [0.0.19] - 2021-01-14
2
59
  - The interpreter supports expressions between parentheses (grouping).
3
60
 
4
- ## Added
61
+ ### Added
5
62
  - Class `Ast::LoxLogicalExpr`
6
63
  - Method `Ast::ASTBuilder#reduce_grouping_expr` as semantic action for grouping expression
7
64
  - Method `Ast::ASTVisitor#visit_grouping_expr` for visiting grouping expressions
8
65
  - Method `Engine::after_grouping_expr`for the evaluation of grouping expressions
9
66
 
67
+ ### Changed
68
+ - File `grammar.rb` rules for if ... else were given names in order to activate semantic actions.
69
+ - File `README.md` updated with little `if ... else` documentation.
70
+
10
71
  ## [0.0.18] - 2021-01-13
11
72
  - The interpreter can evaluate `and`, `or`expressions.
12
73
 
13
- ## Added
74
+ ### Added
14
75
  - Class `Ast::LoxLogicalExpr`
15
76
  - Method `Ast::ASTBuilder#reduce_logical_expr` for the semantic action require for `and`, `or`
16
77
  - Method `Ast::ASTVisitor#visit_logical_expr` for visiting logical expressions
@@ -20,7 +81,7 @@
20
81
  - The interpreter can evaluate all arithmetic and comparison operations.
21
82
  - It implements `==`, `!=` and the unary operations `!`, `-`
22
83
 
23
- ## Added
84
+ ### Added
24
85
  - Class `Ast::LoxUnaryExpr`
25
86
  - Method `Ast::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
26
87
  - Method `Ast::ASTVisitor#visit_unnary_expr` for visiting unary expressions
@@ -28,14 +89,14 @@
28
89
  - In class `Datatype::BuiltinDatatype` the methods `falsey?`, `truthy?`, `!`, `!=`
29
90
  - In class `Datatype::Number`the methods `<`, `<=`, ´>´, `>=` and `-@`
30
91
 
31
- ## Changed
92
+ ### Changed
32
93
  - File `README.md` updated.
33
94
 
34
95
  ## [0.0.16] - 2021-01-11
35
96
  - The interpreter can evaluate product and division of two numbers.
36
97
  - It also implements equality `==` and inequality `!=` operators
37
98
 
38
- ## Added
99
+ ### Added
39
100
  - Method `Datatype::False#==` for equality testing
40
101
  - Method `Datatype::False#!=` for inequality testing
41
102
  - Method `Datatype::LXString#==` for equality testing
@@ -49,17 +110,17 @@
49
110
  - Method `Datatype::True#==` for equality testing
50
111
  - Method `Datatype::True#!=` for inequality testing
51
112
 
52
- ## Changed
113
+ ### Changed
53
114
  - Method `BackEnd::Engine#after_binary_expr` to allow `*`, `/`, `==`, `!=` operators
54
115
  - File `README.md` updated for the newly implemented operators
55
116
 
56
117
  ## [0.0.15] - 2021-01-11
57
118
  - The interpreter can evaluate substraction between two numbers.
58
119
 
59
- ## Added
120
+ ### Added
60
121
  - Method `Datatype::Number#-` implmenting the subtraction operation
61
122
 
62
- ## Changed
123
+ ### Changed
63
124
  - File `README.md` minor editorial changes.
64
125
  - File `lx_string_spec.rb` Added test for string concatentation
65
126
  - File `number_spec.rb` Added tests for addition and subtraction operations
@@ -68,7 +129,7 @@
68
129
  ## [0.0.14] - 2021-01-10
69
130
  - The interpreter can evaluate addition of numbers and string concatenation
70
131
 
71
- ## Added
132
+ ### Added
72
133
  - Method `Ast::ASTVisitor#visit_binary_expr` for visiting binary expressions
73
134
  - Method `Ast::LoxBinaryExpr#accept` for visitor pattern
74
135
  - Method `BackEnd::Engine#after_binary_expr` to trigger execution of binary operator
@@ -76,79 +137,79 @@
76
137
  - Method `Datatype::LXString#+` implementation of the string concatenation
77
138
  - Method `Datatype::Number#+` implementation of the addition of numbers
78
139
 
79
- ## Changed
140
+ ### Changed
80
141
  - File `interpreter_spec.rb` Added tests for addition operation and string concatenation
81
142
 
82
143
 
83
144
  ## [0.0.13] - 2021-01-10
84
145
  - The interpreter can evaluate directly simple literals.
85
146
 
86
- ## Changed
147
+ ### Changed
87
148
  - Class `AST::ASTBuilder` added `reduce_exprStmt` to support the evaluation of literals.
88
149
  - File `README.md` added one more example.
89
150
  - File `parser_spec.rb` Updated the tests to reflect the change in the AST.
90
151
  - File `interpreter_spec.rb` Added a test for literal expression.
91
152
 
92
- ## Fixed
153
+ ### Fixed
93
154
  - File `loxxy.rb`: shorthand method `lox_true` referenced the ... false object (oops).
94
155
 
95
156
  ## [0.0.12] - 2021-01-09
96
157
  - Initial interpreter capable of evaluating a tiny subset of Lox language.
97
158
 
98
- ## Added
159
+ ### Added
99
160
  - Class `AST::LoxNoopExpr`
100
161
  - Class `AST::LoxPrintStmt`
101
162
  - Class `BackEnd::Engine` implementation of the print statement logic
102
163
  - Class `Interpreter`
103
164
 
104
- ## Changed
165
+ ### Changed
105
166
  - Class `Ast::ASTVisitor` Added visit method
106
167
  - File `README.md` added Hello world example.
107
168
 
108
169
  ## [0.0.11] - 2021-01-08
109
170
  - AST node generation for logical expression (and, or).
110
171
 
111
- ## Changed
172
+ ### Changed
112
173
  - Class `AST::ASTBuilder` added `reduce_` methods for logical operations.
113
174
  - File `grammar.rb`added name to logical expression rules
114
175
  - File `README.md` added gem version and license badges, expanded roadmap section.
115
176
 
116
- ## Fixed
177
+ ### Fixed
117
178
  - File `grammar.rb`: a rule had incomplete non-terminal name `conjunct_` in its lhs.
118
179
 
119
180
 
120
181
  ## [0.0.10] - 2021-01-08
121
182
  - AST node generation for equality expression.
122
183
 
123
- ## Changed
184
+ ### Changed
124
185
  - Class `AST::ASTBuilder` refactoring and added `reduce_` methods for equality operations.
125
186
  - File `grammar.rb`added name to equality rules
126
187
  - File `README.md` added gem version and license badges, expanded roadmap section.
127
188
 
128
- ## Fixed
189
+ ### Fixed
129
190
  - File `grammar.rb`: a rule had still the discarded non-terminal `equalityTest_star` in its lhs.
130
191
 
131
192
  ## [0.0.9] - 2021-01-07
132
193
  - AST node generation for comparison expression.
133
194
 
134
- ## Changed
195
+ ### Changed
135
196
  - Class `AST::ASTBuilder` added `reduce_` methods for comparison operations.
136
197
  - File `grammar.rb`added name to comparison rules
137
198
 
138
199
  ## [0.0.8] - 2021-01-07
139
200
  - AST node generation for arithmetic operations of number literals.
140
201
 
141
- ## Changed
202
+ ### Changed
142
203
  - Class `AST::ASTBuilder` added `reduce_` methods for arithmetic operations.
143
204
  - File `grammar.rb`added name to arithmetic rules
144
205
 
145
- ## Fixed
206
+ ### Fixed
146
207
  - File `grammar.rb`: second rule for `factor` had a missing member in rhs.
147
208
 
148
209
  ## [0.0.7] - 2021-01-06
149
210
  - Lox grammar reworked, initial AST classes created.
150
211
 
151
- ## Added
212
+ ### Added
152
213
  - Class `Parser` this one generates AST's (Abstract Syntax Tree)
153
214
  - Class `AST::ASTVisitor` draft initial implementation.
154
215
  - Class `AST::BinaryExpr` draft initial implementation.
@@ -156,7 +217,7 @@
156
217
  - Class `AST::LiteralExpr` draft initial implementation.
157
218
  - Class `AST::LoxNode` draft initial implementation.
158
219
 
159
- ## Changed
220
+ ### Changed
160
221
  - File `spec_helper.rb`: removed Bundler dependency
161
222
  - Class `AST::ASTBuilder` added initial `reduce_` methods.
162
223
  - File `README.md` Removed example with AST generation since this is in flux.
@@ -164,31 +225,31 @@
164
225
  ## [0.0.6] - 2021-01-03
165
226
  - First iteration of a parser with AST generation.
166
227
 
167
- ## Added
228
+ ### Added
168
229
  - Class `Parser` this one generates AST's (Abstract Syntax Tree)
169
230
  - Class `AST::ASTBuilder` default code to generate an AST.
170
231
 
171
- ## Changed
232
+ ### Changed
172
233
  - File `spec_helper.rb`: removed Bundler dependency
173
234
  - File `README.md` Added example with AST visualization.
174
235
 
175
- ## Fixed
236
+ ### Fixed
176
237
  - File `grammar.rb` ensure that the constant `Grammar` is created once only.
177
238
 
178
239
  ## [0.0.5] - 2021-01-02
179
240
  - Improved example in `README.md`, code re-styling to please `Rubocop` 1.7
180
241
 
181
- ## Changed
242
+ ### Changed
182
243
  - Code re-styling to please `Rubocop` 1.7
183
244
  - File `README.md` Improved example with better parse tree visualization.
184
245
 
185
246
  ## [0.0.4] - 2021-01-01
186
247
  - A first parser implementation able to parse Lox source code.
187
248
 
188
- ## Added
249
+ ### Added
189
250
  - Method `LXString::==` equality operator.
190
251
 
191
- ## Changed
252
+ ### Changed
192
253
  - class `Parser` renamed to `RawParser`
193
254
  - File `README.md` Added an example showing the use of `RawParser` class.
194
255
 
data/README.md CHANGED
@@ -8,7 +8,7 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
8
8
 
9
9
  ### Purpose of this project:
10
10
  - To deliver an open source example of a programming language fully implemented in Ruby
11
- (from the scanner, parser, an interpreter).
11
+ (from the scanner and parser to an interpreter).
12
12
  - The implementation should be mature enough to run [LoxLox](https://github.com/benhoyt/loxlox),
13
13
  a Lox interpreter written in Lox.
14
14
 
@@ -141,7 +141,9 @@ Here are the language features currently supported by the interpreter:
141
141
  - [Datatypes](#datatypes)
142
142
  - [Statements](#statements)
143
143
  -[Expressions](#expressions)
144
- -[Print Statement](#print-statement)
144
+ - [Variable declarations](#var-statement)
145
+ - [If Statement](#if-statement)
146
+ - [Print Statement](#print-statement)
145
147
 
146
148
  ### Comments
147
149
 
@@ -168,12 +170,16 @@ loxxy supports all the standard __Lox__ datatypes:
168
170
  ### Statements
169
171
 
170
172
  Loxxy supports the following statements:
171
- -[Expressions](#expressions)
173
+ - [Expressions](#expressions)
172
174
  -[Arithmetic expressions](#arithmetic-expressions)
173
175
  -[String concatenation](#string-concatenation)
174
176
  -[Comparison expressions](#comparison-expressions)
175
177
  -[Logical expressions](#logical-expressions)
176
178
  -[Grouping expressions](#grouping-expressions)
179
+ -[Variable expressions and assignments](#variable-expressions)
180
+
181
+ -[Variable declarations](#var-statement)
182
+ -[If Statement](#if-statement)
177
183
  -[Print Statement](#print-statement)
178
184
 
179
185
  #### Expressions
@@ -245,7 +251,7 @@ REMINDER: In __Lox__, `false` and `nil` are considered falsey, everything else i
245
251
  `!!true; // => true`
246
252
  `!0; // => false`
247
253
 
248
- ##### Grouping expressions
254
+ #### Grouping expressions
249
255
  Use parentheses `(` `)` for a better control in expression/operator precedence.
250
256
 
251
257
  ``` javascript
@@ -253,8 +259,61 @@ print 3 + 4 * 5; // => 23
253
259
  print (3 + 4) * 5; // => 35
254
260
  ```
255
261
 
262
+ #### Variable expressions and assignments
263
+ In __Lox__, a variable expression is nothing than retrieving the value of a variable.
264
+ ``` javascript
265
+ var foo = "bar;" // Variable declaration
266
+ print foo; // Variable expression (= use its value)
267
+ foo = "baz"; // Variable assignment
268
+ print foo; // Output: baz
269
+ ```
270
+
271
+
272
+
273
+ #### Variable declarations
274
+ ``` javascript
275
+ var iAmAVariable = "my-initial-value";
276
+ var iAmNil; // __Lox__ initializes variables to nil by default;
277
+ print iAmNil; // output: nil
278
+ ```
256
279
 
257
- ##### Print Statement
280
+ #### If statement
281
+
282
+ Based on a given condition, an if statement executes one of two statements:
283
+ ``` javascript
284
+ if (condition) {
285
+ print "then-branch";
286
+ } else {
287
+ print "else-branch";
288
+ }
289
+ ```
290
+
291
+ As for other languages, the `else` part is optional.
292
+ ##### Warning: nested `if`...`else`
293
+ Call it a bug ... Nested `if` `else` control flow structure aren't yet supported by __Loxxy__.
294
+ The culprit has a name: [the dangling else](https://en.wikipedia.org/wiki/Dangling_else).
295
+
296
+ The problem in a nutshell: in a nested if ... else ... statement like this:
297
+ ``` javascript
298
+ 'if (true) if (false) print "bad"; else print "good";
299
+ ```
300
+ ... there is an ambiguity. Indeed, according to the __Lox__ grammar, the `else` could be bound
301
+ either to the first `if` or to the second one.
302
+ This ambiguity is usually lifted by applying an ad-hoc rule: an `else` is aways bound to the most
303
+ recent (rightmost) `if`.
304
+ Being a generic parsing library, `Rley` doesn't apply any of these supplemental rules.
305
+ As a consequence,it complains about the found ambiguity and stops the parsing...
306
+ Although `Rley` can cope with ambiguities, this requires the use of an advanced data structure
307
+ called `Shared Packed Parse Forest (SPPF)`.
308
+ SPPF are much more complex to handle than the `common` parse trees present in most compiler or interpreter books.
309
+ Therefore, a future version of `Rley` will incorporate the capability to define disambuiguation rules.
310
+
311
+ In the meantime, the `Loxxy` will progress on other __Lox__ features like:
312
+ - Variables,
313
+ - Block structures...
314
+
315
+
316
+ #### Print Statement
258
317
 
259
318
  The statement print + expression + ; prints the result of the expression to stdout.
260
319
 
@@ -1,9 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'lox_variable_expr'
3
4
  require_relative 'lox_literal_expr'
4
5
  require_relative 'lox_noop_expr'
5
6
  require_relative 'lox_grouping_expr'
6
7
  require_relative 'lox_unary_expr'
7
8
  require_relative 'lox_binary_expr'
8
9
  require_relative 'lox_logical_expr'
10
+ require_relative 'lox_assign_expr'
9
11
  require_relative 'lox_print_stmt'
12
+ require_relative 'lox_if_stmt'
13
+ require_relative 'lox_var_stmt'
14
+ require_relative 'lox_seq_decl'
@@ -149,8 +149,18 @@ module Loxxy
149
149
  end
150
150
 
151
151
  # rule('program' => 'declaration_plus EOF').as ''
152
- def reduce_lox_program(_production, range, tokens, theChildren)
153
- return_first_child(range, tokens, theChildren) # Discard the semicolon
152
+ def reduce_lox_program(_production, _range, tokens, theChildren)
153
+ LoxSeqDecl.new(tokens[0].position, theChildren[0])
154
+ end
155
+
156
+ # rule('declaration_plus' => 'declaration_plus declaration').as ''
157
+ def reduce_declaration_plus_more(_production, _range, _tokens, theChildren)
158
+ theChildren[0] << theChildren[1]
159
+ end
160
+
161
+ # rule('declaration_plus' => 'declaration')
162
+ def reduce_declaration_plus_end(_production, _range, _tokens, theChildren)
163
+ [theChildren[0]]
154
164
  end
155
165
 
156
166
  # rule('exprStmt' => 'expression SEMICOLON')
@@ -158,11 +168,37 @@ module Loxxy
158
168
  return_first_child(range, tokens, theChildren) # Discard the semicolon
159
169
  end
160
170
 
171
+ # rule('varDecl' => 'VAR IDENTIFIER SEMICOLON')
172
+ def reduce_var_declaration(_production, _range, tokens, theChildren)
173
+ var_name = theChildren[1].token.lexeme.dup
174
+ Ast::LoxVarStmt.new(tokens[1].position, var_name, nil)
175
+ end
176
+
177
+ # rule('varDecl' => 'VAR IDENTIFIER EQUAL expression SEMICOLON')
178
+ def reduce_var_initialization(_production, _range, tokens, theChildren)
179
+ var_name = theChildren[1].token.lexeme.dup
180
+ Ast::LoxVarStmt.new(tokens[1].position, var_name, theChildren[3])
181
+ end
182
+
183
+ # rule('ifStmt' => 'IF ifCondition statement elsePart_opt')
184
+ def reduce_if_stmt(_production, _range, tokens, theChildren)
185
+ condition = theChildren[1]
186
+ then_stmt = theChildren[2]
187
+ else_stmt = theChildren[3]
188
+ LoxIfStmt.new(tokens[0].position, condition, then_stmt, else_stmt)
189
+ end
190
+
161
191
  # rule('printStmt' => 'PRINT expression SEMICOLON')
162
192
  def reduce_print_stmt(_production, _range, tokens, theChildren)
163
193
  Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
164
194
  end
165
195
 
196
+ # rule('assignment' => 'owner_opt IDENTIFIER EQUAL assignment')
197
+ def reduce_assign_expr(_production, _range, tokens, theChildren)
198
+ var_name = theChildren[1].token.lexeme.dup
199
+ Ast::LoxAssignExpr.new(tokens[1].position, var_name, theChildren[3])
200
+ end
201
+
166
202
  # rule('logic_or' => 'logic_and disjunct_plus')
167
203
  def reduce_logic_or_plus(production, range, tokens, theChildren)
168
204
  reduce_logical_expr(production, range, tokens, theChildren)
@@ -271,6 +307,12 @@ module Loxxy
271
307
  literal = first_child.token.value
272
308
  LoxLiteralExpr.new(pos, literal)
273
309
  end
310
+
311
+ # rule('primary' => 'IDENTIFIER')
312
+ def reduce_variable_expr(_production, _range, tokens, theChildren)
313
+ var_name = theChildren[0].token.lexeme
314
+ LoxVariableExpr.new(tokens[0].position, var_name)
315
+ end
274
316
  end # class
275
317
  end # module
276
318
  end # module