rlang 0.4.0 → 0.4.1
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 +4 -0
 - data/README.md +12 -2
 - data/docs/RlangManual.md +43 -30
 - data/lib/rlang/lib.rb +2 -1
 - data/lib/rlang/lib/malloc.rb +2 -2
 - data/lib/rlang/lib/memory.rb +18 -0
 - data/lib/rlang/lib/string.rb +30 -0
 - data/lib/rlang/parser.rb +263 -206
 - data/lib/rlang/parser/{wattr.rb → attr.rb} +41 -33
 - data/lib/rlang/parser/data.rb +3 -0
 - data/lib/rlang/parser/ivar.rb +16 -7
 - data/lib/rlang/parser/klass.rb +6 -3
 - data/lib/rlang/parser/method.rb +17 -9
 - data/lib/rlang/parser/wgenerator.rb +168 -47
 - data/lib/rlang/parser/wnode.rb +96 -65
 - data/lib/rlang/version.rb +1 -1
 - metadata +4 -3
 
| 
         @@ -9,61 +9,64 @@ require_relative './ivar' 
     | 
|
| 
       9 
9 
     | 
    
         
             
            require_relative './wtype'
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
            module Rlang::Parser
         
     | 
| 
       12 
     | 
    
         
            -
              class  
     | 
| 
      
 12 
     | 
    
         
            +
              class Attr
         
     | 
| 
       13 
13 
     | 
    
         
             
                include Log
         
     | 
| 
       14 
     | 
    
         
            -
                attr_reader :name, : 
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :name, :getter, :setter, :ivar
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
                # The name argument can either be the attribute name
         
     | 
| 
       17 
17 
     | 
    
         
             
                # (e.g. :size) or an ivar name (e.g. :@size)
         
     | 
| 
       18 
18 
     | 
    
         
             
                def initialize(class_wnode, name, wtype=WType::DEFAULT)
         
     | 
| 
       19 
19 
     | 
    
         
             
                  @class_wnode = class_wnode
         
     | 
| 
       20 
     | 
    
         
            -
                   
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                   
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                  # method objects (with default WType - wattr_type
         
     | 
| 
       30 
     | 
    
         
            -
                  # directives might later change this wtype)
         
     | 
| 
       31 
     | 
    
         
            -
                  # Don't generate WAT code yet
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @ivar = class_wnode.create_ivar(:"@#{name}", wtype)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @getter = nil
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @setter = nil
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @export = false
         
     | 
| 
      
 25 
     | 
    
         
            +
                  logger.debug "Class attribute #{name} created"
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def attr_reader
         
     | 
| 
       32 
29 
     | 
    
         
             
                  @getter = @class_wnode.find_or_create_method(self.getter_name, nil, wtype, :instance)
         
     | 
| 
       33 
     | 
    
         
            -
                  @getter. 
     | 
| 
      
 30 
     | 
    
         
            +
                  @getter.export! if @export
         
     | 
| 
       34 
31 
     | 
    
         
             
                  logger.debug "Getter created: #{@getter.inspect}"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @getter
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
       35 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
                def attr_writer
         
     | 
| 
       36 
36 
     | 
    
         
             
                  @setter = @class_wnode.find_or_create_method(self.setter_name, nil, wtype, :instance)
         
     | 
| 
       37 
     | 
    
         
            -
                  @setter. 
     | 
| 
      
 37 
     | 
    
         
            +
                  @setter.export! if @export
         
     | 
| 
       38 
38 
     | 
    
         
             
                  logger.debug "Setter created: #{@setter.inspect}"
         
     | 
| 
       39 
     | 
    
         
            -
                   
     | 
| 
      
 39 
     | 
    
         
            +
                  @setter
         
     | 
| 
       40 
40 
     | 
    
         
             
                end
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                def  
     | 
| 
       43 
     | 
    
         
            -
                   
     | 
| 
      
 42 
     | 
    
         
            +
                def attr_accessor
         
     | 
| 
      
 43 
     | 
    
         
            +
                  [self.attr_reader, self.attr_writer]
         
     | 
| 
       44 
44 
     | 
    
         
             
                end
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                def  
     | 
| 
       47 
     | 
    
         
            -
                  @ 
     | 
| 
       48 
     | 
    
         
            -
                  # Adjust corresponding method objects wtype accordingly
         
     | 
| 
       49 
     | 
    
         
            -
                  @getter.wtype = wtype
         
     | 
| 
       50 
     | 
    
         
            -
                  @setter.wtype = wtype
         
     | 
| 
       51 
     | 
    
         
            -
                  @ivar.wtype   = wtype
         
     | 
| 
       52 
     | 
    
         
            -
                  logger.debug "WAttr/Getter/Setter/ivar wtype updated : #{@getter.inspect}"
         
     | 
| 
      
 46 
     | 
    
         
            +
                def export!
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @export = true
         
     | 
| 
       53 
48 
     | 
    
         
             
                end
         
     | 
| 
       54 
49 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                def  
     | 
| 
       56 
     | 
    
         
            -
                  @ 
     | 
| 
      
 50 
     | 
    
         
            +
                def class_name
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @class_wnode.class_name
         
     | 
| 
       57 
52 
     | 
    
         
             
                end
         
     | 
| 
       58 
53 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
                def  
     | 
| 
       60 
     | 
    
         
            -
                  @ivar 
     | 
| 
      
 54 
     | 
    
         
            +
                def wtype
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @ivar.wtype
         
     | 
| 
       61 
56 
     | 
    
         
             
                end
         
     | 
| 
       62 
57 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
                def  
     | 
| 
       64 
     | 
    
         
            -
                   
     | 
| 
      
 58 
     | 
    
         
            +
                def offset
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @ivar.offset
         
     | 
| 
       65 
60 
     | 
    
         
             
                end
         
     | 
| 
       66 
61 
     | 
    
         | 
| 
      
 62 
     | 
    
         
            +
                def wtype=(wtype)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # Adjust getter/setter and ivar wtype accordingly
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @getter.wtype = wtype if @getter
         
     | 
| 
      
 65 
     | 
    
         
            +
                  @setter.wtype = wtype if @setter
         
     | 
| 
      
 66 
     | 
    
         
            +
                  @ivar.wtype = wtype
         
     | 
| 
      
 67 
     | 
    
         
            +
                  logger.debug "Attr/Getter/Setter/ivar wtype updated : #{@getter.inspect}"
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       67 
70 
     | 
    
         
             
                def getter_name
         
     | 
| 
       68 
71 
     | 
    
         
             
                  @name
         
     | 
| 
       69 
72 
     | 
    
         
             
                end
         
     | 
