rlang 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,6 +11,7 @@ require_relative './cvar'
11
11
  require_relative './lvar'
12
12
  require_relative './wattr'
13
13
  require_relative './method'
14
+ require_relative './klass'
14
15
 
15
16
  module Rlang::Parser
16
17
  class WNode
@@ -56,10 +57,9 @@ module Rlang::Parser
56
57
  (%{wtype}.const %{size})}
57
58
  }
58
59
 
59
- attr_accessor :type, :wargs, :children, :parent, :comment, :lvars, :cvars, :margs,
60
- :consts, :methods, :method, :template, :keep_on_stack,
61
- :class_wnodes
62
- attr_reader :wtype, :label, :klass_name, :klass_size, :wattrs
60
+ attr_accessor :type, :wargs, :children, :parent, :comment,
61
+ :method, :template, :keep_on_stack, :classes
62
+ attr_reader :wtype, :label, :klass
63
63
 
64
64
  @@label_index = 0
65
65
 
@@ -81,19 +81,13 @@ module Rlang::Parser
81
81
  @wtype = WType::DEFAULT
82
82
 
83
83
  # For root wnode
84
- @class_wnodes = [] # wnodes of classes
84
+ @classes = [] # classes
85
85
 
86
86
  # For class wnode only
87
- @klass_name = nil
88
- @wattrs = [] # class attributes
89
- @cvars = [] # class variables=
90
- @consts = [] # class constants
91
- @methods = [] # methods
87
+ @klass = nil
92
88
 
93
89
  # For method wnode only
94
90
  @method = nil
95
- @margs = [] # method args
96
- @lvars = [] # local variables
97
91
 
98
92
  # For insn wnode with
99
93
  # label (.e.g block, loop)
@@ -184,6 +178,7 @@ module Rlang::Parser
184
178
  # Reparent self node to another wnode
185
179
  def reparent_to(wnode)
186
180
  return if self.parent == wnode
181
+ logger.debug "Reparenting #{self.object_id} to #{wnode.object_id}"
187
182
  old_parent, new_parent = self.parent, wnode
188
183
  new_parent << self
189
184
  old_parent >> self if old_parent
@@ -197,36 +192,68 @@ module Rlang::Parser
197
192
  wn
198
193
  end
199
194
 
200
- # Set this node class name
201
- def class_name=(class_name)
202
- @klass_name = class_name
195
+ def klass=(klass)
196
+ @klass = klass
197
+ @klass.wnode = self
198
+ WNode.root.classes << klass
203
199
  end
204
200
 
205
201
  # Find class name in this node and up the tree
206
202
  def class_name
207
- (cn = self.class_wnode) ? cn.klass_name : nil
203
+ (cn = self.class_wnode) ? cn.klass.name : nil
208
204
  end
209
205
 
210
- # Find class name in this node and up the tree
206
+ # Find class size in this wnode or up the tree
211
207
  def class_size
212
- (cn = self.class_wnode) ? cn.wattrs.sum(&:size) : nil
208
+ (cn = self.class_wnode) ? cn.klass.size : nil
213
209
  end
214
210
 
215
- # Find the class wnode matching with the given
216
- # class name
217
- def find_class(class_name=nil)
211
+ # Find the class object of the current and up the tree
212
+ # if no name given or lookup the matching class from
213
+ # the root level if class name given
214
+ def find_class(class_name)
215
+ logger.debug "looking for class #{class_name ? class_name : 'current'}"
218
216
  if class_name
219
- WNode.root.class_wnodes.find { |wn| wn.class_name == class_name }
217
+ c = WNode.root.classes.find { |c| c.name == class_name }
218
+ else
219
+ logger.debug "Looking for class wnode from wnode #{self} / ID: #{self.object_id} /
220
+ type: #{self.type} / class_wnode ID #{self.class_wnode.object_id} /
221
+ class_wnode #{self.class_wnode} /
222
+ self klass : #{self.klass} /
223
+ self klass wtype : #{self.klass&.wtype} / "
224
+ c = self.class_wnode.klass
225
+ end
226
+ if c
227
+ logger.debug "Found class #{c}"
220
228
  else
