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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15da87c78ce0d90162679c2b76478cfaff17d9f88f78d4109190b83952146956
4
- data.tar.gz: 0c9b1834f17cc51da96ec568d0804131b65dd6b82125ace0e4c56d6062250d09
3
+ metadata.gz: 1258e225c3c22ba2c8a1df645f2ee39fc6fc2330a62b288a15f59e1ca40596b2
4
+ data.tar.gz: 102ac797634d4abf2e72902f568c5b0cc5ec161433e5e4c4e0888e7142508d65
5
5
  SHA512:
6
- metadata.gz: 6c31994ac27f67cc461fc10453468a42a17691f1b5c3171e23d26dcf9ecd6b5f5de8ad97184037990de6268039e57f8b0d5e80e4411f9c0a1a02b5edba766e91
7
- data.tar.gz: 15ceead67dc859d2e4d3ca3e97aaa67372b581317fdbac8a66241ffb3322acec3115a5dab619a11d0a740676734fe5e517b9b1ca3aff218800ac07d693927263
6
+ metadata.gz: a1715b6c93b1861fadafac38327ea2fdee592f2b0b46320b04acd7e64db166911dc614d59412dae9d0bbccea9ca95f9299aac276eba9ee2a87a58963a2ec7d13
7
+ data.tar.gz: 62915b07a3066c8068f41fd622d9d9be4d8baf29b6c3ef0849b3e410be5d52343fa8c00b8bbff1665deefc838cd29a423852f9666af3e410aee77b538f4030f0
@@ -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 block of code.
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 tiny subset of __Lox__.
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.25'
4
+ VERSION = '0.0.26'
5
5
  end
@@ -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.25
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-21 00:00:00.000000000 Z
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