loxxy 0.0.18 → 0.0.23

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: 43f600b63e6a264cf14a760e82537693068118152aa41e2b6d87f99d993280ea
4
- data.tar.gz: 5ea73cae221b5039ec8257ef29c49bd63d22bb2477cde37b60f4f3799fe06534
3
+ metadata.gz: aeb2808649debaf9bdbca836e459b0f7991442c90aad6bb4b174374fb66234df
4
+ data.tar.gz: 78b1b43091b11b5bde2b2444dd785e3c464252af044167acade6f04b830f95fa
5
5
  SHA512:
6
- metadata.gz: 8d4944a0b164730ddf0839abc325fc0389d895abecb1cd37f22909dc5a17243c29965eb194c351044fb3087bebc1d3dfd319aa6188f05e7a31df09bb41326e18
7
- data.tar.gz: e7f857a51b74337724fa4cfd16816d79f9a0dec2b51dcdc8c297a52773048ea2dd2349a110fbf9b0d5eea6f2c57c6397f8196d14520cff59edab1e99444d7a60
6
+ metadata.gz: 24113720fa7bcd7d711cf03668c86af5a10de3b06dcf9b02d6a5c3550d86e0a19d5374b0d0de6c641afd2a5a9de7c7baccee9da96f97fece6aaf37864d91a0d3
7
+ data.tar.gz: 0103b262f03272b23f297a57b7d0735c513f6ef0b82e9a2f13e20068845e0cb6ac1952c46a404247b23dde37e75c3fbc48b45f44c1b07470078e4554d5ed54c5
@@ -1,28 +1,92 @@
1
+ ## [0.0.23] - 2021-01-20
2
+ - Fix for variables without explicit initialization.
3
+
4
+ ### Added
5
+ - Method `Ast::ASTVisitor#visit_builtin` for visiting `Datatype::BuiltinDatatype` value.
6
+ - Method `BackEnd::Engine#before_visit_builtin` push the data value onto the stack.
7
+
8
+ ### Fixed
9
+ - Method `Ast::LoxVarStmt#initialize`: in case no explicit value provided then use `Datatype::Nil.instance`instead of Ruby `nil`
10
+
11
+ ## [0.0.22] - 2021-01-17
12
+ - The interpreter can retrieve the value of a variable.
13
+
14
+ ### Added
15
+ - Method `Ast::ASTBuilder#declaration_plus_more` and `Ast::ASTBuilder#declaration_plus_end` to allow multiple expressions/statements
16
+ - Method `Ast::ASTBuilder#reduce_var_expression` creates an `Ast::LoxVariableExpr` node
17
+ - Method `Ast::ASTVisitor#visit_var_expr` for visiting `Ast::LoxVariableExpr` nodes
18
+ - Class `Ast::LoxSeqDecl` a node that represents a sequence of declarations/statements
19
+ - Class `Ast::LoxVarExpr` a node that represents a variable occurrence in an expression
20
+ - Method `Engine::after_variable_expr`: retrieve the value of variable with given name
21
+
22
+ ### Changed
23
+ - Method `Ast::ASTBuilder#reduce_lox_program` to support multiple statements/declarations
24
+ - File `README.md` updated.
25
+
26
+ ## [0.0.21] - 2021-01-16
27
+ - The interpreter supports the declaration global variables.
28
+
29
+ ### Added
30
+ - Class `BackEnd::Entry`, mixin module for objects put in the symbol table
31
+ - Class `BackEnd::Environment` that keeps track of variables in a given context.
32
+ - Class `BackEnd::SymbolTable` that keeps track of environments.
33
+ - Class `BackEnd::Variable` internal representation of a `Lox` variable
34
+ - Method `Ast::ASTBuilder#reduce_var_declaration` and `Ast::ASTBuilder#reduce_var_declaration`
35
+ - Method `Ast::ASTVisitor#visit_var_stmt` for visiting `LoxVarStmt` nodes
36
+ - Attribute `Engine::symbol_table`for keeping track of variables
37
+ - Method `Engine::after_var_stmt` for the implementation of variable declarations
38
+
39
+ ## [0.0.20] - 2021-01-15
40
+ - The interpreter supports the `if` ... `else` statement.
41
+
42
+ ### Added
43
+ - Class `Ast::LoxItStmt`, AST node specific for `if` `else` statements
44
+ - Method `Ast::ASTBuilder#reduce_if_stmt` as semantic action for if ... else
45
+ - Method `Ast::ASTVisitor#visit_if_stmt` for visiting `LoxIfStmt` nodes
46
+ - Method `Engine::after_if_stmt` implementation of the control flow
47
+
48
+ ## [0.0.19] - 2021-01-14
49
+ - The interpreter supports expressions between parentheses (grouping).
50
+
51
+ ### Added
52
+ - Class `Ast::LoxLogicalExpr`
53
+ - Method `Ast::ASTBuilder#reduce_grouping_expr` as semantic action for grouping expression
54
+ - Method `Ast::ASTVisitor#visit_grouping_expr` for visiting grouping expressions
55
+ - Method `Engine::after_grouping_expr`for the evaluation of grouping expressions
56
+
57
+ ### Changed
58
+ - File `grammar.rb` rules for if ... else were given names in order to activate semantic actions.
59
+ - File `README.md` updated with little `if ... else` documentation.
60
+
1
61
  ## [0.0.18] - 2021-01-13
