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 +4 -4
 - data/CHANGELOG.md +6 -0
 - data/lib/loxxy/back_end/engine.rb +4 -4
 - data/lib/loxxy/back_end/lox_class.rb +9 -2
 - data/lib/loxxy/back_end/lox_function.rb +6 -0
 - data/lib/loxxy/back_end/lox_instance.rb +0 -4
 - data/lib/loxxy/back_end/resolver.rb +8 -2
 - data/lib/loxxy/version.rb +1 -1
 - data/spec/interpreter_spec.rb +25 -1
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2c7d720e2638407882bfd3f34384748a872086e1b1f7a3849f0e029e8672fc1c
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c3aa7ebe4a625ef1b0a257cc750430b9a0aa404bb39dab900b409b2987e09dea
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 1eb8bb6575dd39834c55ce3ad359fbdb9a2129f91d25bc39ea093c5a4ca2aa38300ab28e673b39991678c304aea64ffda473707f9d317980b976c8f98fc3a55f
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: d3dd5baae665ab27a60a13b7392e9d57ef32ff72a37892d8f08e314888a1bfcc3db9ceeb071a28c00dda44f4bce7afed6aadf6c33c411a93d561a30fef833edd
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    
| 
         @@ -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 
     | 
    
         
            -
                     
     | 
| 
      
 33 
     | 
    
         
            +
                    initializer = find_method('init')
         
     | 
| 
      
 34 
     | 
    
         
            +
                    initializer ? initializer.arity : 0
         
     | 
| 
       34 
35 
     | 
    
         
             
                  end
         
     | 
| 
       35 
36 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                  def call(engine,  
     | 
| 
      
 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 
     | 
    
         
            -
                       
     | 
| 
      
 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( 
     | 
| 
      
 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
    
    
    
        data/spec/interpreter_spec.rb
    CHANGED
    
    | 
         @@ -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 ( 
     | 
| 
      
 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. 
     | 
| 
      
 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- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2021-04-11 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: rley
         
     |