loxxy 0.0.25 → 0.0.26
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 +13 -1
- data/README.md +13 -1
- data/lib/loxxy/ast/all_lox_nodes.rb +1 -0
- data/lib/loxxy/ast/ast_builder.rb +5 -0
- data/lib/loxxy/ast/ast_visitor.rb +8 -0
- data/lib/loxxy/ast/lox_while_stmt.rb +32 -0
- data/lib/loxxy/back_end/engine.rb +10 -0
- data/lib/loxxy/front_end/grammar.rb +1 -1
- data/lib/loxxy/version.rb +1 -1
- data/spec/interpreter_spec.rb +29 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1258e225c3c22ba2c8a1df645f2ee39fc6fc2330a62b288a15f59e1ca40596b2
|
4
|
+
data.tar.gz: 102ac797634d4abf2e72902f568c5b0cc5ec161433e5e4c4e0888e7142508d65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1715b6c93b1861fadafac38327ea2fdee592f2b0b46320b04acd7e64db166911dc614d59412dae9d0bbccea9ca95f9299aac276eba9ee2a87a58963a2ec7d13
|
7
|
+
data.tar.gz: 62915b07a3066c8068f41fd622d9d9be4d8baf29b6c3ef0849b3e410be5d52343fa8c00b8bbff1665deefc838cd29a423852f9666af3e410aee77b538f4030f0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
|
+
## [0.0.26] - 2021-01-22
|
2
|
+
- The interpreter implements `while` loops.
|
3
|
+
|
4
|
+
### Added
|
5
|
+
- Class `Ast::LoxWhileStmt` a node that represents a while statement
|
6
|
+
- Method `Ast::ASTBuilder#reduce_while_stmt` creates an `Ast::LoxWhileStmt` node
|
7
|
+
- Method `Ast::ASTVisitor#visit_while_stmt` for visiting an `Ast::LoxWhileStmt` node
|
8
|
+
- Method `BackEnd::Engine#after_while_stmt` implements the while looping structure
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
- File `README.md` updated.
|
12
|
+
|
1
13
|
## [0.0.25] - 2021-01-21
|
2
|
-
- The interpreter implements
|
14
|
+
- The interpreter implements blocks of code.
|
3
15
|
|
4
16
|
### Added
|
5
17
|
- Class `Ast::LoxBlockStmt` a node that represents a block of code
|
data/README.md
CHANGED
@@ -131,7 +131,7 @@ program
|
|
131
131
|
On one hand, the parser covers the complete Lox grammar and should therefore, in principle,
|
132
132
|
parse any valid Lox program.
|
133
133
|
|
134
|
-
On the other hand, the interpreter is under development and currently it can evaluate only a
|
134
|
+
On the other hand, the interpreter is under development and currently it can evaluate only a subset of __Lox__.
|
135
135
|
But the situation is changing almost daily, stay tuned...
|
136
136
|
|
137
137
|
Here are the language features currently supported by the interpreter:
|
@@ -144,6 +144,7 @@ Here are the language features currently supported by the interpreter:
|
|
144
144
|
- [Variable declarations](#var-statement)
|
145
145
|
- [If Statement](#if-statement)
|
146
146
|
- [Print Statement](#print-statement)
|
147
|
+
- [While Statement](#while-statement)
|
147
148
|
- [Block Statement](#block-statement)
|
148
149
|
|
149
150
|
### Comments
|
@@ -182,6 +183,7 @@ Loxxy supports the following statements:
|
|
182
183
|
-[Variable declarations](#var-statement)
|
183
184
|
-[If Statement](#if-statement)
|
184
185
|
-[Print Statement](#print-statement)
|
186
|
+
-[While Statement](#while-statement)
|
185
187
|
-[Block Statement](#block-statement)
|
186
188
|
|
187
189
|
#### Expressions
|
@@ -323,6 +325,16 @@ print "Hello, world!"; // Output: Hello, world!
|
|
323
325
|
|
324
326
|
```
|
325
327
|
|
328
|
+
#### While Statement
|
329
|
+
|
330
|
+
``` javascript
|
331
|
+
var a = 1;
|
332
|
+
while (a < 10) {
|
333
|
+
print a;
|
334
|
+
a = a + 1;
|
335
|
+
} // Output: 123456789
|
336
|
+
```
|
337
|
+
|
326
338
|
#### Block Statement
|
327
339
|
__Lox__ has code blocks.
|
328
340
|
``` javascript
|
@@ -9,6 +9,7 @@ require_relative 'lox_binary_expr'
|
|
9
9
|
require_relative 'lox_logical_expr'
|
10
10
|
require_relative 'lox_assign_expr'
|
11
11
|
require_relative 'lox_block_stmt'
|
12
|
+
require_relative 'lox_while_stmt'
|
12
13
|
require_relative 'lox_print_stmt'
|
13
14
|
require_relative 'lox_if_stmt'
|
14
15
|
require_relative 'lox_var_stmt'
|
@@ -193,6 +193,11 @@ module Loxxy
|
|
193
193
|
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
194
194
|
end
|
195
195
|
|
196
|
+
# rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as ''
|
197
|
+
def reduce_while_stmt(_production, _range, tokens, theChildren)
|
198
|
+
Ast::LoxWhileStmt.new(tokens[1].position, theChildren[2], theChildren[4])
|
199
|
+
end
|
200
|
+
|
196
201
|
# rule('block' => 'LEFT_BRACE declaration_plus RIGHT_BRACE')
|
197
202
|
def reduce_block_stmt(_production, _range, tokens, theChildren)
|
198
203
|
decls = LoxSeqDecl.new(tokens[1].position, theChildren[1])
|
@@ -83,6 +83,14 @@ module Loxxy
|
|
83
83
|
broadcast(:after_print_stmt, aPrintStmt)
|
84
84
|
end
|
85
85
|
|
86
|
+
# Visit event. The visitor is about to visit a while statement node.
|
87
|
+
# @param aWhileStmt [AST::LOXWhileStmt] the while statement node to visit
|
88
|
+
def visit_while_stmt(aWhileStmt)
|
89
|
+
broadcast(:before_while_stmt, aWhileStmt)
|
90
|
+
traverse_subnodes(aWhileStmt) # The condition is visited/evaluated here...
|
91
|
+
broadcast(:after_while_stmt, aWhileStmt, self)
|
92
|
+
end
|
93
|
+
|
86
94
|
# Visit event. The visitor is about to visit a block statement.
|
87
95
|
# @param aBlockStmt [AST::LOXBlockStmt] the print statement node to visit
|
88
96
|
def visit_block_stmt(aBlockStmt)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxWhileStmt < LoxCompoundExpr
|
8
|
+
# @return [LoxNode] body of the while loop (as a statement)
|
9
|
+
attr_reader :body
|
10
|
+
|
11
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
12
|
+
# @param condExpr [Loxxy::Ast::LoxNode] iteration condition
|
13
|
+
# @param theBody [Loxxy::Ast::LoxNode]
|
14
|
+
def initialize(aPosition, condExpr, theBody)
|
15
|
+
super(aPosition, [condExpr])
|
16
|
+
@body = theBody
|
17
|
+
end
|
18
|
+
|
19
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
20
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
21
|
+
def accept(visitor)
|
22
|
+
visitor.visit_while_stmt(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Accessor to the condition expression
|
26
|
+
# @return [LoxNode]
|
27
|
+
def condition
|
28
|
+
subnodes[0]
|
29
|
+
end
|
30
|
+
end # class
|
31
|
+
end # module
|
32
|
+
end # module
|
@@ -66,6 +66,16 @@ module Loxxy
|
|
66
66
|
@ostream.print tos.to_str
|
67
67
|
end
|
68
68
|
|
69
|
+
def after_while_stmt(aWhileStmt, aVisitor)
|
70
|
+
loop do
|
71
|
+
condition = stack.pop
|
72
|
+
break unless condition.truthy?
|
73
|
+
|
74
|
+
aWhileStmt.body.accept(aVisitor)
|
75
|
+
aWhileStmt.condition.accept(aVisitor)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
69
79
|
def before_block_stmt(_aBlockStmt)
|
70
80
|
new_env = Environment.new
|
71
81
|
symbol_table.enter_environment(new_env)
|
@@ -75,7 +75,7 @@ module Loxxy
|
|
75
75
|
|
76
76
|
rule('printStmt' => 'PRINT expression SEMICOLON').as 'print_stmt'
|
77
77
|
rule('returnStmt' => 'RETURN expression_opt SEMICOLON')
|
78
|
-
rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement')
|
78
|
+
rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as 'while_stmt'
|
79
79
|
rule('block' => 'LEFT_BRACE declaration_plus RIGHT_BRACE').as 'block_stmt'
|
80
80
|
rule('block' => 'LEFT_BRACE RIGHT_BRACE')
|
81
81
|
|
data/lib/loxxy/version.rb
CHANGED
data/spec/interpreter_spec.rb
CHANGED
@@ -329,6 +329,35 @@ LOX_END
|
|
329
329
|
expect(sample_cfg[:ostream].string).to eq('innerouter')
|
330
330
|
end
|
331
331
|
|
332
|
+
it 'should implement single statement while loops' do
|
333
|
+
program = <<-LOX_END
|
334
|
+
// Single-expression body.
|
335
|
+
var c = 0;
|
336
|
+
while (c < 3) print c = c + 1;
|
337
|
+
// output: 1
|
338
|
+
// output: 2
|
339
|
+
// output: 3
|
340
|
+
LOX_END
|
341
|
+
expect { subject.evaluate(program) }.not_to raise_error
|
342
|
+
expect(sample_cfg[:ostream].string).to eq('123')
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'should implement block body while loops' do
|
346
|
+
program = <<-LOX_END
|
347
|
+
// Block body.
|
348
|
+
var a = 0;
|
349
|
+
while (a < 3) {
|
350
|
+
print a;
|
351
|
+
a = a + 1;
|
352
|
+
}
|
353
|
+
// output: 0
|
354
|
+
// output: 1
|
355
|
+
// output: 2
|
356
|
+
LOX_END
|
357
|
+
expect { subject.evaluate(program) }.not_to raise_error
|
358
|
+
expect(sample_cfg[:ostream].string).to eq('012')
|
359
|
+
end
|
360
|
+
|
332
361
|
it 'should print the hello world message' do
|
333
362
|
expect { subject.evaluate(hello_world) }.not_to raise_error
|
334
363
|
expect(sample_cfg[:ostream].string).to eq('Hello, world!')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loxxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- lib/loxxy/ast/lox_unary_expr.rb
|
103
103
|
- lib/loxxy/ast/lox_var_stmt.rb
|
104
104
|
- lib/loxxy/ast/lox_variable_expr.rb
|
105
|
+
- lib/loxxy/ast/lox_while_stmt.rb
|
105
106
|
- lib/loxxy/back_end/engine.rb
|
106
107
|
- lib/loxxy/back_end/entry.rb
|
107
108
|
- lib/loxxy/back_end/environment.rb
|