loxxy 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aeb2808649debaf9bdbca836e459b0f7991442c90aad6bb4b174374fb66234df
4
- data.tar.gz: 78b1b43091b11b5bde2b2444dd785e3c464252af044167acade6f04b830f95fa
3
+ metadata.gz: 6085bf18afb919e5ef4d327162470c9d5ca95dde67e00dce78bb26abd6563dec
4
+ data.tar.gz: f1c7732a34b6df2721c20d82404c6ce83bdc8a75b695e4bbe13c51f62d9ac371
5
5
  SHA512:
6
- metadata.gz: 24113720fa7bcd7d711cf03668c86af5a10de3b06dcf9b02d6a5c3550d86e0a19d5374b0d0de6c641afd2a5a9de7c7baccee9da96f97fece6aaf37864d91a0d3
7
- data.tar.gz: 0103b262f03272b23f297a57b7d0735c513f6ef0b82e9a2f13e20068845e0cb6ac1952c46a404247b23dde37e75c3fbc48b45f44c1b07470078e4554d5ed54c5
6
+ metadata.gz: 7546a14b935700e5050411a7805c2b2d00ccfc99160e3241b512289a6cc1762df2f39b7c9845c6ffe7fb95f1412865ef373f5308c9cf333fd72e2025a4a17ed8
7
+ data.tar.gz: 3675956929831e52963759862e8f9d40e5ebd3df471dee87d82784c2d1230ce6057882368042c907741be1038d300b7c83c27ed4bb8d979f5efa2ac79eaa3b1a
@@ -1,3 +1,13 @@
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
+
1
11
  ## [0.0.23] - 2021-01-20
2
12
  - Fix for variables without explicit initialization.
3
13
 