| 
         @@ -71,8 +74,13 @@ module Rlang::Parser 
     | 
|
| 
       71 
74 
     | 
    
         
             
                def setter_name
         
     | 
| 
       72 
75 
     | 
    
         
             
                  "#{@name}=".to_sym
         
     | 
| 
       73 
76 
     | 
    
         
             
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def wasm_name
         
     | 
| 
      
 79 
     | 
    
         
            +
                  "$#{@name}"
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
                
         
     | 
| 
       74 
82 
     | 
    
         
             
                def wasm_type
         
     | 
| 
       75 
     | 
    
         
            -
                   
     | 
| 
      
 83 
     | 
    
         
            +
                  self.wtype.wasm_type
         
     | 
| 
       76 
84 
     | 
    
         
             
                end
         
     | 
| 
       77 
85 
     | 
    
         
             
              end
         
     | 
| 
       78 
86 
     | 
    
         
             
            end
         
     | 
    
        data/lib/rlang/parser/data.rb
    CHANGED
    
    | 
         @@ -17,6 +17,9 @@ module Rlang::Parser 
     | 
|
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
                attr_reader :label, :wtype, :address, :value
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                # NOTE: new and append only takes individual DAta values
         
     | 
| 
      
 21 
     | 
    
         
            +
                # not an array of values
         
     | 
| 
      
 22 
     | 
    
         
            +
                # TODO: fix DAta.new and DAta.append not accepting an array of values
         
     | 
| 
       20 
23 
     | 
    
         
             
                def initialize(label, value, wtype=WType::DEFAULT)
         
     | 
| 
       21 
24 
     | 
    
         
             
                  raise "Data label '#{label}' already initialized" \
         
     | 
| 
       22 
25 
     | 
    
         
             
                    if self.class.exist? label
         
     | 
    
        data/lib/rlang/parser/ivar.rb
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            # Copyright (c) 2019, Laurent Julliard and contributors
         
     | 
| 
       3 
3 
     | 
    
         
             
            # All rights reserved.
         
     | 
| 
       4 
4 
     | 
    
         
             
            #
         
     | 
| 
       5 
     | 
    
         
            -
            # Instance variables
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Instance variables class
         
     | 
| 
       6 
6 
     | 
    
         
             
            #
         
     | 
| 
       7 
7 
     | 
    
         
             
            require_relative '../../utils/log'
         
     | 
| 
       8 
8 
     | 
    
         
             
            require_relative './wtype'
         
     | 
| 
         @@ -11,22 +11,31 @@ require_relative './data' 
     | 
|
| 
       11 
11 
     | 
    
         
             
            module Rlang::Parser
         
     | 
| 
       12 
12 
     | 
    
         
             
              class IVar
         
     | 
| 
       13 
13 
     | 
    
         
             
                include Log
         
     | 
| 
       14 
     | 
    
         
            -
                attr_reader :name 
     | 
| 
       15 
     | 
    
         
            -
                attr_accessor :wtype
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :name
         
     | 
| 
      
 15 
     | 
    
         
            +
                attr_accessor :wtype, :offset
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
17 
     | 
    
         
             
                def initialize(class_wnode, name, wtype=WType::DEFAULT)
         
     | 
| 
       18 
     | 
    
         
            -
                  @name = name
         
     | 
| 
       19 
18 
     | 
    
         
             
                  @class_wnode = class_wnode
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @name = name
         
     | 
| 
       20 
20 
     | 
    
         
             
                  @wtype = wtype
         
     | 
| 
       21 
     | 
    
         
            -
                   
     | 
| 
      
 21 
     | 
    
         
            +
                  # this is the offset of the instance variable
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # in memory in the order they are declared
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # It is computed at the end of a class
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # definition
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @offset = nil
         
     | 
| 
      
 26 
     | 
    
         
            +
                  logger.debug "Instance variable #{name} created"
         
     | 
| 
       22 
27 
     | 
    
         
             
                end
         
     | 
| 
       23 
28 
     | 
    
         | 
| 
       24 
29 
     | 
    
         
             
                def class_name
         
     | 
| 
       25 
30 
     | 
    
         
             
                  @class_wnode.class_name
         
     | 
| 
       26 
31 
     | 
    
         
             
                end
         
     | 
| 
       27 
32 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                def  
     | 
| 
       29 
     | 
    
         
            -
                  @ 
     | 
| 
      
 33 
     | 
    
         
            +
                def size
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @wtype.size
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def wasm_name
         
     | 
| 
      
 38 
     | 
    
         
            +
                  "$#{@name}"
         
     | 
| 
       30 
39 
     | 
    
         
             
                end
         
     | 
| 
       31 
40 
     | 
    
         | 
| 
       32 
41 
     | 
    
         
             
                def wasm_type
         
     | 
    
        data/lib/rlang/parser/klass.rb
    CHANGED
    
    | 
         @@ -13,7 +13,8 @@ module Rlang::Parser 
     | 
|
| 
       13 
13 
     | 
    
         
             
                include Log
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                attr_reader :wtype
         
     | 
| 
       16 
     | 
    
         
            -
                attr_accessor :name, :wnode, : 
     | 
| 
      
 16 
     | 
    
         
            +
                attr_accessor :name, :wnode, :attrs, :ivars, :cvars, 
         
     | 
| 
      
 17 
     | 
    
         
            +
                              :consts, :methods, :offset
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
                def initialize(name)
         
     | 
| 
       19 
20 
     | 
    
         
             
                  @name = name
         
     | 
| 
         @@ -23,14 +24,16 @@ module Rlang::Parser 
     | 
|
| 
       23 
24 
     | 
    
         
             
                  # the wnode implementing the code of the class
         
     | 
| 
       24 
25 
     | 
    
         
             
                  @wnode = nil
         
     | 
| 
       25 
26 
     | 
    
         
             
                  logger.debug "Klass created #{self.inspect}"
         
     | 
| 
       26 
     | 
    
         
            -
                  @ 
     | 
| 
      
 27 
     | 
    
         
            +
                  @attrs  = [] # class attributes
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @ivars   = [] # instance variables
         
     | 
| 
       27 
29 
     | 
    
         
             
                  @cvars   = [] # class variables
         
     | 
| 
       28 
30 
     | 
    
         
             
                  @consts  = [] # class constants
         
     | 
| 
       29 
31 
     | 
    
         
             
                  @methods = [] # methods
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @offset  = 0  # offset of the next class attribute in memory
         
     | 
| 
       30 
33 
     | 
    
         
             
                end
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
       32 
35 
     | 
    
         
             
                def size
         
     | 
| 
       33 
     | 
    
         
            -
                   
     | 
| 
      
 36 
     | 
    
         
            +
                  @offset
         
     | 
| 
       34 
37 
     | 
    
         
             
                end
         
     | 
| 
       35 
38 
     | 
    
         | 
| 
       36 
39 
     | 
    
         
             
                def wtype=(wtype)
         
     | 
    
        data/lib/rlang/parser/method.rb
    CHANGED
    
    | 
         @@ -16,32 +16,40 @@ module Rlang::Parser 
     | 
|
| 
       16 
16 
     | 
    
         
             
                attr_reader :name, :wtype
         
     | 
| 
       17 
17 
     | 
    
         
             
                attr_accessor :class_name, :margs, :lvars, :wnode
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
      
 19 
     | 
    
         
            +
                METHOD_TYPES = [:class, :instance]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def initialize(name, class_name, wtype, method_type)
         
     | 
| 
       20 
22 
     | 
    
         
             
                  raise "Wrong method wtype argument: #{wtype.inspect}" unless wtype.is_a? WType
         
     | 
| 
       21 
23 
     | 
    
         
             
                  @name = name
         
     | 
| 
       22 
24 
     | 
    
         
             
                  @class_name = class_name
         
     | 
| 
       23 
     | 
    
         
            -
                  @wtype = wtype
         
     | 
| 
       24 
     | 
    
         
            -
                  @ 
     | 
| 
      
 25 
     | 
    
         
            +
                  @wtype = wtype || WType::DEFAULT
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @method_type = method_type
         
     | 
| 
      
 27 
     | 
    
         
            +
                  raise "Unknown method type: #{method_type}" unless METHOD_TYPES.include? @method_type
         
     | 
| 
       25 
28 
     | 
    
         
             
                  @wnode = nil # wnode where method is implemented
         
     | 
| 
       26 
29 
     | 
    
         
             
                  logger.debug "Method created #{self.inspect}"
         
     | 
| 
       27 
30 
     | 
    
         
             
                  @margs = []   # method args
         
     | 
| 
       28 
31 
     | 
    
         
             
                  @lvars = []   # local variables
         
     | 
| 
       29 
32 
     | 
    
         
             
                end
         
     | 
| 
       30 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
                def implemented?
         
     | 
| 
      
 35 
     | 
    
         
            +
                  !@wnode.nil?
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
       31 
38 
     | 
    
         
             
                def instance!
         
     | 
| 
       32 
     | 
    
         
            -
                  @ 
     | 
| 
      
 39 
     | 
    
         
            +
                  @method_type = :instance
         
     | 
| 
       33 
40 
     | 
    
         
             
                end
         
     | 
| 
       34 
41 
     | 
    
         | 
| 
       35 
42 
     | 
    
         
             
                def instance?
         
     | 
| 
       36 
     | 
    
         
            -
                  @instance
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @method_type == :instance
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
       37 
45 
     | 
    
         
             
                end
         
     | 
| 
       38 
46 
     | 
    
         | 
| 
       39 
47 
     | 
    
         
             
                def class!
         
     | 
| 
       40 
     | 
    
         
            -
                  @ 
     | 
| 
      
 48 
     | 
    
         
            +
                  @method_type = :class
         
     | 
| 
       41 
49 
     | 
    
         
             
                end
         
     | 
| 
       42 
50 
     | 
    
         | 
| 
       43 
51 
     | 
    
         
             
                def class?
         
     | 
| 
       44 
     | 
    
         
            -
                   
     | 
| 
      
 52 
     | 
    
         
            +
                  @method_type == :class
         
     | 
| 
       45 
53 
     | 
    
         
             
                end
         
     | 
| 
       46 
54 
     | 
    
         | 
| 
       47 
55 
     | 
    
         
             
                def wtype=(wtype)
         
     | 
| 
         @@ -50,7 +58,7 @@ module Rlang::Parser 
     | 
|
| 
       50 
58 
     | 
    
         
             
                end
         
     | 
| 
       51 
59 
     | 
    
         | 
| 
       52 
60 
     | 
    
         
             
                def wasm_name
         
     | 
| 
       53 
     | 
    
         
            -
                  if  
     | 
| 
      
 61 
     | 
    
         
            +
                  if self.instance?
         
     | 
| 
       54 
62 
     | 
    
         
             
                    "$#{@class_name}##{@name}"
         
     | 
| 
       55 
63 
     | 
    
         
             
                  else
         
     | 
| 
       56 
64 
     | 
    
         
             
                    "$#{@class_name}::#{@name}"
         
     | 
| 
         @@ -62,7 +70,7 @@ module Rlang::Parser 
     | 
|
| 
       62 
70 
     | 
    
         
             
                end
         
     | 
| 
       63 
71 
     | 
    
         | 
| 
       64 
72 
     | 
    
         
             
                def export_name
         
     | 
| 
       65 
     | 
    
         
            -
                  if  
     | 
| 
      
 73 
     | 
    
         
            +
                  if self.instance?
         
     | 
| 
       66 
74 
     | 
    
         
             
                    "#{@class_name.downcase}_i_#{@name}"
         
     | 
| 
       67 
75 
     | 
    
         
             
                  else
         
     | 
| 
       68 
76 
     | 
    
         
             
                    "#{@class_name.downcase}_c_#{@name}"
         
     | 
| 
         @@ -50,6 +50,8 @@ module Rlang::Parser 
     | 
|
| 
       50 
50 
     | 
    
         
             
                :'!'   => :eqz
         
     | 
| 
       51 
51 
     | 
    
         
             
              }
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
      
 53 
     | 
    
         
            +
              ALL_OPS_MAP = [*ARITHMETIC_OPS_MAP, *RELATIONAL_OPS_MAP, *BOOLEAN_OPS_MAP, *UNARY_OPS_MAP].to_h
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       53 
55 
     | 
    
         
             
              # Matrix of how to cast a WASM type to another
         
     | 
| 
       54 
56 
     | 
    
         
             
              CAST_OPS = {
         
     | 
| 
       55 
57 
     | 
    
         
             
                I32: { I32: :cast_nope, I64: :cast_extend, F32: :cast_notyet, F64: :cast_notyet, Class: :cast_wtype, none: :cast_error},
         
     | 
| 
         @@ -60,6 +62,9 @@ module Rlang::Parser 
     | 
|
| 
       60 
62 
     | 
    
         
             
                none: { I32: :cast_error, I64: :cast_error, F32: :cast_error, F64: :cast_error, Class: :cast_error, none: :cast_error},
         
     | 
| 
       61 
63 
     | 
    
         
             
              }
         
     | 
| 
       62 
64 
     | 
    
         | 
| 
      
 65 
     | 
    
         
            +
              # Rlang class size method name
         
     | 
| 
      
 66 
     | 
    
         
            +
              SIZE_METHOD = :_size_
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
       63 
68 
     | 
    
         
             
              # new template when object size > 0
         
     | 
| 
       64 
69 
     | 
    
         
             
              NEW_TMPL = %q{
         
     | 
| 
       65 
70 
     | 
    
         
             
              result :Object, :alloc, :%{default_wtype}
         
     | 
| 
         @@ -71,7 +76,7 @@ module Rlang::Parser 
     | 
|
| 
       71 
76 
     | 
    
         
             
              end
         
     | 
| 
       72 
77 
     | 
    
         
             
              }
         
     | 
| 
       73 
78 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
              # new template when object size  
     | 
| 
      
 79 
     | 
    
         
            +
              # new template when object size is 0 (no instance var)
         
     | 
| 
       75 
80 
     | 
    
         
             
              # use 0 as the _self_ address in memory. It should never
         
     | 
| 
       76 
81 
     | 
    
         
             
              # be used anyway
         
     | 
| 
       77 
82 
     | 
    
         
             
              NEW_ZERO_TMPL = %q{
         
     | 
| 
         @@ -91,6 +96,11 @@ module Rlang::Parser 
     | 
|
| 
       91 
96 
     | 
    
         
             
              end
         
     | 
| 
       92 
97 
     | 
    
         
             
              }
         
     | 
| 
       93 
98 
     | 
    
         | 
| 
      
 99 
     | 
    
         
            +
              # Dynamically allocate a string object
         
     | 
| 
      
 100 
     | 
    
         
            +
              STRING_NEW_TMPL = %q{
         
     | 
| 
      
 101 
     | 
    
         
            +
                String.new(%{ptr}, %{length})
         
     | 
| 
      
 102 
     | 
    
         
            +
              }
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
       94 
104 
     | 
    
         
             
              # Generate the wasm nodes and tree structure
         
     | 
| 
       95 
105 
     | 
    
         
             
              # ***IMPORTANT NOTE***
         
     | 
| 
       96 
106 
     | 
    
         
             
              # Unless otherwise stated all methods receive
         
     | 
| 
         @@ -106,6 +116,7 @@ module Rlang::Parser 
     | 
|
| 
       106 
116 
     | 
    
         
             
                  @parser = parser
         
     | 
| 
       107 
117 
     | 
    
         
             
                  @root = WTree.new().root
         
     | 
| 
       108 
118 
     | 
    
         
             
                  @new_count = 0
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @static_count = 0
         
     | 
| 
       109 
120 
     | 
    
         
             
                end
         
     | 
| 
       110 
121 
     | 
    
         | 
| 
       111 
122 
     | 
    
         
             
                def klass(wnode, class_name)
         
     | 
| 
         @@ -118,22 +129,51 @@ module Rlang::Parser 
     | 
|
| 
       118 
129 
     | 
    
         
             
                  k.wnode
         
     | 
| 
       119 
130 
     | 
    
         
             
                end
         
     | 
| 
       120 
131 
     | 
    
         | 
| 
       121 
     | 
    
         
            -
                 
     | 
| 
      
 132 
     | 
    
         
            +
                # Postprocess ivars
         
     | 
| 
      
 133 
     | 
    
         
            +
                # (called at end of class parsing)
         
     | 
| 
      
 134 
     | 
    
         
            +
                def ivars_setup(wnode)
         
     | 
| 
       122 
135 
     | 
    
         
             
                  wnc = wnode.class_wnode
         
     | 
| 
       123 
     | 
    
         
            -
                   
     | 
| 
       124 
     | 
    
         
            -
                   
     | 
| 
       125 
     | 
    
         
            -
                   
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
      
 136 
     | 
    
         
            +
                  raise "Cannot find class for attributes definition!!" unless wnc
         
     | 
| 
      
 137 
     | 
    
         
            +
                  klass = wnc.klass
         
     | 
| 
      
 138 
     | 
    
         
            +
                  logger.debug "Postprocessing ivars for class #{klass.name}..."
         
     | 
| 
      
 139 
     | 
    
         
            +
                  klass.ivars.each do |iv|
         
     | 
| 
      
 140 
     | 
    
         
            +
                    iv.offset = klass.offset
         
     | 
| 
      
 141 
     | 
    
         
            +
                    logger.debug "... ivar #{iv.name} has offset #{iv.offset}"
         
     | 
| 
      
 142 
     | 
    
         
            +
                    # Update offset for next ivar
         
     | 
| 
      
 143 
     | 
    
         
            +
                    klass.offset += iv.size
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                # generate code for class attributes
         
     | 
| 
      
 148 
     | 
    
         
            +
                # (called at end of class parsing)
         
     | 
| 
      
 149 
     | 
    
         
            +
                def def_attr(wnode)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  wnc = wnode.class_wnode
         
     | 
| 
      
 151 
     | 
    
         
            +
                  raise "Cannot find class for attributes definition!!" unless wnc
         
     | 
| 
      
 152 
     | 
    
         
            +
                  # Process each declared class attribute
         
     | 
| 
      
 153 
     | 
    
         
            +
                  wnc.klass.attrs.each do |attr|
         
     | 
| 
      
 154 
     | 
    
         
            +
                    logger.debug("Generating accessors for attribute #{wnc.klass.name}\##{attr.name}")
         
     | 
| 
       127 
155 
     | 
    
         
             
                    # Generate getter and setter methods wnode
         
     | 
| 
       128 
     | 
    
         
            -
                     
     | 
| 
       129 
     | 
    
         
            -
                     
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
      
 156 
     | 
    
         
            +
                    # unless method already implemented by user
         
     | 
| 
      
 157 
     | 
    
         
            +
                    if attr.setter
         
     | 
| 
      
 158 
     | 
    
         
            +
                      unless attr.setter.implemented?
         
     | 
| 
      
 159 
     | 
    
         
            +
                        attr.setter.wnode = self.attr_setter(wnc, attr)
         
     | 
| 
      
 160 
     | 
    
         
            +
                      else
         
     | 
| 
      
 161 
     | 
    
         
            +
                        logger.debug "Attribute setter #{attr.setter.name} already defined. Skipping"
         
     | 
| 
      
 162 
     | 
    
         
            +
                      end
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
                    if attr.getter
         
     | 
| 
      
 165 
     | 
    
         
            +
                      unless attr.getter.implemented?
         
     | 