2
62
  - The interpreter can evaluate `and`, `or`expressions.
3
63
 
4
-
64
+ ### Added
65
+ - Class `Ast::LoxLogicalExpr`
66
+ - Method `Ast::ASTBuilder#reduce_logical_expr` for the semantic action require for `and`, `or`
67
+ - Method `Ast::ASTVisitor#visit_logical_expr` for visiting logical expressions
68
+ - Method `Backend::Engine#after_logical_expr` implements the evaluation of the logical expressions
5
69
 
6
70
  ## [0.0.17] - 2021-01-12
7
71
  - The interpreter can evaluate all arithmetic and comparison operations.
8
72
  - It implements `==`, `!=` and the unary operations `!`, `-`
9
73
 
10
- ## Added
11
- - Class `AST::LoxUnaryExpr`
12
- - Method `AST::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
74
+ ### Added
75
+ - Class `Ast::LoxUnaryExpr`
76
+ - Method `Ast::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
13
77
  - Method `Ast::ASTVisitor#visit_unnary_expr` for visiting unary expressions
14
78
  - Method `Backend::Engine#after_unary_expr` evaluating an unary expression
15
79
  - In class `Datatype::BuiltinDatatype` the methods `falsey?`, `truthy?`, `!`, `!=`
16
80
  - In class `Datatype::Number`the methods `<`, `<=`, ´>´, `>=` and `-@`
17
81
 
18
- ## Changed
82
+ ### Changed
19
83
  - File `README.md` updated.
20
84
 
21
85
  ## [0.0.16] - 2021-01-11
22
86
  - The interpreter can evaluate product and division of two numbers.
23
87
  - It also implements equality `==` and inequality `!=` operators
24
88
 
25
- ## Added
89
+ ### Added
26
90
  - Method `Datatype::False#==` for equality testing
27
91
  - Method `Datatype::False#!=` for inequality testing
28
92
  - Method `Datatype::LXString#==` for equality testing
@@ -36,17 +100,17 @@
36
100
  - Method `Datatype::True#==` for equality testing
37
101
  - Method `Datatype::True#!=` for inequality testing
38
102
 
39
- ## Changed
103
+ ### Changed
40
104
  - Method `BackEnd::Engine#after_binary_expr` to allow `*`, `/`, `==`, `!=` operators
41
105
  - File `README.md` updated for the newly implemented operators
42
106
 
43
107
  ## [0.0.15] - 2021-01-11
44
108
  - The interpreter can evaluate substraction between two numbers.
45
109
 
46
- ## Added
110
+ ### Added
47
111
  - Method `Datatype::Number#-` implmenting the subtraction operation
48
112
 
49
- ## Changed
113
+ ### Changed
50
114
  - File `README.md` minor editorial changes.
51
115
  - File `lx_string_spec.rb` Added test for string concatentation
52
116
  - File `number_spec.rb` Added tests for addition and subtraction operations
@@ -55,7 +119,7 @@
55
119
  ## [0.0.14] - 2021-01-10
56
120
  - The interpreter can evaluate addition of numbers and string concatenation
57
121
 
58
- ## Added
122
+ ### Added
59
123
  - Method `Ast::ASTVisitor#visit_binary_expr` for visiting binary expressions
60
124
  - Method `Ast::LoxBinaryExpr#accept` for visitor pattern
61
125
  - Method `BackEnd::Engine#after_binary_expr` to trigger execution of binary operator
@@ -63,79 +127,79 @@
63
127
  - Method `Datatype::LXString#+` implementation of the string concatenation
64
128
  - Method `Datatype::Number#+` implementation of the addition of numbers
65
129
 
66
- ## Changed
130
+ ### Changed
67
131
  - File `interpreter_spec.rb` Added tests for addition operation and string concatenation
68
132
 
69
133
 
70
134
  ## [0.0.13] - 2021-01-10
71
135
  - The interpreter can evaluate directly simple literals.
72
136
 
73
- ## Changed
137
+ ### Changed
74
138
  - Class `AST::ASTBuilder` added `reduce_exprStmt` to support the evaluation of literals.
75
139
  - File `README.md` added one more example.
76
140
  - File `parser_spec.rb` Updated the tests to reflect the change in the AST.
77
141
  - File `interpreter_spec.rb` Added a test for literal expression.
78
142
 
79
- ## Fixed
143
+ ### Fixed
80
144
  - File `loxxy.rb`: shorthand method `lox_true` referenced the ... false object (oops).
81
145
 
82
146
  ## [0.0.12] - 2021-01-09
83
147
  - Initial interpreter capable of evaluating a tiny subset of Lox language.
84
148
 
85
- ## Added
149
+ ### Added
86
150
  - Class `AST::LoxNoopExpr`
87
151
  - Class `AST::LoxPrintStmt`
88
152
  - Class `BackEnd::Engine` implementation of the print statement logic
89
153
  - Class `Interpreter`
90
154
 
91
- ## Changed
155
+ ### Changed
92
156
  - Class `Ast::ASTVisitor` Added visit method
93
157
  - File `README.md` added Hello world example.
94
158
 
95
159
  ## [0.0.11] - 2021-01-08
96
160
  - AST node generation for logical expression (and, or).
97
161
 
98
- ## Changed
162
+ ### Changed
99
163
  - Class `AST::ASTBuilder` added `reduce_` methods for logical operations.
100
164
  - File `grammar.rb`added name to logical expression rules
101
165
  - File `README.md` added gem version and license badges, expanded roadmap section.
102
166
 
103
- ## Fixed
167
+ ### Fixed
104
168
  - File `grammar.rb`: a rule had incomplete non-terminal name `conjunct_` in its lhs.
105
169
 
106
170
 
107
171
  ## [0.0.10] - 2021-01-08
108
172
  - AST node generation for equality expression.
109
173
 
110
- ## Changed
174
+ ### Changed
111
175
  - Class `AST::ASTBuilder` refactoring and added `reduce_` methods for equality operations.
112
176
  - File `grammar.rb`added name to equality rules
113
177
  - File `README.md` added gem version and license badges, expanded roadmap section.
114
178
 
115
- ## Fixed
179
+ ### Fixed
116
180
  - File `grammar.rb`: a rule had still the discarded non-terminal `equalityTest_star` in its lhs.
117
181
 
118
182
  ## [0.0.9] - 2021-01-07
119
183
  - AST node generation for comparison expression.
120
184
 
121
- ## Changed
185
+ ### Changed
122
186
  - Class `AST::ASTBuilder` added `reduce_` methods for comparison operations.
123
187
  - File `grammar.rb`added name to comparison rules
124
188
 
125
189
  ## [0.0.8] - 2021-01-07
126
190
  - AST node generation for arithmetic operations of number literals.
127
191
 
128
- ## Changed
192
+ ### Changed
129
193
  - Class `AST::ASTBuilder` added `reduce_` methods for arithmetic operations.
130
194
  - File `grammar.rb`added name to arithmetic rules
131
195
 
132
- ## Fixed
196
+ ### Fixed
133
197
  - File `grammar.rb`: second rule for `factor` had a missing member in rhs.
134
198
 
135
199
  ## [0.0.7] - 2021-01-06
136
200
  - Lox grammar reworked, initial AST classes created.
137
201
 
138
- ## Added
202
+ ### Added
139
203
  - Class `Parser` this one generates AST's (Abstract Syntax Tree)
140
204
  - Class `AST::ASTVisitor` draft initial implementation.
141
205
  - Class `AST::BinaryExpr` draft initial implementation.
@@ -143,7 +207,7 @@
143
207
  - Class `AST::LiteralExpr` draft initial implementation.
144
208
  - Class `AST::LoxNode` draft initial implementation.
145
209
 
146
- ## Changed
210
+ ### Changed
147
211
  - File `spec_helper.rb`: removed Bundler dependency
148
212
  - Class `AST::ASTBuilder` added initial `reduce_` methods.
149
213
  - File `README.md` Removed example with AST generation since this is in flux.
@@ -151,31 +215,31 @@
151
215
  ## [0.0.6] - 2021-01-03
152
216
  - First iteration of a parser with AST generation.
153
217
 
154
- ## Added
218
+ ### Added
155
219
  - Class `Parser` this one generates AST's (Abstract Syntax Tree)
156
220
  - Class `AST::ASTBuilder` default code to generate an AST.
157
221
 
158
- ## Changed
222
+ ### Changed
159
223
  - File `spec_helper.rb`: removed Bundler dependency
160
224
  - File `README.md` Added example with AST visualization.
161
225
 
162
- ## Fixed
226
+ ### Fixed
163
227
  - File `grammar.rb` ensure that the constant `Grammar` is created once only.
164
228
 
165
229
  ## [0.0.5] - 2021-01-02
