loxxy 0.1.03 → 0.1.04

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: 2bf956c6e2d6736535acd1e9b0cb29df6b55a8d9002be073cb70bbf753fb06c9
4
- data.tar.gz: 1f635dc69e588f01406cd988bf98d12b9ea398f36e249113a37b089788ef21cb
3
+ metadata.gz: 16614a276ddf1553d4373e5da9ab78d7f03f2fc8cadec6190c28bb27bdd95b99
4
+ data.tar.gz: 98903f6ec0c9e010fd429f6b1753b34f52b4cfc67c7eafd21b1103c6ac429bba
5
5
  SHA512:
6
- metadata.gz: dce93451a9efc548df45683f5772a5d5509c25a57969465f3ff9f48f8b5adcc642b7bb92b25d43658869b5b62d3108796964226c35130cb1492335dc6eaf8fe1
7
- data.tar.gz: 881dfd881db0d2ec3e56b91ad14bc6dd0e0b91ba3839fa1efe09c3636aac575856e3e8c4d4a64a55e913a757a4f1d275cc843734ceda3a23ef597591cb282f3f
6
+ metadata.gz: 8278546ef246d8f4d5db72b18d5c91dfa3dc1d7f18f81b7491ca01df38a64495a3b5eb26df0fa18b652f59d56784efb8fe9348b5b65d091aa27a09e6b8f144a4
7
+ data.tar.gz: deaa7b43f225788b9366610572f5994eec8950a8e66c8159b83a18b874139d322270f274c4753dc28b6926b7c295d42a2f77600211dfbd0df0e24b82e1a155b5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
+ ## [0.1.04] - 2021-02-28
2
+
3
+ ### Added
4
+ - Class `Ast::LoxReturnStmt` a node that represents a return statement
5
+ - Method `Ast::ASTBuilder#reduce_return_stmt`
6
+ - Method `Ast::ASTVisitor#visit_return_stmt` for visiting an `Ast::LoxReturnStmt` node
7
+ - Method `BackEnd::Engine#after_return_stmt` to handle return statement
8
+ - Method `BackEnd::Function#!` implementing the logical negation of a function (as value).
9
+ - Test suite for logical operators (in project repository)
10
+ - Test suite for block code
11
+ - Test suite for call and function declaration (initial)
12
+
13
+ ### Changed
14
+ - Method `BackEnd::Engine#after_call_expr` now generate a `catch` and `throw` events
15
+
1
16
  ## [0.1.03] - 2021-02-26
2
- - Runtime argument chacking for arithmetic and comparison operators
17
+ - Runtime argument checking for arithmetic and comparison operators
3
18
 
4
19
  ### Added
5
20
  - Test suite for arithmetic and comparison operators (in project repository)
@@ -221,11 +236,11 @@
221
236
  - The interpreter can evaluate substraction between two numbers.
222
237
 
223
238
  ### Added
224
- - Method `Datatype::Number#-` implmenting the subtraction operation
239
+ - Method `Datatype::Number#-` implementing the subtraction operation
225
240
 
226
241
  ### Changed
227
242
  - File `README.md` minor editorial changes.
228
- - File `lx_string_spec.rb` Added test for string concatentation
243
+ - File `lx_string_spec.rb` Added test for string concatenation
229
244
  - File `number_spec.rb` Added tests for addition and subtraction operations
230
245
  - File `interpreter_spec.rb` Added tests for subtraction operation
231
246
 
@@ -12,6 +12,7 @@ require_relative 'lox_logical_expr'
12
12
  require_relative 'lox_assign_expr'
13
13
  require_relative 'lox_block_stmt'
14
14
  require_relative 'lox_while_stmt'
15
+ require_relative 'lox_return_stmt'
15
16
  require_relative 'lox_print_stmt'
16
17
  require_relative 'lox_if_stmt'
17
18
  require_relative 'lox_for_stmt'