| 
      
 166 
     | 
    
         
            +
                        attr.getter.wnode = self.attr_getter(wnc, attr)
         
     | 
| 
      
 167 
     | 
    
         
            +
                      else
         
     | 
| 
      
 168 
     | 
    
         
            +
                        logger.debug "Attribute getter #{attr.getter.name} already defined. Skipping"
         
     | 
| 
      
 169 
     | 
    
         
            +
                      end
         
     | 
| 
      
 170 
     | 
    
         
            +
                    end
         
     | 
| 
       132 
171 
     | 
    
         
             
                  end
         
     | 
| 
       133 
172 
     | 
    
         | 
| 
       134 
173 
     | 
    
         
             
                  # Also generate the Class::_size_ method
         
     | 
| 
       135 
     | 
    
         
            -
                  #  
     | 
| 
       136 
     | 
    
         
            -
                   
     | 
| 
      
 174 
     | 
    
         
            +
                  # (needed for dynamic memory allocation
         
     | 
| 
      
 175 
     | 
    
         
            +
                  #  by Object.allocate)
         
     | 
| 
      
 176 
     | 
    
         
            +
                  size_method = wnc.find_or_create_method(SIZE_METHOD, wnc.klass.name, WType::DEFAULT, :class)
         
     | 
| 
       137 
177 
     | 
    
         
             
                  unless size_method.wnode
         
     | 
| 
       138 
178 
     | 
    
         
             
                    logger.debug("Generating #{size_method.class_name}\##{size_method.name}")
         
     | 
| 
       139 
179 
     | 
    
         
             
                    wns = WNode.new(:insn, wnc, true)
         
     | 
| 
         @@ -145,22 +185,22 @@ module Rlang::Parser 
     | 
|
| 
       145 
185 
     | 
    
         
             
                end
         
     | 
| 
       146 
186 
     | 
    
         | 
| 
       147 
187 
     | 
    
         
             
                # Generate attribute setter method wnode
         
     | 
| 
       148 
     | 
    
         
            -
                def  
     | 
| 
      
 188 
     | 
    
         
            +
                def attr_setter(wnode, attr)
         
     | 
| 
       149 
189 
     | 
    
         
             
                  wnc = wnode.class_wnode
         
     | 
| 
       150 
190 
     | 
    
         
             
                  wn_set = WNode.new(:insn, wnc, true)
         
     | 
| 
       151 
     | 
    
         
            -
                  wn_set.c(: 
     | 
| 
       152 
     | 
    
         
            -
                         
     | 
| 
       153 
     | 
    
         
            -
                        offset: offset)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  wn_set.c(:attr_setter, func_name: attr.setter.wasm_name, 
         
     | 
| 
      
 192 
     | 
    
         
            +
                        attr_name: attr.wasm_name, wtype: attr.wasm_type,
         
     | 
| 
      
 193 
     | 
    
         
            +
                        offset: attr.offset)
         
     | 
| 
       154 
194 
     | 
    
         
             
                  wn_set
         
     | 
| 
       155 
195 
     | 
    
         
             
                end
         
     | 
| 
       156 
196 
     | 
    
         | 
| 
       157 
197 
     | 
    
         
             
                # Generate attribute getter method wnode
         
     | 
| 
       158 
     | 
    
         
            -
                def  
     | 
| 
      
 198 
     | 
    
         
            +
                def attr_getter(wnode, attr)
         
     | 
| 
       159 
199 
     | 
    
         
             
                  wnc = wnode.class_wnode
         
     | 
| 
       160 
200 
     | 
    
         
             
                  wn_get = WNode.new(:insn, wnc, true)
         
     | 
| 
       161 
     | 
    
         
            -
                  wn_get.c(: 
     | 
| 
       162 
     | 
    
         
            -
                         
     | 
| 
       163 
     | 
    
         
            -
                        offset: offset)
         
     | 
| 
      
 201 
     | 
    
         
            +
                  wn_get.c(:attr_getter, func_name: attr.getter.wasm_name, 
         
     | 
| 
      
 202 
     | 
    
         
            +
                        attr_name: attr.wasm_name, wtype: attr.wasm_type,
         
     | 
| 
      
 203 
     | 
    
         
            +
                        offset: attr.offset)
         
     | 
| 
       164 
204 
     | 
    
         
             
                  wn_get
         
     | 
| 
       165 
205 
     | 
    
         
             
                end
         
     | 
| 
       166 
206 
     | 
    
         | 
| 
         @@ -225,11 +265,12 @@ module Rlang::Parser 
     | 
|
| 
       225 
265 
     | 
    
         
             
                  wn    
         
     | 
| 
       226 
266 
     | 
    
         
             
                end
         
     | 
| 
       227 
267 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                # Set  
     | 
| 
       229 
     | 
    
         
            -
                # Constant assignment doesn't generate any code
         
     | 
| 
       230 
     | 
    
         
            -
                # A Data object is instantiated and initialized
         
     | 
| 
       231 
     | 
    
         
            -
                # when the Const object is created in parser
         
     | 
| 
      
 268 
     | 
    
         
            +
                # Set constant
         
     | 
| 
       232 
269 
     | 
    
         
             
                def casgn(wnode, const)
         
     | 
| 
      
 270 
     | 
    
         
            +
                  (wn = WNode.new(:insn, wnode)).wtype = const.wtype
         
     | 
| 
      
 271 
     | 
    
         
            +
                  wn.c(:store, wtype: const.wtype)
         
     | 
| 
      
 272 
     | 
    
         
            +
                  WNode.new(:insn, wn).c(:addr, value: const.address)
         
     | 
| 
      
 273 
     | 
    
         
            +
                  wn
         
     | 
| 
       233 
274 
     | 
    
         
             
                end
         
     | 
| 
       234 
275 
     | 
    
         | 
| 
       235 
276 
     | 
    
         
             
                # Get class variable
         
     | 
| 
         @@ -254,34 +295,38 @@ module Rlang::Parser 
     | 
|
| 
       254 
295 
     | 
    
         
             
                  wn
         
     | 
| 
       255 
296 
     | 
    
         
             
                end
         
     | 
| 
       256 
297 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                # Call setter (on  
     | 
| 
      
 298 
     | 
    
         
            +
                # Call setter (on attr or instance variable)
         
     | 
| 
       258 
299 
     | 
    
         
             
                # This is the same as calling the corresponding setter
         
     | 