166
230
  - Improved example in `README.md`, code re-styling to please `Rubocop` 1.7
167
231
 
168
- ## Changed
232
+ ### Changed
169
233
  - Code re-styling to please `Rubocop` 1.7
170
234
  - File `README.md` Improved example with better parse tree visualization.
171
235
 
172
236
  ## [0.0.4] - 2021-01-01
173
237
  - A first parser implementation able to parse Lox source code.
174
238
 
175
- ## Added
239
+ ### Added
176
240
  - Method `LXString::==` equality operator.
177
241
 
178
- ## Changed
242
+ ### Changed
179
243
  - class `Parser` renamed to `RawParser`
180
244
  - File `README.md` Added an example showing the use of `RawParser` class.
181
245
 
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](#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,69 @@ REMINDER: In __Lox__, `false` and `nil` are considered falsey, everything else i
245
251
  `!!true; // => true`
246
252
  `!0; // => false`
247
253
 
248
- ##### Print Statement
254
+ #### Grouping expressions
255
+ Use parentheses `(` `)` for a better control in expression/operator precedence.
256
+
257
+ ``` javascript
258
+ print 3 + 4 * 5; // => 23
259
+ print (3 + 4) * 5; // => 35
260
+ ```
261
+
262
+ #### Variable expressions
263
+ In __Lox__, a variable expression is nothing than retrieving the value of a variable.
264
+ ``` javascript
265
+ var foo = "bar;" // Variable declaration
266
+ foo; // Varible expression (= retrieving its value)
267
+ ```
268
+
269
+ #### Variable declarations
270
+ ``` javascript
271
+ var iAmAVariable = "my-initial-value";
272
+ var iAmNil; // __Lox__ initializes variables to nil by default;
273
+ print iAmNil; // output: nil
274
+ ```
275
+
276
+ Warning: current version cannot assign a value to an existing variable.
277
+ Expect this capability to be implemented in the coming days.
278
+
279
+
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
249
317
 
250
318
  The statement print + expression + ; prints the result of the expression to stdout.
251
319
 
@@ -1,8 +1,13 @@
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'
6
+ require_relative 'lox_grouping_expr'
5
7
  require_relative 'lox_unary_expr'
6
8
  require_relative 'lox_binary_expr'
7
9
  require_relative 'lox_logical_expr'
8
10
  require_relative 'lox_print_stmt'
11
+ require_relative 'lox_if_stmt'
12
+ require_relative 'lox_var_stmt'
13
+ require_relative 'lox_seq_decl'
@@ -134,6 +134,11 @@ module Loxxy
134
134
  [[operator, operand2]]
135
135
  end
136
136
 
137
+ # Return the AST node corresponding to the second symbol in the rhs
138
+ def reduce_keep_symbol2(_production, _range, _tokens, theChildren)
139
+ theChildren[1]
140
+ end
141
+
137
142
  #####################################
138
143
  # SEMANTIC ACTIONS
139
144
  #####################################
@@ -144,8 +149,18 @@ module Loxxy
144
149
  end
145
150
 
146
151
  # rule('program' => 'declaration_plus EOF').as ''
147
- def reduce_lox_program(_production, range, tokens, theChildren)
148
- 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]]
149
164
  end
150
165
 
151
166
  # rule('exprStmt' => 'expression SEMICOLON')
@@ -153,6 +168,26 @@ module Loxxy
153
168
  return_first_child(range, tokens, theChildren) # Discard the semicolon
154
169
  end
155
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
+
156
191
  # rule('printStmt' => 'PRINT expression SEMICOLON')
157
192
  def reduce_print_stmt(_production, _range, tokens, theChildren)
158
193
  Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
@@ -253,6 +288,12 @@ module Loxxy
253
288
  LoxUnaryExpr.new(tokens[0].position, operator, operand)
254
289
  end
255
290
 
291
+ # rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
292
+ def reduce_grouping_expr(_production, _range, tokens, theChildren)
293
+ subexpr = theChildren[1]
294
+ LoxGroupingExpr.new(tokens[0].position, subexpr)
295
+ end
296
+
256
297
  # rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
257
298
  def reduce_literal_expr(_production, _range, _tokens, theChildren)
258
299
  first_child = theChildren.first
@@ -260,6 +301,12 @@ module Loxxy
260
301
  literal = first_child.token.value
261
302
  LoxLiteralExpr.new(pos, literal)
262
303
  end
304
+
305
+ # rule('primary' => 'IDENTIFIER')
306
+ def reduce_variable_expr(_production, _range, tokens, theChildren)
307
+ var_name = theChildren[0].token.lexeme
308
+ LoxVariableExpr.new(tokens[0].position, var_name)
309
+ end
263
310
  end # class
264
311
  end # module
265
312
  end # module