rlang 0.3.1 → 0.4.0
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/.gitignore +2 -1
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +7 -1
- data/README.md +21 -1
- data/bin/rlang +18 -53
- data/docs/RlangManual.md +65 -27
- data/examples/fib/fib.rb +11 -0
- data/examples/fib/index.html +38 -0
- data/examples/fib/server.rb +16 -0
- data/lib/builder/rlang.rb +1 -1
- data/lib/builder/rlang/builder.rb +41 -9
- data/lib/builder/rlang/compiler.rb +83 -0
- data/lib/builder/wat/builder.rb +12 -21
- data/lib/rlang/lib.rb +1 -1
- data/lib/rlang/lib/malloc.rb +9 -19
- data/lib/rlang/lib/object.rb +16 -0
- data/lib/rlang/lib/unistd.rb +22 -0
- data/lib/rlang/parser.rb +176 -33
- data/lib/rlang/parser/data.rb +5 -0
- data/lib/rlang/parser/export.rb +4 -0
- data/lib/rlang/parser/global.rb +4 -0
- data/lib/rlang/parser/ivar.rb +36 -0
- data/lib/rlang/parser/klass.rb +49 -0
- data/lib/rlang/parser/marg.rb +4 -0
- data/lib/rlang/parser/method.rb +8 -4
- data/lib/rlang/parser/wattr.rb +19 -6
- data/lib/rlang/parser/wgenerator.rb +146 -47
- data/lib/rlang/parser/wnode.rb +108 -60
- data/lib/rlang/parser/wtype.rb +1 -0
- data/lib/rlang/version.rb +1 -1
- data/rlang.gemspec +1 -0
- metadata +23 -2
data/lib/rlang/parser/data.rb
CHANGED
@@ -29,6 +29,11 @@ module Rlang::Parser
|
|
29
29
|
logger.debug "New Data[#{@label}] initialized with #{@value} at address #{@address}"
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.reset!
|
33
|
+
@@label_table = {}
|
34
|
+
@@current_address = 0
|
35
|
+
end
|
36
|
+
|
32
37
|
def append_value(value, wtype)
|
33
38
|
@value << value
|
34
39
|
if value.is_a?(String)
|
data/lib/rlang/parser/export.rb
CHANGED
data/lib/rlang/parser/global.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Instance variables
|
6
|
+
#
|
7
|
+
require_relative '../../utils/log'
|
8
|
+
require_relative './wtype'
|
9
|
+
require_relative './data'
|
10
|
+
|
11
|
+
module Rlang::Parser
|
12
|
+
class IVar
|
13
|
+
include Log
|
14
|
+
attr_reader :name, :class_wnode
|
15
|
+
attr_accessor :wtype
|
16
|
+
|
17
|
+
def initialize(class_wnode, name, wtype=WType::DEFAULT)
|
18
|
+
@name = name
|
19
|
+
@class_wnode = class_wnode
|
20
|
+
@wtype = wtype
|
21
|
+
logger.debug "creating instance variable #{name} in class #{self.class_name} / wtype #{wtype}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_name
|
25
|
+
@class_wnode.class_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def wattr_name
|
29
|
+
@name.to_s.tr('@','').to_sym
|
30
|
+
end
|
31
|
+
|
32
|
+
def wasm_type
|
33
|
+
@wtype.wasm_type
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
|
5
|
+
# Rlang classes
|
6
|
+
require_relative '../../utils/log'
|
7
|
+
require_relative './wtype'
|
8
|
+
|
9
|
+
module Rlang::Parser
|
10
|
+
# Note: Cannot use Class as class name
|
11
|
+
# because it's already used by Ruby
|
12
|
+
class Klass
|
13
|
+
include Log
|
14
|
+
|
15
|
+
attr_reader :wtype
|
16
|
+
attr_accessor :name, :wnode, :wattrs, :cvars, :consts, :methods
|
17
|
+
|
18
|
+
def initialize(name)
|
19
|
+
@name = name
|
20
|
+
# the type of a class is its name by definition
|
21
|
+
@wtype = WType.new(name)
|
22
|
+
@size = 0
|
23
|
+
# the wnode implementing the code of the class
|
24
|
+
@wnode = nil
|
25
|
+
logger.debug "Klass created #{self.inspect}"
|
26
|
+
@wattrs = [] # class attributes
|
27
|
+
@cvars = [] # class variables
|
28
|
+
@consts = [] # class constants
|
29
|
+
@methods = [] # methods
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
self.wattrs.sum(&:size)
|
34
|
+
end
|
35
|
+
|
36
|
+
def wtype=(wtype)
|
37
|
+
@wtype = wtype
|
38
|
+
logger.debug "Klass #{@name} wtype updated: #{self.inspect}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def wasm_name
|
42
|
+
@name
|
43
|
+
end
|
44
|
+
|
45
|
+
def wasm_type
|
46
|
+
@wtype.wasm_type
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/rlang/parser/marg.rb
CHANGED
data/lib/rlang/parser/method.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# Copyright (c) 2019, Laurent Julliard and contributors
|
3
3
|
# All rights reserved.
|
4
4
|
|
5
|
-
#
|
5
|
+
# Rlang methods
|
6
6
|
require_relative '../../utils/log'
|
7
7
|
require_relative './wtype'
|
8
8
|
require_relative './export'
|
@@ -14,14 +14,18 @@ module Rlang::Parser
|
|
14
14
|
include Log
|
15
15
|
|
16
16
|
attr_reader :name, :wtype
|
17
|
-
attr_accessor :class_name
|
17
|
+
attr_accessor :class_name, :margs, :lvars, :wnode
|
18
18
|
|
19
19
|
def initialize(name, class_name, wtype=WType::DEFAULT)
|
20
|
+
raise "Wrong method wtype argument: #{wtype.inspect}" unless wtype.is_a? WType
|
20
21
|
@name = name
|
21
22
|
@class_name = class_name
|
22
23
|
@wtype = wtype
|
23
24
|
@instance = false
|
24
|
-
|
25
|
+
@wnode = nil # wnode where method is implemented
|
26
|
+
logger.debug "Method created #{self.inspect}"
|
27
|
+
@margs = [] # method args
|
28
|
+
@lvars = [] # local variables
|
25
29
|
end
|
26
30
|
|
27
31
|
def instance!
|
@@ -42,7 +46,7 @@ module Rlang::Parser
|
|
42
46
|
|
43
47
|
def wtype=(wtype)
|
44
48
|
@wtype = wtype
|
45
|
-
logger.debug "Method wtype updated: #{self
|
49
|
+
logger.debug "Method wtype updated: #{self}"
|
46
50
|
end
|
47
51
|
|
48
52
|
def wasm_name
|
data/lib/rlang/parser/wattr.rb
CHANGED
@@ -5,29 +5,37 @@
|
|
5
5
|
# Method argument class
|
6
6
|
|
7
7
|
require_relative '../../utils/log'
|
8
|
+
require_relative './ivar'
|
8
9
|
require_relative './wtype'
|
9
10
|
|
10
11
|
module Rlang::Parser
|
11
12
|
class WAttr
|
12
13
|
include Log
|
13
|
-
attr_reader :name, :wtype, :getter, :setter
|
14
|
+
attr_reader :name, :wtype, :getter, :setter, :ivar
|
14
15
|
|
16
|
+
# The name argument can either be the attribute name
|
17
|
+
# (e.g. :size) or an ivar name (e.g. :@size)
|
15
18
|
def initialize(class_wnode, name, wtype=WType::DEFAULT)
|
16
19
|
@class_wnode = class_wnode
|
17
|
-
|
20
|
+
if name.to_s[0] == '@'
|
21
|
+
@ivar = IVar.new(@class_wnode, name, wtype)
|
22
|
+
@name = @ivar.wattr_name
|
23
|
+
else
|
24
|
+
@name = name
|
25
|
+
@ivar = IVar.new(@class_wnode, self.ivar_name, wtype)
|
26
|
+
end
|
18
27
|
@wtype = wtype
|
19
28
|
# Also create the corresponding getter and setter
|
20
29
|
# method objects (with default WType - wattr_type
|
21
30
|
# directives might later change this wtype)
|
22
31
|
# Don't generate WAT code yet
|
23
|
-
@getter = @class_wnode.
|
32
|
+
@getter = @class_wnode.find_or_create_method(self.getter_name, nil, wtype, :instance)
|
24
33
|
@getter.instance!
|
25
34
|
logger.debug "Getter created: #{@getter.inspect}"
|
26
35
|
|
27
|
-
@setter = @class_wnode.
|
36
|
+
@setter = @class_wnode.find_or_create_method(self.setter_name, nil, wtype, :instance)
|
28
37
|
@setter.instance!
|
29
38
|
logger.debug "Setter created: #{@setter.inspect}"
|
30
|
-
|
31
39
|
logger.debug "Class attribute #{name} created"
|
32
40
|
end
|
33
41
|
|
@@ -40,13 +48,18 @@ module Rlang::Parser
|
|
40
48
|
# Adjust corresponding method objects wtype accordingly
|
41
49
|
@getter.wtype = wtype
|
42
50
|
@setter.wtype = wtype
|
43
|
-
|
51
|
+
@ivar.wtype = wtype
|
52
|
+
logger.debug "WAttr/Getter/Setter/ivar wtype updated : #{@getter.inspect}"
|
44
53
|
end
|
45
54
|
|
46
55
|
def size
|
47
56
|
@wtype.size
|
48
57
|
end
|
49
58
|
|
59
|
+
def ivar_name
|
60
|
+
@ivar ? @ivar.name : :"@#{name}"
|
61
|
+
end
|
62
|
+
|
50
63
|
def wasm_name
|
51
64
|
"$#{@name}"
|
52
65
|
end
|
@@ -60,11 +60,43 @@ module Rlang::Parser
|
|
60
60
|
none: { I32: :cast_error, I64: :cast_error, F32: :cast_error, F64: :cast_error, Class: :cast_error, none: :cast_error},
|
61
61
|
}
|
62
62
|
|
63
|
+
# new template when object size > 0
|
64
|
+
NEW_TMPL = %q{
|
65
|
+
result :Object, :alloc, :%{default_wtype}
|
66
|
+
def self.new(%{margs})
|
67
|
+
result :%{class_name}
|
68
|
+
object_ptr = Object.alloc(%{class_name}._size_).cast_to(:%{class_name})
|
69
|
+
object_ptr.initialize(%{margs})
|
70
|
+
return object_ptr
|
71
|
+
end
|
72
|
+
}
|
73
|
+
|
74
|
+
# new template when object size iz 0 (no instance var)
|
75
|
+
# use 0 as the _self_ address in memory. It should never
|
76
|
+
# be used anyway
|
77
|
+
NEW_ZERO_TMPL = %q{
|
78
|
+
result :Object, :alloc, :%{default_wtype}
|
79
|
+
def self.new(%{margs})
|
80
|
+
result :%{class_name}
|
81
|
+
object_ptr = 0.cast_to(:%{class_name})
|
82
|
+
object_ptr.initialize(%{margs})
|
83
|
+
return object_ptr
|
84
|
+
end
|
85
|
+
}
|
86
|
+
|
87
|
+
# Do nothing initialize method
|
88
|
+
DUMB_INIT_TMPL = %q{
|
89
|
+
def initialize()
|
90
|
+
result :nil
|
91
|
+
end
|
92
|
+
}
|
93
|
+
|
63
94
|
# Generate the wasm nodes and tree structure
|
64
95
|
# ***IMPORTANT NOTE***
|
65
96
|
# Unless otherwise stated all methods receive
|
66
97
|
# the parent wnode as their first argument
|
67
98
|
# and must generate child nodes of this parent
|
99
|
+
# Child node created is returned
|
68
100
|
class WGenerator
|
69
101
|
include Log
|
70
102
|
attr_accessor :parser
|
@@ -76,38 +108,40 @@ module Rlang::Parser
|
|
76
108
|
@new_count = 0
|
77
109
|
end
|
78
110
|
|
79
|
-
def klass(wnode,
|
80
|
-
#
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
cwn
|
111
|
+
def klass(wnode, class_name)
|
112
|
+
# Create class object and class wnode if it doesn't exist yet
|
113
|
+
k = wnode.find_or_create_class(class_name)
|
114
|
+
# Create the Class.new method object too (not
|
115
|
+
# the code yet in case the end user code defines
|
116
|
+
# its own implementation in the class body)
|
117
|
+
k.wnode.find_or_create_method(:new, k.name, k.wtype, :class)
|
118
|
+
k.wnode
|
89
119
|
end
|
90
120
|
|
91
|
-
def
|
121
|
+
def def_wattr(wnode)
|
92
122
|
wnc = wnode.class_wnode
|
93
|
-
return if wnc.wattrs.empty?
|
94
123
|
# Process each declared attribute
|
95
124
|
offset = 0
|
96
|
-
wnc.wattrs.each do |wa|
|
97
|
-
logger.debug("Generating accessors for attribute #{wa}")
|
125
|
+
wnc.klass.wattrs.each do |wa|
|
126
|
+
logger.debug("Generating accessors for attribute #{wnc.klass.name}\##{wa.name}")
|
98
127
|
# Generate getter and setter methods wnode
|
99
|
-
wattr_setter(wnc, wa, offset)
|
100
|
-
wattr_getter(wnc, wa, offset)
|
128
|
+
(wa.setter.wnode = wattr_setter(wnc, wa, offset)) unless wa.setter.wnode
|
129
|
+
(wa.getter.wnode = wattr_getter(wnc, wa, offset)) unless wa.getter.wnode
|
101
130
|
# Update offset
|
102
131
|
offset += wa.wtype.size
|
103
132
|
end
|
104
133
|
|
105
|
-
# Also generate the Class::
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
134
|
+
# Also generate the Class::_size_ method
|
135
|
+
# always (needed by Object.allocate)
|
136
|
+
size_method = wnc.find_or_create_method(:_size_, wnc.klass.name, WType::DEFAULT, :class )
|
137
|
+
unless size_method.wnode
|
138
|
+
logger.debug("Generating #{size_method.class_name}\##{size_method.name}")
|
139
|
+
wns = WNode.new(:insn, wnc, true)
|
140
|
+
wns.wtype = WType::DEFAULT
|
141
|
+
wns.c(:class_size, func_name: size_method.wasm_name,
|
142
|
+
wtype: wns.wasm_type, size: wnc.class_size)
|
143
|
+
size_method.wnode = wns
|
144
|
+
end
|
111
145
|
end
|
112
146
|
|
113
147
|
# Generate attribute setter method wnode
|
@@ -133,32 +167,34 @@ module Rlang::Parser
|
|
133
167
|
def instance_method(wnode, method)
|
134
168
|
logger.debug("Generating wnode for instance method #{method.inspect}")
|
135
169
|
wn = WNode.new(:method, wnode)
|
170
|
+
method.wnode = wn
|
136
171
|
wn.method = method # must be set before calling func_name
|
137
172
|
wn.wtype = method.wtype
|
138
173
|
wn.c(:func, func_name: wn.method.wasm_name)
|
139
174
|
# Also declare a "hidden" parameter representing the
|
140
175
|
# pointer to the instance (always default wtype)
|
141
176
|
wn.create_marg(:_self_)
|
142
|
-
logger.debug("
|
177
|
+
logger.debug("Building instance method: wn.wtype #{wn.wtype}, wn.method #{wn.method}")
|
143
178
|
wn
|
144
179
|
end
|
145
180
|
|
146
181
|
def class_method(wnode, method)
|
147
182
|
logger.debug("Generating wnode for class method #{method}")
|
148
183
|
wn = WNode.new(:method, wnode)
|
184
|
+
method.wnode = wn
|
149
185
|
wn.method = method # must be set before calling func_name
|
150
186
|
wn.wtype = method.wtype
|
151
187
|
wn.c(:func, func_name: wn.method.wasm_name)
|
152
|
-
logger.debug("Building method: wn.wtype #{wn.wtype}, wn.method #{wn.method}")
|
188
|
+
logger.debug("Building class method: wn.wtype #{wn.wtype}, wn.method #{wn.method}")
|
153
189
|
wn
|
154
190
|
end
|
155
191
|
|
156
192
|
def params(wnode)
|
157
|
-
|
193
|
+
wnm = wnode.method_wnode
|
158
194
|
# use reverse to preserve proper param order
|
159
|
-
|
195
|
+
wnm.method.margs.reverse.each do |marg|
|
160
196
|
logger.debug("Prepending param #{marg}")
|
161
|
-
wn = WNode.new(:insn,
|
197
|
+
wn = WNode.new(:insn, wnm, true)
|
162
198
|
wn.wtype = marg.wtype
|
163
199
|
wn.c(:param, name: marg.wasm_name)
|
164
200
|
end
|
@@ -173,10 +209,10 @@ module Rlang::Parser
|
|
173
209
|
end
|
174
210
|
|
175
211
|
def locals(wnode)
|
176
|
-
|
177
|
-
|
212
|
+
wnm = wnode.method_wnode
|
213
|
+
wnm.method.lvars.reverse.each do |lvar|
|
178
214
|
logger.debug("Prepending local #{lvar.inspect}")
|
179
|
-
wn = WNode.new(:insn,
|
215
|
+
wn = WNode.new(:insn, wnm, true)
|
180
216
|
wn.wtype = lvar.wtype
|
181
217
|
wn.c(:local, name: lvar.wasm_name)
|
182
218
|
end
|
@@ -189,13 +225,14 @@ module Rlang::Parser
|
|
189
225
|
wn
|
190
226
|
end
|
191
227
|
|
228
|
+
# Set class variable
|
192
229
|
# Constant assignment doesn't generate any code
|
193
230
|
# A Data object is instantiated and initialized
|
194
231
|
# when the Const object is created in parser
|
195
232
|
def casgn(wnode, const)
|
196
233
|
end
|
197
234
|
|
198
|
-
#
|
235
|
+
# Get class variable
|
199
236
|
def const(wnode, const)
|
200
237
|
(wn = WNode.new(:insn, wnode)).wtype = const.wtype
|
201
238
|
wn.c(:load, wtype: const.wtype, var_name: const.wasm_name)
|
@@ -203,20 +240,51 @@ module Rlang::Parser
|
|
203
240
|
wn
|
204
241
|
end
|
205
242
|
|
206
|
-
# Global variable
|
243
|
+
# Set Global variable
|
207
244
|
def gvasgn(wnode, gvar)
|
208
245
|
(wn = WNode.new(:insn, wnode)).wtype = gvar.wtype
|
209
246
|
wn.c(:global_set, var_name: gvar.name)
|
210
247
|
wn
|
211
248
|
end
|
212
249
|
|
213
|
-
# Global variable
|
250
|
+
# Get Global variable
|
214
251
|
def gvar(wnode, gvar)
|
215
252
|
(wn = WNode.new(:insn, wnode)).wtype = gvar.wtype
|
216
253
|
wn.c(:global_get, var_name: gvar.name)
|
217
254
|
wn
|
218
255
|
end
|
219
256
|
|
257
|
+
# Call setter (on wattr or instance variable)
|
258
|
+
# This is the same as calling the corresponding setter
|
259
|
+
def call_setter(wnode, wnode_recv, wattr)
|
260
|
+
wn = self.call(wnode, wnode_recv.wtype.name, wattr.setter_name, :instance)
|
261
|
+
# First argument of the setter must be the receiver
|
262
|
+
wnode_recv.reparent_to(wn)
|
263
|
+
wn
|
264
|
+
end
|
265
|
+
|
266
|
+
# Call getter (on wattr or instance variable)
|
267
|
+
# This is the same as calling the corresponding getter
|
268
|
+
def call_getter(wnode, wnode_recv, wattr)
|
269
|
+
wn = self.call(wnode, wnode_recv.wtype.name, wattr.getter_name, :instance)
|
270
|
+
# First argument of the getter must always be the receiver
|
271
|
+
wnode_recv.reparent_to(wn)
|
272
|
+
wn
|
273
|
+
end
|
274
|
+
|
275
|
+
# Set instance variable
|
276
|
+
# This is the same as calling the corresponding setter
|
277
|
+
def ivasgn(wnode, wnode_recv, wattr)
|
278
|
+
self.call_setter(wnode, wnode_recv, wattr)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Get instance variable.
|
282
|
+
# This is the same as calling the corresponding getter
|
283
|
+
def ivar(wnode, wnode_recv, wattr)
|
284
|
+
self.call_getter(wnode, wnode_recv, wattr)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Set class variable
|
220
288
|
# Create the class variable storage node and
|
221
289
|
# an empty expression node to populate later
|
222
290
|
def cvasgn(wnode, cvar)
|
@@ -226,7 +294,7 @@ module Rlang::Parser
|
|
226
294
|
wn
|
227
295
|
end
|
228
296
|
|
229
|
-
#
|
297
|
+
# Get class variable
|
230
298
|
def cvar(wnode, cvar)
|
231
299
|
(wn = WNode.new(:insn, wnode)).wtype = cvar.wtype
|
232
300
|
wn.c(:load, wtype: cvar.wtype, var_name: cvar.wasm_name)
|
@@ -388,7 +456,7 @@ module Rlang::Parser
|
|
388
456
|
if [:add, :sub].include? wnode_op.wargs[:operator]
|
389
457
|
(wn_mulop = WNode.new(:insn, wnode_op)).c(:operator, operator: :mul)
|
390
458
|
WNode.new(:insn, wn_mulop).c(:const,
|
391
|
-
value: lambda { wnode_recv.find_class(wnode_recv.wtype.name).
|
459
|
+
value: lambda { wnode_recv.find_class(wnode_recv.wtype.name).size })
|
392
460
|
wnode_args.first.reparent_to(wn_mulop)
|
393
461
|
else
|
394
462
|
# It's a relational operator. In this case
|
@@ -403,11 +471,11 @@ module Rlang::Parser
|
|
403
471
|
|
404
472
|
# Statically allocate an object in data segment
|
405
473
|
# with the size of the class
|
406
|
-
def
|
407
|
-
|
408
|
-
if
|
474
|
+
def static_new(wnode, class_name)
|
475
|
+
klass = wnode.find_class(class_name)
|
476
|
+
if klass.size > 0
|
409
477
|
data_label = "#{class_name}_new_#{@new_count += 1}"
|
410
|
-
data = DAta.new(data_label.to_sym, "\x00"*
|
478
|
+
data = DAta.new(data_label.to_sym, "\x00"*klass.wnode.class_size)
|
411
479
|
address = data.address
|
412
480
|
else
|
413
481
|
# TODO: point to address 0. It is not safe but normally
|
@@ -421,9 +489,44 @@ module Rlang::Parser
|
|
421
489
|
wn_object_addr
|
422
490
|
end
|
423
491
|
|
492
|
+
# Create the dynamic new method. It allocates memory
|
493
|
+
# for the object created and calls initialize
|
494
|
+
def def_new(wnode_class)
|
495
|
+
# no new method for native types
|
496
|
+
return if wnode_class.klass.wtype.native?
|
497
|
+
new_method = wnode_class.find_method(:new, wnode_class.class_name, :class)
|
498
|
+
return if new_method.wnode # already implemented
|
499
|
+
|
500
|
+
init_method = wnode_class.find_method(:initialize, wnode_class.class_name, :instance)
|
501
|
+
logger.debug "Creating code for #{wnode_class.class_name}.new"
|
502
|
+
new_tmpl = wnode_class.class_size.zero? ? NEW_ZERO_TMPL : NEW_TMPL
|
503
|
+
new_source = new_tmpl % {
|
504
|
+
default_wtype: WType::DEFAULT.name,
|
505
|
+
class_name: wnode_class.class_name,
|
506
|
+
# Do not pass _self_ argument to the new method of course !!
|
507
|
+
margs: init_method.margs.reject {|ma| ma._self_?}.map(&:name).join(', '),
|
508
|
+
class_size: wnode_class.class_size
|
509
|
+
}
|
510
|
+
new_method.wnode = self.parser.parse(new_source, wnode_class)
|
511
|
+
end
|
512
|
+
|
513
|
+
# Define a dumb initialize method if not implemented
|
514
|
+
# already in user code
|
515
|
+
def def_initialize(wnode_class)
|
516
|
+
# no new/initialize method for native types
|
517
|
+
return if WType.new(wnode_class.class_name).native?
|
518
|
+
# generate code for a dumb initialize method if not defined
|
519
|
+
# in user code
|
520
|
+
unless wnode_class.find_method(:initialize, wnode_class.class_name, :instance)
|
521
|
+
logger.debug "Creating MEthod and code for #{wnode_class.class_name}#initialize"
|
522
|
+
init_source = DUMB_INIT_TMPL
|
523
|
+
self.parser.parse(init_source, wnode_class)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
424
527
|
def call(wnode, class_name, method_name, method_type)
|
425
|
-
method = wnode.find_or_create_method(method_name, class_name, method_type)
|
426
|
-
logger.debug "found method #{method
|
528
|
+
method = wnode.find_or_create_method(method_name, class_name, nil, method_type)
|
529
|
+
logger.debug "found method #{method}"
|
427
530
|
(wn_call = WNode.new(:insn, wnode)).c(:call, func_name: method.wasm_name)
|
428
531
|
wn_call.wtype = method.wtype
|
429
532
|
wn_call
|
@@ -431,7 +534,7 @@ module Rlang::Parser
|
|
431
534
|
|
432
535
|
# self in an instance context is passed as the first argument
|
433
536
|
# of a method call
|
434
|
-
def
|
537
|
+
def _self_(wnode)
|
435
538
|
(wns = WNode.new(:insn, wnode)).c(:local_get, var_name: '$_self_')
|
436
539
|
wns.wtype = WType.new(wnode.class_name)
|
437
540
|
wns
|
@@ -499,11 +602,7 @@ module Rlang::Parser
|
|
499
602
|
# Determine which wasm type has precedence among
|
500
603
|
# all wnodes
|
501
604
|
def self.leading_wtype(*wnodes)
|
502
|
-
|
503
|
-
WType.leading(wnodes.map(&:wtype))
|
504
|
-
rescue
|
505
|
-
raise "#{wnodes.map(&:to_s)}"
|
506
|
-
end
|
605
|
+
WType.leading(wnodes.map(&:wtype))
|
507
606
|
end
|
508
607
|
end
|
509
608
|
end
|