221
- self.class_wnode
222
- end
229
+ logger.debug "Class #{class_name} not found"
230
+ end
231
+ c
232
+ end
233
+
234
+ # Create a Class object. **NOTE** the self
235
+ # wnode must be the parent of the new class
236
+ def create_class(class_name)
237
+ if (k = self.find_class(class_name))
238
+ raise "Cannot create class #{class_name} for wnode #{self} as it already exists!!"
239
+ else
240
+ wnc = WNode.new(:class, self)
241
+ wnc.klass = Klass.new(class_name)
242
+ logger.debug "Created class #{wnc.klass} under wnode #{self} / id: #{self.object_id}"
243
+ logger.debug "k inspection: #{wnc.klass}"
244
+ end
245
+ wnc.klass
246
+ end
247
+
248
+ def find_or_create_class(class_name)
249
+ self.find_class(class_name) || self.create_class(class_name)
223
250
  end
224
251
 
225
252
  # create a constant
226
253
  def create_const(c_name, class_name, value, wtype)
227
254
  class_name ||= self.class_name
228
255
  if (cn = self.class_wnode)
229
- cn.consts << (const = Const.new(class_name, c_name, value, wtype))
256
+ cn.klass.consts << (const = Const.new(class_name, c_name, value, wtype))
230
257
  else
231
258
  raise "No class found for class constant #{const}"
232
259
  end
@@ -236,11 +263,11 @@ module Rlang::Parser
236
263
  # Look for constant in the appropriate class wnode
237
264
  # (it can be the current class or another class)
238
265
  def find_const(c_name, class_name=nil)
239
- wn_class = find_class(class_name)
240
- raise "Can't find parent class for constant #{c_name}" unless wn_class
241
- class_name = wn_class.class_name
266
+ k = find_class(class_name)
267
+ raise "Can't find parent class for constant #{c_name}" unless k
268
+ class_name = k.name
242
269
  logger.debug "looking for const #{c_name} in class #{class_name} at wnode #{self.class_wnode}..."
243
- wn_class.consts.find { |c| c.class_name == class_name && c.name == c_name }
270
+ k.consts.find { |c| c.class_name == class_name && c.name == c_name }
244
271
  end
245
272
 
246
273
  def find_or_create_const(c_name, class_name, value, wtype)
@@ -248,27 +275,51 @@ module Rlang::Parser
248
275
  end
249
276
 
250
277
  def find_wattr(wa_name, class_name=nil)
251
- wn_class = find_class(class_name)
252
- raise "Can't find parent class for wattr #{wa_name}" unless wn_class
253
- class_name = wn_class.class_name
254
- logger.debug "looking for wattr #{wa_name} in class #{class_name} at wnode #{self.class_wnode}..."
255
- wn_class.wattrs.find { |wa| wa.class_name == class_name && wa.name == wa_name }
278
+ k = find_class(class_name)
279
+ raise "Can't find parent class for wattr #{wa_name}" unless k
280
+ logger.debug "looking for wattr #{wa_name} in class #{k.name} at wnode #{self.class_wnode}..."
281
+ k.wattrs.find { |wa| wa.class_name == k.name && wa.name == wa_name }
256
282
  end
257
283
 
258
284
  def create_wattr(wa_name, wtype=WType::DEFAULT)
259
285
  if (cn = self.class_wnode)
260
286
  logger.debug "creating wattr #{wa_name} in class #{self.class_name} at wnode #{self.class_wnode}..."
261
- cn.wattrs << (wattr = WAttr.new(cn, wa_name, wtype))
287
+ cn.klass.wattrs << (wattr = WAttr.new(cn, wa_name, wtype))
262
288
  else
263
289
  raise "No class found for class attribute #{wa_name}"
264
290
  end
265
291
  wattr
266
292
  end
267
293
 
294
+ def find_or_create_wattr(wa_name, class_name=nil, wtype=WType::DEFAULT)
295
+ find_wattr(wa_name, class_name) || create_wattr(wa_name, wtype)
296
+ end
297
+
298
+ def create_ivar(iv_name, wtype=WType::DEFAULT)
299
+ if (cn = self.class_wnode)
300
+ logger.debug "creating ivar #{iv_name} in class #{self.class_name} at wnode #{self.class_wnode}..."
301
+ cn.klass.wattrs << (wattr = WAttr.new(cn, iv_name, wtype))
302
+ else
303
+ raise "No class found for instance variable #{iv_name}"
304
+ end
305
+ wattr
306
+ end
307
+
308
+ def find_ivar(iv_name, class_name=nil)
309
+ klass = find_class(class_name)
310
+ raise "Can't find parent class for ivar #{iv_name}" unless klass
311
+ logger.debug "looking for ivar #{iv_name} in class #{class_name} at wnode #{self.class_wnode}..."
312
+ self.class_wnode.klass.wattrs.find { |wa| wa.ivar.class_name == klass.name && wa.ivar.name == iv_name }
313
+ end
314
+
315
+ def find_or_create_ivar(iv_name)
316
+ self.find_ivar(iv_name) || self.create_ivar(iv_name)
317
+ end
318
+
268
319
  def create_cvar(cv_name, value=0, wtype=WType::DEFAULT)