| 
       259 
     | 
    
         
            -
                def call_setter(wnode, wnode_recv,  
     | 
| 
       260 
     | 
    
         
            -
                  wn = self.call(wnode, wnode_recv.wtype.name,  
     | 
| 
      
 300 
     | 
    
         
            +
                def call_setter(wnode, wnode_recv, attr)
         
     | 
| 
      
 301 
     | 
    
         
            +
                  wn = self.call(wnode, wnode_recv.wtype.name, attr.setter_name, :instance)
         
     | 
| 
       261 
302 
     | 
    
         
             
                  # First argument of the setter must be the receiver
         
     | 
| 
       262 
303 
     | 
    
         
             
                  wnode_recv.reparent_to(wn)
         
     | 
| 
       263 
304 
     | 
    
         
             
                  wn
         
     | 
| 
       264 
305 
     | 
    
         
             
                end
         
     | 
| 
       265 
306 
     | 
    
         | 
| 
       266 
     | 
    
         
            -
                # Call getter (on  
     | 
| 
      
 307 
     | 
    
         
            +
                # Call getter (on attr or instance variable)
         
     | 
| 
       267 
308 
     | 
    
         
             
                # This is the same as calling the corresponding getter
         
     | 
| 
       268 
     | 
    
         
            -
                def call_getter(wnode, wnode_recv,  
     | 
| 
       269 
     | 
    
         
            -
                  wn = self.call(wnode, wnode_recv.wtype.name,  
     | 
| 
      
 309 
     | 
    
         
            +
                def call_getter(wnode, wnode_recv, attr)
         
     | 
| 
      
 310 
     | 
    
         
            +
                  wn = self.call(wnode, wnode_recv.wtype.name, attr.getter_name, :instance)
         
     | 
| 
       270 
311 
     | 
    
         
             
                  # First argument of the getter must always be the receiver
         
     | 
| 
       271 
312 
     | 
    
         
             
                  wnode_recv.reparent_to(wn)
         
     | 
| 
       272 
313 
     | 
    
         
             
                  wn
         
     | 
| 
       273 
314 
     | 
    
         
             
                end
         
     | 
| 
       274 
315 
     | 
    
         | 
| 
       275 
316 
     | 
    
         
             
                # Set instance variable
         
     | 
| 
       276 
     | 
    
         
            -
                 
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
     | 
    
         
            -
                   
     | 
| 
      
 317 
     | 
    
         
            +
                def ivasgn(wnode, ivar)
         
     | 
| 
      
 318 
     | 
    
         
            +
                  (wn = WNode.new(:insn, wnode)).wtype = ivar.wtype
         
     | 
| 
      
 319 
     | 
    
         
            +
                  wn.c(:store_offset, wtype: ivar.wasm_type, offset: lambda { ivar.offset })
         
     | 
| 
      
 320 
     | 
    
         
            +
                  self._self_(wn)
         
     | 
| 
      
 321 
     | 
    
         
            +
                  wn
         
     | 
| 
       279 
322 
     | 
    
         
             
                end
         
     | 
| 
       280 
323 
     | 
    
         | 
| 
       281 
324 
     | 
    
         
             
                # Get instance variable. 
         
     | 
| 
       282 
     | 
    
         
            -
                 
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
                   
     | 
| 
      
 325 
     | 
    
         
            +
                def ivar(wnode, ivar)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  (wn = WNode.new(:insn, wnode)).wtype = ivar.wtype
         
     | 
| 
      
 327 
     | 
    
         
            +
                  wn.c(:load_offset, wtype: ivar.wasm_type, offset: lambda { ivar.offset })
         
     | 
| 
      
 328 
     | 
    
         
            +
                  self._self_(wn)
         
     | 
| 
      
 329 
     | 
    
         
            +
                  wn
         
     | 
| 
       285 
330 
     | 
    
         
             
                end
         
     | 
| 
       286 
331 
     | 
    
         | 
| 
       287 
332 
     | 
    
         
             
                # Set class variable
         
     | 
| 
         @@ -339,6 +384,52 @@ module Rlang::Parser 
     | 
|
| 
       339 
384 
     | 
    
         
             
                  wn
         
     | 
| 
       340 
385 
     | 
    
         
             
                end
         
     | 
| 
       341 
386 
     | 
    
         | 
| 
      
 387 
     | 
    
         
            +
                # Generate a phony node (generally used to create 
         
     | 
| 
      
 388 
     | 
    
         
            +
                # a wnode subtree under the phony node and later
         
     | 
| 
      
 389 
     | 
    
         
            +
                # reparent it to the proper place in the wtree)
         
     | 
| 
      
 390 
     | 
    
         
            +
                def phony(wnode)
         
     | 
| 
      
 391 
     | 
    
         
            +
                  phony = WNode.new(:none, wnode)
         
     | 
| 
      
 392 
     | 
    
         
            +
                  phony
         
     | 
| 
      
 393 
     | 
    
         
            +
                end
         
     | 
| 
      
 394 
     | 
    
         
            +
             
     | 
| 
      
 395 
     | 
    
         
            +
                # Static string allocation
         
     | 
| 
      
 396 
     | 
    
         
            +
                def string_static(string, data_label)
         
     | 
| 
      
 397 
     | 
    
         
            +
                  # Allocate string itself and the attributes
         
     | 
| 
      
 398 
     | 
    
         
            +
                  # of String object pointing to that string
         
     | 
| 
      
 399 
     | 
    
         
            +
                  data_stg = DAta.append(data_label.to_sym, string)
         
     | 
| 
      
 400 
     | 
    
         
            +
                  data_stg
         
     | 
| 
      
 401 
     | 
    
         
            +
                end
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                # Static new string object
         
     | 
| 
      
 404 
     | 
    
         
            +
                def string_static_new(wnode, string)
         
     | 
| 
      
 405 
     | 
    
         
            +
                  klass = wnode.find_class(nil)
         
     | 
| 
      
 406 
     | 
    
         
            +
                  data_label = "#{klass.name}_string_#{@static_count += 1}"
         
     | 
| 
      
 407 
     | 
    
         
            +
                  # Statically 
         
     | 
| 
      
 408 
     | 
    
         
            +
                  data_stg = self.string_static(string, data_label)
         
     | 
| 
      
 409 
     | 
    
         
            +
                  # align on :I32 boundary
         
     | 
| 
      
 410 
     | 
    
         
            +
                  DAta.align(4)
         
     | 
| 
      
 411 
     | 
    
         
            +
                  data_len = DAta.append("#{data_label}_len".to_sym, string.length, WType::DEFAULT)
         
     | 
| 
      
 412 
     | 
    
         
            +
                  data_ptr = DAta.append("#{data_label}_ptr".to_sym, data_stg.address, WType::DEFAULT)
         
     | 
| 
      
 413 
     | 
    
         
            +
                  # Generate address wnode
         
     | 
| 
      
 414 
     | 
    
         
            +
                  (wn_object_addr = WNode.new(:insn, wnode)).c(:addr, value: data_len.address)
         
     | 
| 
      
 415 
     | 
    
         
            +
                  wn_object_addr.wtype = WType.new(:String)
         
     | 
| 
      
 416 
     | 
    
         
            +
                  wn_object_addr
         
     | 
| 
      
 417 
     | 
    
         
            +
                end
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
                # Dynamic new string object
         
     | 
| 
      
 420 
     | 
    
         
            +
                def string_dynamic_new(wnode, string)
         
     | 
| 
      
 421 
     | 
    
         
            +
                  klass = wnode.find_class(nil)
         
     | 
| 
      
 422 
     | 
    
         
            +
                  data_label = "#{klass.name}_string_#{@static_count += 1}"
         
     | 
| 
      
 423 
     | 
    
         
            +
                  data_stg = self.string_static(string, data_label)
         
     | 
| 
      
 424 
     | 
    
         
            +
                  string_new_source = STRING_NEW_TMPL % {
         
     | 
| 
      
 425 
     | 
    
         
            +
                    string: string,
         
     | 
| 
      
 426 
     | 
    
         
            +
                    ptr: data_stg.address,
         
     | 
| 
      
 427 
     | 
    
         
            +
                    length: string.length
         
     | 
| 
      
 428 
     | 
    
         
            +
                  }
         
     | 
| 
      
 429 
     | 
    
         
            +
                  #puts string_new_source;exit
         
     | 
| 
      
 430 
     | 
    
         
            +
                  wn_string = self.parser.parse(string_new_source, wnode)
         
     | 
| 
      
 431 
     | 
    
         
            +
                end
         
     | 
| 
      
 432 
     | 
    
         
            +
             
     | 
| 
       342 
433 
     | 
    
         
             
                # All the cast_xxxx methods below returns
         
     | 
| 
       343 
434 
     | 
    
         
             
                # the new wnode doing the cast operation
         
     | 
| 
       344 
435 
     | 
    
         
             
                # or the same wnode if there is no additional code
         
     | 
| 
         @@ -402,27 +493,44 @@ module Rlang::Parser 
     | 
|
| 
       402 
493 
     | 
    
         
             
                # TODO: simplify this complex method (possibly by using
         
     | 
| 
       403 
494 
     | 
    
         
             
                # a conversion table source type -> destination type)
         
     | 
| 
       404 
495 
     | 
    
         
             
                def cast(wnode, wtype, signed=false)
         
     | 
| 
       405 
     | 
    
         
            -
                  logger.debug "wnode: #{wnode}, wtype: #{wtype}"
         
     | 
| 
      
 496 
     | 
    
         
            +
                  logger.debug "Casting wnode: #{wnode}, wtype: #{wtype}, wnode ID: #{wnode.object_id}"
         
     | 
| 
       406 
497 
     | 
    
         
             
                  src_type  = (wnode.wtype.native? ? wnode.wtype.name : :Class)
         
     | 
| 
       407 
498 
     | 
    
         
             
                  dest_type = (wtype.native? ? wtype.name : :Class)
         
     | 
| 
       408 
499 
     | 
    
         
             
                  cast_method = CAST_OPS[src_type] && CAST_OPS[src_type][dest_type] || :cast_error
         
     | 
| 
       409 
     | 
    
         
            -
             
     | 
| 
      
 500 
     | 
    
         
            +
                  logger.debug "Calling cast method: #{cast_method}"
         
     | 
| 
       410 
501 
     | 
    
         
             
                  wn_cast_op = self.send(cast_method, wnode, wtype, signed)
         
     | 
| 
       411 
     | 
    
         
            -
                  logger.debug "After type cast: wnode: #{wn_cast_op}, wtype: #{wtype}"
         
     | 
| 
      
 502 
     | 
    
         
            +
                  logger.debug "After type cast: wnode: #{wn_cast_op}, wtype: #{wtype}, wnode ID: #{wn_cast_op.object_id}"
         
     | 
| 
       412 
503 
     | 
    
         
             
                  wn_cast_op
         
     | 
| 
       413 
504 
     | 
    
         
             
                end
         
     | 
| 
       414 
505 
     | 
    
         | 
| 
      
 506 
     | 
    
         
            +
                # before generating native operator Wasm code check
         
     | 
| 
      
 507 
     | 
    
         
            +
                # if the operator was overloaded
         
     | 
| 
      
 508 
     | 
    
         
            +
                def send_method(wnode, method_name, wtype=WType.new(:none))
         
     | 
| 
      
 509 
     | 
    
         
            +
                  class_name = wtype.name
         
     | 
| 
      
 510 
     | 
    
         
            +
                  if wnode.find_method(method_name, class_name, :instance)
         
     | 
| 
      
 511 
     | 
    
         
            +
                    # it's an instance method call
         
     | 
| 
      
 512 
     | 
    
         
            +
                    logger.debug "Overloaded operator #{method_name} found in class #{class_name}"
         
     | 
| 
      
 513 
     | 
    
         
            +
                    wn_op = self.call(wnode, class_name, method_name, :instance)
         
     | 
| 
      
 514 
     | 
    
         
            +
                  else
         
     | 
| 
      
 515 
     | 
    
         
            +
                    # it's a native Wasm operator
         
     | 
| 
      
 516 
     | 
    
         
            +
                    if ALL_OPS_MAP.has_key? method_name
         
     | 
| 
      
 517 
     | 
    
         
            +
                      wn_op = self.native_operator(wnode, method_name, wtype)
         
     | 
| 
      
 518 
     | 
    
         
            +
                    else
         
     | 
| 
      
 519 
     | 
    
         
            +
                      raise "Unknown method '#{method_name}' in class #{class_name}"
         
     | 
| 
      
 520 
     | 
    
         
            +
                    end
         
     | 
| 
      
 521 
     | 
    
         
            +
                  end
         
     | 
| 
      
 522 
     | 
    
         
            +
                  wn_op
         
     | 
| 
      
 523 
     | 
    
         
            +
                end
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
       415 
525 
     | 
    
         
             
                # just create a wnode for the WASM operator
         
     | 
| 
       416 
526 
     | 
    
         
             
                # Do not set wtype or a code template yet,
         
     | 
| 
       417 
527 
     | 
    
         
             
                # wait until operands type is known (see
         
     | 
| 
       418 
528 
     | 
    
         
             
                # operands below)
         
     | 
| 
       419 
     | 
    
         
            -
                def  
     | 
| 
       420 
     | 
    
         
            -
                  if (op =  
     | 
| 
       421 
     | 
    
         
            -
                            RELATIONAL_OPS_MAP[operator] ||
         
     | 
| 
       422 
     | 
    
         
            -
                            BOOLEAN_OPS_MAP[operator]    ||
         
     | 
| 
       423 
     | 
    
         
            -
                            UNARY_OPS_MAP[operator]  ))
         
     | 
| 
      
 529 
     | 
    
         
            +
                def native_operator(wnode, operator, wtype=WType.new(:none))
         
     | 
| 
      
 530 
     | 
    
         
            +
                  if (op = ALL_OPS_MAP[operator])
         
     | 
| 
       424 
531 
     | 
    
         
             
                    (wn_op = WNode.new(:insn, wnode)).c(:operator, operator: op)
         
     | 
| 
       425 
532 
     | 
    
         
             
                    wn_op.wtype = wtype
         
     | 
| 
      
 533 
     | 
    
         
            +
                    logger.debug "Creating operator #{operator} wnode: #{wn_op}"
         
     | 
| 
       426 
534 
     | 
    
         
             
                    wn_op
         
     | 
| 
       427 
535 
     | 
    
         
             
                  else
         
     | 
| 
       428 
536 
     | 
    
         
             
                    raise "operator '#{operator}' not supported"
         
     | 
| 
         @@ -432,8 +540,21 @@ module Rlang::Parser 
     | 
|
| 
       432 
540 
     | 
    
         
             
                # finish the setting of the operator node and
         
     | 
| 
       433 
541 
     | 
    
         
             
                # attach operands
         
     | 
| 
       434 
542 
     | 
    
         
             
                def operands(wnode_op, wnode_recv, wnode_args)
         
     | 
| 
      
 543 
     | 
    
         
            +
                  logger.debug "Processing operands in operator wnode: #{wnode_op}..."
         
     | 
| 
      
 544 
     | 
    
         
            +
                  # Do not post process operands if the operator
         
     | 
| 
      
 545 
     | 
    
         
            +
                  # wnode is a call (= overloaded operator)
         
     | 
| 
      
 546 
     | 
    
         
            +
                  # and not a native operand
         
     | 
| 
      
 547 
     | 
    
         
            +
                  if wnode_op.template == :call
         
     | 
| 
      
 548 
     | 
    
         
            +
                    logger.debug "Doing nothing because it's a func call..."
         
     | 
| 
      
 549 
     | 
    
         
            +
                    return wnode_op
         
     | 
| 
      
 550 
     | 
    
         
            +
                  end
         
     | 
| 
      
 551 
     | 
    
         
            +
             
     | 
| 
      
 552 
     | 
    
         
            +
                  # A native operator only expects 0 (unary) or 1 (binary)
         
     | 
| 
      
 553 
     | 
    
         
            +
                  # argument in addition to the receiver 
         
     | 
| 
       435 
554 
     | 
    
         
             
                  raise "only 0 or 1 operand expected (got #{wnode_args.count})" if wnode_args.count > 1
         
     | 
| 
       436 
555 
     | 
    
         
             
                  op = wnode_op.wargs[:operator]
         
     | 
| 
      
 556 
     | 
    
         
            +
                  #wnode_recv = wnode_op.children[0]
         
     | 
| 
      
 557 
     | 
    
         
            +
                  #wnode_args = wnode_op.children[1..-1]
         
     | 
| 
       437 
558 
     | 
    
         
             
                  # First find out the wtype that has precedence
         
     | 
| 
       438 
559 
     | 
    
         
             
                  wtype = self.class.leading_wtype(wnode_recv, *wnode_args)
         
     | 
| 
       439 
560 
     | 
    
         | 
| 
         @@ -441,7 +562,7 @@ module Rlang::Parser 
     | 
|
| 
       441 
562 
     | 
    
         
             
                  logger.debug "leading type cast: #{wtype}"
         
     | 
| 
       442 
563 
     | 
    
         | 
| 
       443 
564 
     | 
    
         
             
                  # Attach receiver and argument to the operator wnode
         
     | 
| 
       444 
     | 
    
         
            -
                  # type casting them if necessary
         
     | 
| 
      
 565 
     | 
    
         
            +
                  # type casting them if necessary    
         
     | 
| 
       445 
566 
     | 
    
         
             
                  self.cast(wnode_recv, wtype).reparent_to(wnode_op)
         
     | 
| 
       446 
567 
     | 
    
         
             
                  self.cast(wnode_args.first, wtype).reparent_to(wnode_op) unless wnode_args.empty?
         
     | 
| 
       447 
568 
     | 
    
         | 
| 
         @@ -455,8 +576,7 @@ module Rlang::Parser 
     | 
|
| 
       455 
576 
     | 
    
         
             
                    # if + or - operator then multiply arg by size of object
         
     | 
| 
       456 
577 
     | 
    
         
             
                    if [:add, :sub].include? wnode_op.wargs[:operator]
         
     | 
| 
       457 
578 
     | 
    
         
             
                      (wn_mulop = WNode.new(:insn, wnode_op)).c(:operator, operator: :mul)
         
     | 
| 
       458 
     | 
    
         
            -
                      WNode.new(:insn, wn_mulop).c(: 
     | 
| 
       459 
     | 
    
         
            -
                        value: lambda { wnode_recv.find_class(wnode_recv.wtype.name).size })
         
     | 
| 
      
 579 
     | 
    
         
            +
                      WNode.new(:insn, wn_mulop).c(:call, func_name: "$#{wnode_recv.wtype.name}::#{SIZE_METHOD}")
         
     | 
| 
       460 
580 
     | 
    
         
             
                      wnode_args.first.reparent_to(wn_mulop)
         
     | 
| 
       461 
581 
     | 
    
         
             
                    else
         
     | 
| 
       462 
582 
     | 
    
         
             
                      # It's a relational operator. In this case
         
     | 
| 
         @@ -466,6 +586,7 @@ module Rlang::Parser 
     | 
|
| 
       466 
586 
     | 
    
         
             
                      wnode_op.wtype = WType::DEFAULT
         
     | 
| 
       467 
587 
     | 
    
         
             
                    end
         
     | 
| 
       468 
588 
     | 
    
         
             
                  end
         
     | 
| 
      
 589 
     | 
    
         
            +
                  logger.debug "Operands in operator wnode after postprocessing: #{wnode_op}..."
         
     | 
| 
       469 
590 
     | 
    
         
             
                  wnode_op
         
     | 
| 
       470 
591 
     | 
    
         
             
                end
         
     | 
| 
       471 
592 
     | 
    
         |