data/README.md CHANGED
@@ -176,7 +176,7 @@ Loxxy supports the following statements:
176
176
  -[Comparison expressions](#comparison-expressions)
177
177
  -[Logical expressions](#logical-expressions)
178
178
  -[Grouping expressions](#grouping-expressions)
179
- -[Variable expressions](#variable-expressions)
179
+ -[Variable expressions and assignments](#variable-expressions)
180
180
 
181
181
  -[Variable declarations](#var-statement)
182
182
  -[If Statement](#if-statement)
@@ -259,13 +259,17 @@ print 3 + 4 * 5; // => 23
259
259
  print (3 + 4) * 5; // => 35
260
260
  ```
261
261
 
262
- #### Variable expressions
262
+ #### Variable expressions and assignments
263
263
  In __Lox__, a variable expression is nothing than retrieving the value of a variable.
264
264
  ``` javascript
265
265
  var foo = "bar;" // Variable declaration
266
- foo; // Varible expression (= retrieving its value)
266
+ print foo; // Variable expression (= use its value)
267
+ foo = "baz"; // Variable assignment
268
+ print foo; // Output: baz
267
269
  ```
268
270
 
271
+
272
+
269
273
  #### Variable declarations
270
274
  ``` javascript
271
275
  var iAmAVariable = "my-initial-value";
@@ -273,10 +277,6 @@ var iAmNil; // __Lox__ initializes variables to nil by default;
273
277
  print iAmNil; // output: nil
274
278
  ```
275
279
 
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
280
  #### If statement
281
281
 
282
282
  Based on a given condition, an if statement executes one of two statements:
@@ -7,6 +7,7 @@ require_relative 'lox_grouping_expr'
7
7
  require_relative 'lox_unary_expr'
8
8
  require_relative 'lox_binary_expr'
9
9
  require_relative 'lox_logical_expr'
10
+ require_relative 'lox_assign_expr'
10
11
  require_relative 'lox_print_stmt'
11
12
  require_relative 'lox_if_stmt'
12
13
  require_relative 'lox_var_stmt'
@@ -193,6 +193,12 @@ module Loxxy
193
193
  Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
194
194
  end
195
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
+
196
202
  # rule('logic_or' => 'logic_and disjunct_plus')
197
203
  def reduce_logic_or_plus(production, range, tokens, theChildren)
198
204
  reduce_logical_expr(production, range, tokens, theChildren)
@@ -83,6 +83,14 @@ module Loxxy
83
83
  broadcast(:after_print_stmt, aPrintStmt)
84
84
  end
85
85
 
86
+ # Visit event. The visitor is visiting an assignment node
87
+ # @param aLiteralExpr [AST::LoxAssignExpr] the variable assignment node to visit.
88
+ def visit_assign_expr(anAssignExpr)
89
+ broadcast(:before_assign_expr, anAssignExpr)
90
+ traverse_subnodes(anAssignExpr)
91
+ broadcast(:after_assign_expr, anAssignExpr)
92
+ end
93
+
86
94
  # Visit event. The visitor is about to visit a logical expression.
87
95
  # Since logical expressions may take shorcuts by not evaluating all their
88
96
  # sub-expressiosns, they are responsible for visiting or not their children.
@@ -129,7 +137,7 @@ module Loxxy
129
137
  broadcast(:after_literal_expr, aLiteralExpr)
130
138
  end
131
139
 
132
- # Visit event. The visitor is visiting a variable reference node
140
+ # Visit event. The visitor is visiting a variable usage node
133
141
  # @param aLiteralExpr [AST::LoxVariableExpr] the variable reference node to visit.
134
142
  def visit_variable_expr(aVariableExpr)
135
143
  broadcast(:before_variable_expr, aVariableExpr)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lox_compound_expr'
4
+
5
+ module Loxxy
6
+ module Ast
7
+ # This AST node represents the assignment of a value to a variable
8
+ class LoxAssignExpr < LoxCompoundExpr
9
+ # @return [String] variable name
10
+ attr_reader :name
11
+
12
+ # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
13
+ # @param aName [String] name of the variable
14
+ # @param aValue [Loxxy::Ast::LoxNode, NilClass] value to assign
15
+ def initialize(aPosition, aName, aValue)
16
+ super(aPosition, [aValue])
17
+ @name = aName
18
+ end
19
+
20
+ # Part of the 'visitee' role in Visitor design pattern.
21
+ # @param visitor [Ast::ASTVisitor] the visitor
22
+ def accept(visitor)
23
+ visitor.visit_assign_expr(self)
24
+ end
25
+ end # class
26
+ end # module
27
+ end # module
@@ -66,6 +66,15 @@ module Loxxy
66
66
  @ostream.print tos.to_str
67
67
  end
68
68
 
69
+ def after_assign_expr(anAssignExpr)
70
+ var_name = anAssignExpr.name
71
+ variable = symbol_table.lookup(var_name)
72
+ raise StandardError, "Unknown variable #{var_name}" unless variable
73
+ value = stack.pop
74
+ variable.assign(value)
75
+ stack.push value # An expression produces a value
76
+ end
77
+
69
78
  def after_logical_expr(aLogicalExpr, visitor)
70
79
  op = aLogicalExpr.operator
71
80
  operand1 = stack.pop # only first operand was evaluated
@@ -11,13 +11,18 @@ module Loxxy
11
11
  include Entry # Add expected behaviour for symbol table entries
12
12
 
13
13
  # @return [Datatype::BuiltinDatatype] the value assigned to the variable
14
- attr_accessor :value
14
+ attr_reader :value
15
15
 
16
16
  # Create a variable with given name and initial value
17
17
  # @param aName [String] The name of the variable
18
18
  # @param aValue [Datatype::BuiltinDatatype] the initial assigned value
19
19
  def initialize(aName, aValue = Datatype::Nil.instance)
20
20
  init_name(aName)
21
+ assign(aValue)
22
+ end
23
+
24
+ # @param aValue [Datatype::BuiltinDatatype] the assigned value
25
+ def assign(aValue)
21
26
  @value = aValue
22
27
  end
23
28
  end # class
@@ -83,7 +83,7 @@ module Loxxy
83
83
  rule('expression_opt' => 'expression')
84
84
  rule('expression_opt' => [])
85
85
  rule('expression' => 'assignment')
86
- rule('assignment' => 'owner_opt IDENTIFIER EQUAL assignment')
86
+ rule('assignment' => 'owner_opt IDENTIFIER EQUAL assignment').as 'assign_expr'
87
87
  rule('assignment' => 'logic_or')
88
88
  rule('owner_opt' => 'call DOT')
89
89
  rule('owner_opt' => [])
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.23'
4
+ VERSION = '0.0.24'
5
5
  end
@@ -277,13 +277,28 @@ LOX_END
277
277
 
278
278
  it 'should set uninitialized variables to nil' do
279
279
  program = <<-LOX_END
280
- var foo;
281
- print foo; // => nil
280
+ var a;
281
+ print a; // => nil
282
282
  LOX_END
283
283
  expect { subject.evaluate(program) }.not_to raise_error
284
284
  expect(sample_cfg[:ostream].string).to eq('nil')
285
285
  end
286
286
 
287
+ it 'should accept assignments to a global variable' do
288
+ program = <<-LOX_END
289
+ var a = "before";
290
+ print a; // output: before
291
+
292
+ a = "after";
293
+ print a; // output: after
294
+
295
+ print a = "arg"; // output: arg
296
+ print a; // output: arg
297
+ LOX_END
298
+ expect { subject.evaluate(program) }.not_to raise_error
299
+ expect(sample_cfg[:ostream].string).to eq('beforeafterargarg')
300
+ end
301
+
287
302
  it 'should print the hello world message' do
288
303
  expect { subject.evaluate(hello_world) }.not_to raise_error
289
304
  expect(sample_cfg[:ostream].string).to eq('Hello, world!')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loxxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.23
4
+ version: 0.0.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
@@ -87,6 +87,7 @@ files:
87
87
  - lib/loxxy/ast/all_lox_nodes.rb
88
88
  - lib/loxxy/ast/ast_builder.rb
89
89
  - lib/loxxy/ast/ast_visitor.rb
90
+ - lib/loxxy/ast/lox_assign_expr.rb
90
91
  - lib/loxxy/ast/lox_binary_expr.rb
91
92
  - lib/loxxy/ast/lox_compound_expr.rb
92
93
  - lib/loxxy/ast/lox_grouping_expr.rb