269
320
  if (cn = self.class_wnode)
270
321
  logger.debug "creating cvar #{cv_name} in class #{self.class_name} at wnode #{self.class_wnode}..."
271
- cn.cvars << (cvar = CVar.new(cn.klass_name, cv_name, value, wtype))
322
+ cn.klass.cvars << (cvar = CVar.new(cn.klass.name, cv_name, value, wtype))
272
323
  else
273
324
  raise "No class found for class variable #{cv_name}"
274
325
  end
@@ -277,12 +328,12 @@ module Rlang::Parser
277
328
 
278
329
  def find_cvar(cv_name)
279
330
  logger.debug "looking for cvar #{cv_name} in class #{self.class_name} at wnode #{self.class_wnode}..."
280
- self.class_wnode.cvars.find { |cv| cv.class_name == self.class_name && cv.name == cv_name }
331
+ self.class_wnode.klass.cvars.find { |cv| cv.class_name == self.class_name && cv.name == cv_name }
281
332
  end
282
333
 
283
334
  def create_lvar(name)
284
335
  if (mn = self.method_wnode)
285
- mn.lvars << (lvar = LVar.new(name))
336
+ mn.method.lvars << (lvar = LVar.new(name))
286
337
  else
287
338
  raise "No method found for local variable #{name}"
288
339
  end
@@ -290,7 +341,7 @@ module Rlang::Parser
290
341
  end
291
342
 
292
343
  def find_lvar(name)
293
- self.method_wnode.lvars.find { |lv| lv.name == name }
344
+ self.method_wnode.method.lvars.find { |lv| lv.name == name }
294
345
  end
295
346
 
296
347
  def find_or_create_lvar(name)
@@ -300,7 +351,7 @@ module Rlang::Parser
300
351
  # add method argument
301
352
  def create_marg(name)
302
353
  if (mn = self.method_wnode)
303
- mn.margs << (marg = MArg.new(name))
354
+ mn.method.margs << (marg = MArg.new(name))
304
355
  else
305
356
  raise "No class found for class variable #{marg}"
306
357
  end
@@ -308,51 +359,48 @@ module Rlang::Parser
308
359
  end
309
360
 
310
361
  def find_marg(name)
311
- self.method_wnode.margs.find { |ma| ma.name == name }
362
+ self.method_wnode.method.margs.find { |ma| ma.name == name }
312
363
  end
313
364
 
314
365
  # method_type is either :instance or :class
315
366
  def create_method(method_name, class_name, wtype, method_type)
316
- raise "MEthod already exists: #{m}" \
317
- if (m = find_method(method_name, class_name, method_type))
367
+ if (m = find_method(method_name, class_name, method_type))
368
+ raise "MEthod already exists: #{m.inspect}"
369
+ end
318
370
  if (cn = self.class_wnode)
319
- class_name ||= cn.klass_name
320
- cn.methods << (method = MEthod.new(method_name, class_name, wtype))
371
+ class_name ||= cn.klass.name
372
+ cn.klass.methods << (method = MEthod.new(method_name, class_name, wtype))
321
373
  else
322
374
  raise "No class wnode found to create method #{method_name}"
323
375
  end
324
376
  method_type == :class ? method.class! : method.instance!
325
- logger.debug "Created MEthod: #{method.inspect}"
377
+ logger.debug "Created MEthod: #{method}"
326
378
  method
327
379
  end
328
380
 
329
- # method_type is either :instance or :class
381
+ # method_type is either :instance or :class
330
382
  def find_method(method_name, class_name, method_type)
331
- if class_name
332
- class_wnode = find_class(class_name)
333
- else
334
- class_wnode = self.class_wnode
335
- end
336
- raise "Couldn't find class wnode for class_name #{class_name}" unless class_wnode
337
- class_name = class_wnode.klass_name
383
+ k = self.find_class(class_name)
384
+ raise "Couldn't find class wnode for class_name #{class_name}" unless k
338
385
  if method_type == :class
