rlang 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|