@@ -221,6 +221,11 @@ module Loxxy
221
221
  Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
222
222
  end
223
223
 
224
+ # rule('returnStmt' => 'RETURN expression_opt SEMICOLON')
225
+ def reduce_return_stmt(_production, _range, tokens, theChildren)
226
+ Ast::LoxReturnStmt.new(tokens[1].position, theChildren[1])
227
+ end
228
+
224
229
  # rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as ''
225
230
  def reduce_while_stmt(_production, _range, tokens, theChildren)
226
231
  Ast::LoxWhileStmt.new(tokens[1].position, theChildren[2], theChildren[4])
@@ -91,6 +91,14 @@ module Loxxy
91
91
  broadcast(:after_print_stmt, aPrintStmt)
92
92
  end
93
93
 
94
+ # Visit event. The visitor is about to visit a return statement.
95
+ # @param aReturnStmt [AST::LOXReturnStmt] the return statement node to visit
96
+ def visit_return_stmt(aReturnStmt)
97
+ broadcast(:before_return_stmt, aReturnStmt)
98
+ traverse_subnodes(aReturnStmt)
99
+ broadcast(:after_return_stmt, aReturnStmt, self)
100
+ end
101
+
94
102
  # Visit event. The visitor is about to visit a while statement node.
95
103
  # @param aWhileStmt [AST::LOXWhileStmt] the while statement node to visit
96
104
  def visit_while_stmt(aWhileStmt)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lox_compound_expr'
4
+
5
+ module Loxxy
6
+ module Ast
7
+ class LoxReturnStmt < LoxCompoundExpr
8
+ # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
9
+ # @param anExpression [Ast::LoxNode] expression to return
10
+ def initialize(aPosition, anExpression)
11
+ super(aPosition, [anExpression])
12
+ end
13
+
14
+ # Part of the 'visitee' role in Visitor design pattern.
15
+ # @param visitor [Ast::ASTVisitor] the visitor
16
+ def accept(visitor)
17
+ visitor.visit_return_stmt(self)
18
+ end
19
+ end # class
20
+ end # module
21
+ end # module
@@ -19,7 +19,7 @@ module Loxxy
19
19
  # @return [BackEnd::SymbolTable]
20
20
  attr_reader :symbol_table
21
21
 
22
- # @return [Array<Datatype::BuiltinDatatyp>] Stack for the values of expr
22
+ # @return [Array<Datatype::BuiltinDatatype>] Data stack for the expression results
23
23
  attr_reader :stack
24
24
 
25
25
  # @return [Hash { Symbol => UnaryOperator}]
@@ -98,6 +98,10 @@ module Loxxy
98
98
  @ostream.print tos ? tos.to_str : 'nil'
99
99
  end
100
100
 
101
+ def after_return_stmt(_returnStmt, _aVisitor)
102
+ throw(:return)
103
+ end
104
+
101
105
  def after_while_stmt(aWhileStmt, aVisitor)
102
106
  loop do
103
107
  condition = stack.pop
@@ -192,21 +196,32 @@ module Loxxy
192
196
  callee = stack.pop
193
197
  aCallExpr.arguments.reverse_each { |arg| arg.accept(aVisitor) }
194
198
 
195
- if callee.kind_of?(NativeFunction)
199
+ case callee
200
+ when NativeFunction
196
201
  stack.push callee.call # Pass arguments
197
- else
202
+ when Function
198
203
  new_env = Environment.new(symbol_table.current_env)
199
204
  symbol_table.enter_environment(new_env)
200
205
  callee.parameters&.each do |param_name|
201
206
  local = Variable.new(param_name, stack.pop)
202
207
  symbol_table.insert(local)
203
208
  end
204
- callee.call(aVisitor)
209
+ catch(:return) do
210
+ callee.call(aVisitor)
211
+ throw(:return)
212
+ end
205
213
 
206
214
  symbol_table.leave_environment
215
+ else
216
+ raise Loxxy::RuntimeError, 'Can only call functions and classes.'
207
217
  end
208
218
  end
209
219
 
220
+ def complete_call
221
+ callee = ret_stack.pop
222
+ symbol_table.leave_environment if callee.kind_of?(Function)
223
+ end
224
+
210
225
  def after_grouping_expr(_groupingExpr)
211
226
  # Do nothing: work was already done by visiting /evaluating the subexpression
212
227
  end
@@ -255,7 +270,8 @@ module Loxxy
255
270
  negate_op = UnaryOperator.new('-', [Datatype::Number])
256
271
  unary_operators[:-@] = negate_op
257
272
 
258
- negation_op = UnaryOperator.new('!', [Datatype::BuiltinDatatype])
273
+ negation_op = UnaryOperator.new('!', [Datatype::BuiltinDatatype,
274
+ BackEnd::Function])
259
275
  unary_operators[:!] = negation_op
260
276
  end
261
277
 
@@ -34,6 +34,13 @@ module Loxxy
34
34
  body.empty? ? Datatype::Nil.instance : body.accept(aVisitor)
35
35
  end
36
36
 
37
+ # Logical negation.
38
+ # As a function is a truthy thing, its negation is thus false.
39
+ # @return [Datatype::False]
40
+ def !
41
+ Datatype::False.instance
42
+ end
43
+
37
44
  # Text representation of a Lox function
38
45
  def to_str
39
46
  "<fn #{name}>"
@@ -74,7 +74,7 @@ module Loxxy
74
74
  rule('elsePart_opt' => [])
75
75
 
76
76
  rule('printStmt' => 'PRINT expression SEMICOLON').as 'print_stmt'
77
- rule('returnStmt' => 'RETURN expression_opt SEMICOLON')
77
+ rule('returnStmt' => 'RETURN expression_opt SEMICOLON').as 'return_stmt'
78
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').as 'block_empty'
@@ -92,6 +92,7 @@ module Loxxy
92
92
 
93
93
  private
94
94
 
95
+ # rubocop: disable Lint/DuplicateBranch
95
96
  def _next_token
96
97
  skip_intertoken_spaces
97
98
  curr_ch = scanner.peek(1)
@@ -125,6 +126,7 @@ module Loxxy
125
126
 
126
127
  return token
127
128
  end
129
+ # rubocop: enable Lint/DuplicateBranch
128
130
 
129
131
  def build_token(aSymbolName, aLexeme)
130
132
  begin
data/lib/loxxy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.1.03'
4
+ VERSION = '0.1.04'
5
5
  end
@@ -424,6 +424,20 @@ LOX_END
424
424
  expect(sample_cfg[:ostream].string).to eq('<fn foo><native fn>')
425
425
  end
426
426
 
427
+ it 'should support return statements' do
428
+ program = <<-LOX_END
429
+ fun max(a, b) {
430
+ if (a > b) return a;
431
+
432
+ return b;
433
+ }
434
+
435
+ max(3, 2);
436
+ LOX_END
437
+ result = subject.evaluate(program)
438
+ expect(result).to eq(3)
439
+ end
440
+
427
441
  it 'should print the hello world message' do
428
442
  expect { subject.evaluate(hello_world) }.not_to raise_error
429
443
  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.1.03
4
+ version: 0.1.04
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-26 00:00:00.000000000 Z
11
+ date: 2021-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -103,6 +103,7 @@ files:
103
103
  - lib/loxxy/ast/lox_node.rb
104
104
  - lib/loxxy/ast/lox_noop_expr.rb
105
105
  - lib/loxxy/ast/lox_print_stmt.rb
106
+ - lib/loxxy/ast/lox_return_stmt.rb
106
107
  - lib/loxxy/ast/lox_seq_decl.rb
107
108
  - lib/loxxy/ast/lox_unary_expr.rb
108
109
  - lib/loxxy/ast/lox_var_stmt.rb