339
- method = class_wnode.methods.find { |m| m.name == method_name && m.class_name == class_name && m.class? }
386
+ method = k.methods.find { |m| m.name == method_name && m.class_name == class_name && m.class? }
340
387
  elsif method_type == :instance
341
- method = class_wnode.methods.find { |m| m.name == method_name && m.class_name == class_name && m.instance? }
388
+ method = k.methods.find { |m| m.name == method_name && m.class_name == class_name && m.instance? }
342
389
  else
343
390
  raise "Unknown method type : #{method_type.inspect}"
344
391
  end
345
392
  if method
346
- logger.debug "Found MEthod: #{method.inspect}"
393
+ logger.debug "Found MEthod: #{method}"
347
394
  else
348
- logger.debug "Couldn't find MEthod: #{class_name.inspect},#{method_name.inspect}"
395
+ logger.debug "Couldn't find MEthod: #{k.name},#{method_name}"
349
396
  end
350
397
  method
351
398
  end
352
399
 
353
- def find_or_create_method(method_name, class_name=nil, method_type=:class)
400
+ def find_or_create_method(method_name, class_name, wtype, method_type)
401
+ wtype ||= WType::DEFAULT
354
402
  self.find_method(method_name, class_name, method_type) || \
355
- self.create_method(method_name, class_name, WType::DEFAULT, method_type)
403
+ self.create_method(method_name, class_name, wtype, method_type)
356
404
  end
357
405
 
358
406
  # Find block wnode up the tree
@@ -15,6 +15,7 @@ require_relative '../../utils/log'
15
15
  require_relative './ext/type'
16
16
 
17
17
  class WType
18
+ include Log
18
19
 
19
20
  WASM_TYPE_MAP = {
20
21
  I64: Type::I64,
@@ -1,3 +1,3 @@
1
1
  module Rlang
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -37,4 +37,5 @@ Gem::Specification.new do |spec|
37
37
  spec.add_development_dependency "rake", "~> 12.0"
38
38
  spec.add_development_dependency "minitest", "~> 5.0"
39
39
  spec.add_development_dependency "wasmer", "~> 0.3"
40
+ spec.add_development_dependency "simplecov", "~> 0.18"
40
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rlang
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Laurent Julliard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-01 00:00:00.000000000 Z
11
+ date: 2020-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.18'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.18'
83
97
  description: "Rlang is meant to create fast and uncluttered WebAssembly code \n from
84
98
  the comfort of the Ruby language. It is actually made of two things: a supported
85
99
  \n subset of the Ruby language and a compiler transforming this Ruby subset in
@@ -103,11 +117,15 @@ files:
103
117
  - bin/rlang
104
118
  - docs/RlangCompiler.md
105
119
  - docs/RlangManual.md
120
+ - examples/fib/fib.rb
121
+ - examples/fib/index.html
122
+ - examples/fib/server.rb
106
123
  - lib/builder.rb
107
124
  - lib/builder/ext.rb
108
125
  - lib/builder/ext/tempfile.rb
109
126
  - lib/builder/rlang.rb
110
127
  - lib/builder/rlang/builder.rb
128
+ - lib/builder/rlang/compiler.rb
111
129
  - lib/builder/wat.rb
112
130
  - lib/builder/wat/builder.rb
113
131
  - lib/builder/wat/renderer.rb
@@ -116,6 +134,7 @@ files:
116
134
  - lib/rlang/lib/malloc.c
117
135
  - lib/rlang/lib/malloc.rb
118
136
  - lib/rlang/lib/memory.rb
137
+ - lib/rlang/lib/object.rb
119
138
  - lib/rlang/lib/type.rb
120
139
  - lib/rlang/lib/type/i32.rb
121
140
  - lib/rlang/lib/type/i64.rb
@@ -129,6 +148,8 @@ files:
129
148
  - lib/rlang/parser/ext/string.rb
130
149
  - lib/rlang/parser/ext/type.rb
131
150
  - lib/rlang/parser/global.rb
151
+ - lib/rlang/parser/ivar.rb
152
+ - lib/rlang/parser/klass.rb
132
153
  - lib/rlang/parser/lvar.rb
133
154
  - lib/rlang/parser/marg.rb
134
155
  - lib/rlang/parser/method.rb