loxxy 0.1.16 → 0.1.17

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: 60e57ef9264b4239571378ddcbefe044ff63192534ce94fc99b9a3b1c1813f02
4
- data.tar.gz: 94c26f57455d0e267354f68655e86288dd00f5c322df3e4d1b6f5478cad0eb17
3
+ metadata.gz: 2c7d720e2638407882bfd3f34384748a872086e1b1f7a3849f0e029e8672fc1c
4
+ data.tar.gz: c3aa7ebe4a625ef1b0a257cc750430b9a0aa404bb39dab900b409b2987e09dea
5
5
  SHA512:
6
- metadata.gz: 8e5d6f864c1a340aecc7a362d8f2c311dc553869fc72b40d287736df2b62715eb208b2b299f1106dba5645dc4bb859f1d96fbfa79441c83c0e5faa223dd6642d
7
- data.tar.gz: 452f9815e8812d9313c228697410a4c7433ec12c58269da305999f1de2822c89ad0b9a0f4e72865c333ddbee725b0ff102b4bc14ab4c51dcf7dba2784a08074a
6
+ metadata.gz: 1eb8bb6575dd39834c55ce3ad359fbdb9a2129f91d25bc39ea093c5a4ca2aa38300ab28e673b39991678c304aea64ffda473707f9d317980b976c8f98fc3a55f
7
+ data.tar.gz: d3dd5baae665ab27a60a13b7392e9d57ef32ff72a37892d8f08e314888a1bfcc3db9ceeb071a28c00dda44f4bce7afed6aadf6c33c411a93d561a30fef833edd
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.1.17] - 2021-04-11
2
+ - TODO
3
+
4
+ ### Fixed
5
+ - TODO
6
+
1
7
  ## [0.1.16] - 2021-04-10
2
8
  - Fixed an issue in name lookup. All the `this` test suite is passing.
3
9
 
@@ -74,7 +74,9 @@ module Loxxy
74
74
  meths = aClassStmt.body.map do |func_node|
75
75
  func_node.is_method = true
76
76
  func_node.accept(aVisitor)
77
- stack.pop
77
+ mth = stack.pop
78
+ mth.is_initializer = true if mth.name == 'init'
79
+ mth
78
80
  end
79
81
 
80
82
  klass = LoxClass.new(aClassStmt.name, meths, self)
@@ -234,15 +236,13 @@ module Loxxy
234
236
  case callee
235
237
  when NativeFunction
236
238
  stack.push callee.call # Pass arguments
237
- when LoxFunction
239
+ when LoxFunction, LoxClass
238
240
  arg_count = aCallExpr.arguments.size
239
241
  if arg_count != callee.arity
240
242
  msg = "Expected #{callee.arity} arguments but got #{arg_count}."
241
243
  raise Loxxy::RuntimeError, msg
242
244
  end
243
245
  callee.call(self, aVisitor)
244
- when LoxClass
245
- callee.call(self, aVisitor)
246
246
  else
247
247
  raise Loxxy::RuntimeError, 'Can only call functions and classes.'
248
248
  end
@@ -30,11 +30,18 @@ module Loxxy
30
30
  end
31
31
 
32
32
  def arity
33
- 0
33
+ initializer = find_method('init')
34
+ initializer ? initializer.arity : 0
34
35
  end
35
36
 
36
- def call(engine, _visitor)
37
+ def call(engine, visitor)
37
38
  instance = LoxInstance.new(self, engine)
39
+ initializer = find_method('init')
40
+ if initializer
41
+ constructor = initializer.bind(instance)
42
+ constructor.call(engine, visitor)
43
+ end
44
+
38
45
  engine.stack.push(instance)
39
46
  end
40
47
 
@@ -15,6 +15,7 @@ module Loxxy
15
15
  attr_reader :body
16
16
  attr_reader :stack
17
17
  attr_reader :closure
18
+ attr_accessor :is_initializer
18
19
 
19
20
  # Create a function with given name
20
21
  # @param aName [String] The name of the function
@@ -24,6 +25,7 @@ module Loxxy
24
25
  @body = aBody.kind_of?(Ast::LoxNoopExpr) ? aBody : aBody.subnodes[0]
25
26
  @stack = anEngine.stack
26
27
  @closure = anEngine.symbol_table.current_env
28
+ @is_initializer = false
27
29
  anEngine.symbol_table.current_env.embedding = true
28
30
  end
29
31
 
@@ -48,6 +50,10 @@ module Loxxy
48
50
  (body.nil? || body.kind_of?(Ast::LoxNoopExpr)) ? Datatype::Nil.instance : body.accept(aVisitor)
49
51
  throw(:return)
50
52
  end
53
+ if is_initializer
54
+ enclosing_env = engine.symbol_table.current_env.enclosing
55
+ engine.stack.push(enclosing_env.defns['this'].value)
56
+ end
51
57
 
52
58
  engine.symbol_table.leave_environment
53
59
  end
@@ -47,10 +47,6 @@ module Loxxy
47
47
  # Set the value of property with given name
48
48
  # aName [String] name of object property
49
49
  def set(aName, aValue)
50
- unless fields.include? aName
51
- raise StandardError, "Undefined property '#{aName}'."
52
- end
53
-
54
50
  fields[aName] = aValue
55
51
  end
56
52
  end # class
@@ -70,7 +70,8 @@ module Loxxy
70
70
  begin_scope
71
71
  define('this')
72
72
  aClassStmt.body.each do |fun_stmt|
73
- resolve_function(fun_stmt, :method, aVisitor)
73
+ mth_type = fun_stmt.name == 'init' ? :initializer : :method
74
+ resolve_function(fun_stmt, mth_type, aVisitor)
74
75
  end
75
76
  end_scope
76
77
  @current_class = previous_class
@@ -92,7 +93,7 @@ module Loxxy
92
93
  anIfStmt.else_stmt&.accept(aVisitor)
93
94
  end
94
95
 
95
- def before_return_stmt(_returnStmt)
96
+ def before_return_stmt(returnStmt)
96
97
  if scopes.size < 2
97
98
  msg = "Error at 'return': Can't return from top-level code."
98
99
  raise StandardError, msg
@@ -102,6 +103,11 @@ module Loxxy
102
103
  msg = "Error at 'return': Can't return from outside a function."
103
104
  raise StandardError, msg
104
105
  end
106
+
107
+ if current_function == :initializer
108
+ msg = "Error at 'return': Can't return a value from an initializer."
109
+ raise StandardError, msg unless returnStmt.subnodes[0].kind_of?(Datatype::Nil)
110
+ end
105
111
  end
106
112
 
107
113
  def after_while_stmt(aWhileStmt, aVisitor)
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.16'
4
+ VERSION = '0.1.17'
5
5
  end
@@ -543,7 +543,7 @@ LOX_END
543
543
  closure;
544
544
  LOX_END
545
545
  # Expected result: Backend::LoxFunction('closure')
546
- # Expected function's closure ()environment layout):
546
+ # Expected function's closure (environment layout):
547
547
  # Environment('global')
548
548
  # defns
549
549
  # +- ['clock'] => BackEnd::Engine::NativeFunction
@@ -567,6 +567,30 @@ LOX_END
567
567
  expect(global_env.defns['clock'].value).to be_kind_of(BackEnd::Engine::NativeFunction)
568
568
  expect(global_env.defns['Foo'].value).to be_kind_of(BackEnd::LoxClass)
569
569
  end
570
+
571
+ it 'should support custom initializer' do
572
+ lox_snippet = <<-LOX_END
573
+ // From section 3.9.5
574
+ class Breakfast {
575
+ init(meat, bread) {
576
+ this.meat = meat;
577
+ this.bread = bread;
578
+ }
579
+
580
+ serve(who) {
581
+ print "Enjoy your " + this.meat + " and " +
582
+ this.bread + ", " + who + ".";
583
+ }
584
+ }
585
+
586
+ var baconAndToast = Breakfast("bacon", "toast");
587
+ baconAndToast.serve("Dear Reader");
588
+ // Output: "Enjoy your bacon and toast, Dear Reader."
589
+ LOX_END
590
+ expect { subject.evaluate(lox_snippet) }.not_to raise_error
591
+ predicted = 'Enjoy your bacon and toast, Dear Reader.'
592
+ expect(sample_cfg[:ostream].string).to eq(predicted)
593
+ end
570
594
  end # context
571
595
  end # describe
572
596
  # rubocop: enable Metrics/BlockLength
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.16
4
+ version: 0.1.17
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-04-10 00:00:00.000000000 Z
11
+ date: 2021-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley