rubinius-ast 2.1.3 → 2.2.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/lib/rubinius/ast/constants.rb +3 -2
- data/lib/rubinius/ast/control_flow.rb +7 -4
- data/lib/rubinius/ast/data.rb +1 -1
- data/lib/rubinius/ast/definitions.rb +375 -241
- data/lib/rubinius/ast/encoding.rb +3 -2
- data/lib/rubinius/ast/exceptions.rb +1 -1
- data/lib/rubinius/ast/file.rb +1 -1
- data/lib/rubinius/ast/grapher.rb +1 -1
- data/lib/rubinius/ast/literals.rb +69 -9
- data/lib/rubinius/ast/node.rb +5 -1
- data/lib/rubinius/ast/operators.rb +83 -17
- data/lib/rubinius/ast/self.rb +1 -1
- data/lib/rubinius/ast/sends.rb +84 -90
- data/lib/rubinius/ast/transforms.rb +1 -1
- data/lib/rubinius/ast/values.rb +123 -11
- data/lib/rubinius/ast/variables.rb +154 -195
- data/lib/rubinius/ast/version.rb +2 -2
- data/rubinius-ast.gemspec +1 -2
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 446fcd824eee49fa15042e4aa39a3e802b49a4bb
|
4
|
+
data.tar.gz: b89a58a16a0ccacf3ac5e638fd29b2cefc2d5472
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 625a245f3487f621f66419640e446a00e4046318ec505a123c80ee27186b803f1d01f5635ae7884134cba19625e3d36468bd87348ab930fb69820706031a725d
|
7
|
+
data.tar.gz: 9ad09df099f4f9bc70476b71d144972186b0fcf8a194cb092b4af4c956609321fd3be6ca55d398a93f79e84dc289cf688efee67d33cf9cdfbed03020e4d38f7a
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
|
6
6
|
class TypeConstant < Node
|
@@ -204,7 +204,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
204
204
|
pos(g)
|
205
205
|
|
206
206
|
if g.state.op_asgn?
|
207
|
-
g.
|
207
|
+
g.push_rubinius
|
208
|
+
g.find_const :Runtime
|
208
209
|
g.push_literal @name
|
209
210
|
g.push_scope
|
210
211
|
g.send :find_constant_for_op_asign_or, 2
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
class Case < Node
|
6
6
|
attr_accessor :whens, :else
|
@@ -209,7 +209,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
209
209
|
g.dup
|
210
210
|
@condition.bytecode(g)
|
211
211
|
g.cast_array
|
212
|
-
g.
|
212
|
+
g.push_rubinius
|
213
|
+
g.find_const :Runtime
|
213
214
|
g.rotate(3)
|
214
215
|
g.send :matches_when, 2
|
215
216
|
g.git body
|
@@ -271,14 +272,16 @@ module Rubinius::ToolSets.current::ToolSet
|
|
271
272
|
end
|
272
273
|
|
273
274
|
def get_flip_flop(g, index)
|
274
|
-
g.
|
275
|
+
g.push_rubinius
|
276
|
+
g.find_const :Runtime
|
275
277
|
g.push_scope
|
276
278
|
g.push_literal index
|
277
279
|
g.send(:get_flip_flop, 2)
|
278
280
|
end
|
279
281
|
|
280
282
|
def set_flip_flop(g, index, value)
|
281
|
-
g.
|
283
|
+
g.push_rubinius
|
284
|
+
g.find_const :Runtime
|
282
285
|
g.push_scope
|
283
286
|
g.push_literal index
|
284
287
|
g.push_literal value
|
data/lib/rubinius/ast/data.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: us-ascii -*-
|
2
2
|
|
3
|
-
module
|
3
|
+
module CodeTools
|
4
4
|
module AST
|
5
5
|
class Alias < Node
|
6
6
|
attr_accessor :to, :from
|
@@ -79,8 +79,8 @@ module Rubinius::ToolSets.current::ToolSet
|
|
79
79
|
@locals = nil
|
80
80
|
end
|
81
81
|
|
82
|
-
def
|
83
|
-
if @array.first.kind_of?
|
82
|
+
def extract_parameters
|
83
|
+
if @array.first.kind_of? Parameters
|
84
84
|
node = @array.shift
|
85
85
|
if @array.first.kind_of? BlockArgument
|
86
86
|
node.block_arg = @array.shift
|
@@ -191,7 +191,7 @@ module Rubinius::ToolSets.current::ToolSet
|
|
191
191
|
def initialize(line, name, block)
|
192
192
|
@line = line
|
193
193
|
@name = name
|
194
|
-
@arguments = block.
|
194
|
+
@arguments = block.extract_parameters
|
195
195
|
block.array << NilLiteral.new(line) if block.array.empty?
|
196
196
|
@body = block
|
197
197
|
end
|
@@ -277,153 +277,53 @@ module Rubinius::ToolSets.current::ToolSet
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
-
class
|
281
|
-
attr_accessor :
|
282
|
-
attr_reader :block_arg, :block_index
|
280
|
+
class Lambda < Node
|
281
|
+
attr_accessor :arguments, :body
|
283
282
|
|
284
|
-
def initialize(line,
|
283
|
+
def initialize(line, arguments, body)
|
285
284
|
@line = line
|
286
|
-
@
|
287
|
-
@
|
288
|
-
@block_index = nil
|
289
|
-
|
290
|
-
if defaults
|
291
|
-
defaults = DefaultArguments.new line, defaults
|
292
|
-
@defaults = defaults
|
293
|
-
@optional = defaults.names
|
294
|
-
|
295
|
-
stop = defaults.names.first
|
296
|
-
last = args.each_with_index { |a, i| break i if a == stop }
|
297
|
-
@required = args[0, last]
|
298
|
-
else
|
299
|
-
@required = args.dup
|
300
|
-
@optional = []
|
301
|
-
end
|
302
|
-
|
303
|
-
if splat.kind_of? Symbol
|
304
|
-
args << splat
|
305
|
-
elsif splat
|
306
|
-
splat = :*
|
307
|
-
args << splat
|
308
|
-
end
|
309
|
-
@names = args
|
310
|
-
@splat = splat
|
311
|
-
end
|
312
|
-
|
313
|
-
def block_arg=(node)
|
314
|
-
@names << node.name
|
315
|
-
|
316
|
-
@block_index = @names.length - 1
|
317
|
-
@block_arg = node
|
285
|
+
@arguments = arguments
|
286
|
+
@body = Iter.new line, arguments, body
|
318
287
|
end
|
319
288
|
|
320
289
|
def bytecode(g)
|
321
|
-
g
|
322
|
-
map_arguments g.state.scope
|
323
|
-
|
324
|
-
@defaults.bytecode(g) if @defaults
|
325
|
-
@block_arg.bytecode(g) if @block_arg
|
326
|
-
g.state.check_for_locals = true
|
327
|
-
end
|
328
|
-
|
329
|
-
def required_args
|
330
|
-
@required.size
|
331
|
-
end
|
332
|
-
|
333
|
-
alias_method :arity, :required_args
|
334
|
-
|
335
|
-
def post_args
|
336
|
-
0
|
337
|
-
end
|
338
|
-
|
339
|
-
def total_args
|
340
|
-
@required.size + @optional.size
|
341
|
-
end
|
342
|
-
|
343
|
-
def splat_index
|
344
|
-
if @splat
|
345
|
-
index = @names.size
|
346
|
-
index -= 1 if @block_arg
|
347
|
-
index -= 1 if @splat.kind_of? Symbol
|
348
|
-
index
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
def map_arguments(scope)
|
353
|
-
@required.each { |arg| scope.new_local arg }
|
354
|
-
@defaults.map_arguments scope if @defaults
|
355
|
-
scope.new_local @splat if @splat.kind_of? Symbol
|
356
|
-
scope.assign_local_reference @block_arg if @block_arg
|
357
|
-
end
|
358
|
-
|
359
|
-
def to_actual(line)
|
360
|
-
arguments = ActualArguments.new line
|
361
|
-
|
362
|
-
last = -1
|
363
|
-
last -= 1 if @block_arg and @block_arg.name == names[last]
|
364
|
-
last -= 1 if @splat == names[last]
|
365
|
-
|
366
|
-
arguments.array = @names[0..last].map { |name| LocalVariableAccess.new line, name }
|
367
|
-
|
368
|
-
if @splat.kind_of? Symbol
|
369
|
-
arguments.splat = SplatValue.new(line, LocalVariableAccess.new(line, @splat))
|
370
|
-
end
|
290
|
+
pos(g)
|
371
291
|
|
372
|
-
|
292
|
+
g.push_rubinius
|
293
|
+
@body.bytecode(g)
|
294
|
+
g.send_with_block :lambda, 0, false
|
373
295
|
end
|
374
296
|
|
375
297
|
def to_sexp
|
376
|
-
|
377
|
-
|
378
|
-
@required.each { |x| sexp << x }
|
379
|
-
sexp += @defaults.names if @defaults
|
380
|
-
|
381
|
-
if @splat == :*
|
382
|
-
sexp << :*
|
383
|
-
elsif @splat
|
384
|
-
sexp << :"*#{@splat}"
|
385
|
-
end
|
386
|
-
|
387
|
-
sexp += @post if @post
|
388
|
-
|
389
|
-
sexp << :"&#{@block_arg.name}" if @block_arg
|
390
|
-
|
391
|
-
sexp << [:block] + @defaults.to_sexp if @defaults
|
392
|
-
|
393
|
-
sexp
|
298
|
+
[:lambda, @arguments.to_sexp, [:scope, @body.body.to_sexp]]
|
394
299
|
end
|
395
300
|
end
|
396
301
|
|
397
|
-
class
|
398
|
-
attr_accessor :
|
302
|
+
class Parameters < Node
|
303
|
+
attr_accessor :names, :required, :optional, :defaults, :splat,
|
304
|
+
:post, :keywords, :kwrest
|
305
|
+
attr_reader :block_arg, :block_index
|
399
306
|
|
400
|
-
def initialize(line, required, optional, splat,
|
307
|
+
def initialize(line, required=nil, optional=nil, splat=nil,
|
308
|
+
post=nil, kwargs=nil, kwrest=nil, block=nil)
|
401
309
|
@line = line
|
402
310
|
@defaults = nil
|
311
|
+
@keywords = nil
|
403
312
|
@block_arg = nil
|
404
313
|
@splat_index = nil
|
405
314
|
@block_index = nil
|
315
|
+
@locals = []
|
316
|
+
@local_index = 0
|
406
317
|
|
407
|
-
@required = []
|
408
318
|
names = []
|
409
319
|
|
410
|
-
|
411
|
-
required.each do |arg|
|
412
|
-
case arg
|
413
|
-
when Symbol
|
414
|
-
names << arg
|
415
|
-
@required << arg
|
416
|
-
when MultipleAssignment
|
417
|
-
@required << PatternArguments.from_masgn(arg)
|
418
|
-
@splat_index = -4 if @required.size == 1
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
320
|
+
process_fixed_arguments Array(required), @required = [], names
|
422
321
|
|
423
322
|
if optional
|
424
323
|
@defaults = DefaultArguments.new line, optional
|
425
324
|
@optional = @defaults.names
|
426
325
|
names.concat @optional
|
326
|
+
@locals.concat @defaults.arguments
|
427
327
|
else
|
428
328
|
@optional = []
|
429
329
|
end
|
@@ -431,35 +331,84 @@ module Rubinius::ToolSets.current::ToolSet
|
|
431
331
|
case splat
|
432
332
|
when Symbol
|
433
333
|
names << splat
|
334
|
+
@locals << splat
|
434
335
|
when true
|
435
336
|
splat = :*
|
436
|
-
|
337
|
+
@locals << splat
|
437
338
|
when false
|
438
|
-
@splat_index = -3
|
439
339
|
splat = nil
|
340
|
+
@splat_index = -3
|
341
|
+
end
|
342
|
+
|
343
|
+
@splat = splat
|
344
|
+
|
345
|
+
process_fixed_arguments post, @post = [], names
|
346
|
+
|
347
|
+
if kwargs
|
348
|
+
@keywords = KeywordParameters.new line, kwargs, kwrest
|
349
|
+
names.concat @keywords.names
|
350
|
+
elsif kwrest
|
351
|
+
@keywords = KeywordParameters.new line, nil, kwrest
|
352
|
+
end
|
353
|
+
|
354
|
+
if @keywords
|
355
|
+
var = local_placeholder
|
356
|
+
@keywords.value = LocalVariableAccess.new line, var
|
357
|
+
@locals << var
|
440
358
|
end
|
441
359
|
|
442
|
-
@
|
443
|
-
|
444
|
-
|
360
|
+
@names = names
|
361
|
+
|
362
|
+
self.block_arg = block
|
363
|
+
end
|
364
|
+
|
365
|
+
def process_fixed_arguments(array, arguments, names)
|
366
|
+
if array
|
367
|
+
array.each do |arg|
|
445
368
|
case arg
|
446
|
-
when
|
447
|
-
|
369
|
+
when :_
|
370
|
+
var = names.include?(:_) ? local_placeholder : arg
|
371
|
+
names << arg
|
448
372
|
when Symbol
|
449
|
-
|
373
|
+
var = arg
|
450
374
|
names << arg
|
375
|
+
when MultipleAssignment
|
376
|
+
var = arg
|
377
|
+
var.right = LocalVariableAccess.new line, local_placeholder
|
378
|
+
when VariableAssignment
|
379
|
+
var = arg
|
380
|
+
names << var.name
|
451
381
|
end
|
382
|
+
|
383
|
+
arguments << var
|
384
|
+
@locals << var
|
452
385
|
end
|
453
386
|
end
|
387
|
+
end
|
454
388
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
389
|
+
def local_placeholder
|
390
|
+
:"_:#{@local_index += 1}"
|
391
|
+
end
|
392
|
+
|
393
|
+
def block_arg=(block)
|
394
|
+
case block
|
395
|
+
when BlockArgument
|
396
|
+
@block_arg = block
|
397
|
+
when nil
|
398
|
+
return
|
399
|
+
else
|
400
|
+
@block_arg = BlockArgument.new @line, block
|
459
401
|
end
|
460
402
|
|
461
|
-
@
|
462
|
-
|
403
|
+
if @locals.last.kind_of? BlockArgument
|
404
|
+
@block_index -= 1
|
405
|
+
@locals.pop
|
406
|
+
end
|
407
|
+
@names.pop if @names.last.kind_of? BlockArgument
|
408
|
+
|
409
|
+
@block_index = @locals.size
|
410
|
+
@locals << @block_arg
|
411
|
+
@names << @block_arg.name
|
463
412
|
end
|
464
413
|
|
465
414
|
def required_args
|
@@ -471,153 +420,126 @@ module Rubinius::ToolSets.current::ToolSet
|
|
471
420
|
end
|
472
421
|
|
473
422
|
def total_args
|
474
|
-
@required.size + @optional.size + @post.size
|
423
|
+
args = @required.size + @optional.size + @post.size
|
424
|
+
args += 1 if @keywords
|
425
|
+
args
|
475
426
|
end
|
476
427
|
|
477
428
|
def splat_index
|
478
429
|
return @splat_index if @splat_index
|
479
430
|
|
480
|
-
if @splat
|
481
|
-
index = @names.size
|
482
|
-
index -= 1 if @block_arg
|
483
|
-
index -= 1 if @splat.kind_of? Symbol
|
484
|
-
index -= @post.size
|
485
|
-
index
|
486
|
-
end
|
431
|
+
return @required.size + @optional.size if @splat
|
487
432
|
end
|
488
433
|
|
489
|
-
def
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
434
|
+
def arity
|
435
|
+
arity = required_args
|
436
|
+
|
437
|
+
if @keywords and @keywords.required?
|
438
|
+
arity += 1
|
439
|
+
end
|
440
|
+
|
441
|
+
if @splat or not @optional.empty? or
|
442
|
+
(@keywords and not @keywords.required?)
|
443
|
+
arity += 1
|
498
444
|
end
|
499
445
|
|
500
|
-
@
|
501
|
-
|
446
|
+
if @splat or not @optional.empty? or
|
447
|
+
(@keywords and not @keywords.required?)
|
448
|
+
arity = -arity
|
449
|
+
end
|
502
450
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
451
|
+
arity
|
452
|
+
end
|
453
|
+
|
454
|
+
def map_arguments(scope)
|
455
|
+
@locals.map do |v|
|
456
|
+
case v
|
507
457
|
when Symbol
|
508
|
-
scope.new_local
|
458
|
+
scope.new_local v
|
459
|
+
when MultipleAssignment
|
460
|
+
scope.assign_local_reference v.right
|
461
|
+
when LocalVariable
|
462
|
+
scope.assign_local_reference v
|
463
|
+
when nil
|
464
|
+
STDERR.puts @locals.inspect, self.inspect
|
509
465
|
end
|
510
466
|
end
|
511
467
|
|
512
|
-
scope
|
513
|
-
|
468
|
+
@keywords.map_arguments(scope) if @keywords
|
514
469
|
end
|
515
470
|
|
516
471
|
def bytecode(g)
|
517
472
|
g.state.check_for_locals = false
|
518
473
|
map_arguments g.state.scope
|
519
474
|
|
520
|
-
@required.
|
521
|
-
if arg.kind_of?
|
522
|
-
|
475
|
+
@required.each_with_index do |arg, index|
|
476
|
+
if arg.kind_of? MultipleAssignment
|
477
|
+
g.push_local index
|
523
478
|
arg.bytecode(g)
|
524
479
|
g.pop
|
525
480
|
end
|
526
481
|
end
|
482
|
+
|
527
483
|
@defaults.bytecode(g) if @defaults
|
528
|
-
|
484
|
+
|
485
|
+
index = @required.size + @optional.size
|
486
|
+
index += 1 if @splat_index
|
487
|
+
|
529
488
|
@post.each do |arg|
|
530
|
-
if arg.kind_of?
|
531
|
-
|
489
|
+
if arg.kind_of? MultipleAssignment
|
490
|
+
g.push_local index
|
491
|
+
index += 1
|
532
492
|
arg.bytecode(g)
|
533
493
|
g.pop
|
534
494
|
end
|
535
495
|
end
|
496
|
+
|
497
|
+
@keywords.bytecode(g) if @keywords
|
498
|
+
|
499
|
+
@block_arg.bytecode(g) if @block_arg
|
500
|
+
|
536
501
|
g.state.check_for_locals = true
|
537
502
|
end
|
538
|
-
end
|
539
503
|
|
540
|
-
|
541
|
-
|
504
|
+
def to_sexp
|
505
|
+
sexp = [:args]
|
542
506
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
case n
|
550
|
-
when MultipleAssignment
|
551
|
-
array << PatternArguments.from_masgn(n)
|
552
|
-
when LocalVariable
|
553
|
-
array << LeftPatternVariable.new(n.line, n.name)
|
554
|
-
end
|
507
|
+
@required.each do |a|
|
508
|
+
case a
|
509
|
+
when Symbol
|
510
|
+
sexp << a
|
511
|
+
when Node
|
512
|
+
sexp << a.to_sexp
|
555
513
|
end
|
556
514
|
end
|
557
515
|
|
558
|
-
if
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
post_args << PatternArguments.from_masgn(n)
|
565
|
-
when LocalVariable
|
566
|
-
post_args << PostPatternVariable.new(n.line, n.name, idx)
|
567
|
-
end
|
568
|
-
idx += 1
|
569
|
-
end
|
570
|
-
array.concat(post_args.reverse)
|
516
|
+
sexp += @defaults.names if @defaults
|
517
|
+
|
518
|
+
if @splat == :*
|
519
|
+
sexp << :*
|
520
|
+
elsif @splat
|
521
|
+
sexp << :"*#{@splat}"
|
571
522
|
end
|
572
523
|
|
573
|
-
if
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
524
|
+
if @post
|
525
|
+
@post.each do |a|
|
526
|
+
case a
|
527
|
+
when Symbol
|
528
|
+
sexp << a
|
529
|
+
when Node
|
530
|
+
sexp << a.to_sexp
|
531
|
+
end
|
580
532
|
end
|
581
533
|
end
|
582
534
|
|
583
|
-
|
584
|
-
end
|
535
|
+
sexp += @keywords.names if @keywords
|
585
536
|
|
586
|
-
|
587
|
-
@line = line
|
588
|
-
@arguments = arguments
|
589
|
-
@argument = nil
|
590
|
-
end
|
537
|
+
sexp << :"&#{@block_arg.name}" if @block_arg
|
591
538
|
|
592
|
-
|
593
|
-
|
594
|
-
# pattern will be destructured from the value of this assignment.
|
595
|
-
def map_arguments(scope)
|
596
|
-
arguments = @arguments.body
|
597
|
-
while arguments
|
598
|
-
node = arguments.first
|
599
|
-
case node
|
600
|
-
when LeftPatternVariable, PostPatternVariable, SplatPatternVariable
|
601
|
-
@argument = node
|
602
|
-
scope.new_local node.name
|
603
|
-
scope.assign_local_reference node
|
604
|
-
return
|
605
|
-
end
|
606
|
-
arguments = node.arguments.body
|
607
|
-
end
|
608
|
-
end
|
539
|
+
sexp << [:block] + @defaults.to_sexp if @defaults
|
540
|
+
sexp << @keywords.to_sexp if @keywords
|
609
541
|
|
610
|
-
|
611
|
-
@arguments.body.each do |arg|
|
612
|
-
if arg.kind_of? PatternArguments
|
613
|
-
g.shift_array
|
614
|
-
g.cast_array
|
615
|
-
arg.bytecode(g)
|
616
|
-
g.pop
|
617
|
-
else
|
618
|
-
arg.bytecode(g)
|
619
|
-
end
|
620
|
-
end
|
542
|
+
sexp
|
621
543
|
end
|
622
544
|
end
|
623
545
|
|
@@ -653,6 +575,218 @@ module Rubinius::ToolSets.current::ToolSet
|
|
653
575
|
end
|
654
576
|
end
|
655
577
|
|
578
|
+
class KeywordParameters < Node
|
579
|
+
attr_accessor :arguments, :defaults, :names, :kwrest, :value
|
580
|
+
|
581
|
+
def initialize(line, block, kwrest)
|
582
|
+
@line = line
|
583
|
+
@kwrest = kwrest
|
584
|
+
@required = []
|
585
|
+
@defaults = []
|
586
|
+
|
587
|
+
if block
|
588
|
+
array = block.array
|
589
|
+
@names = array.map { |a| a.name }
|
590
|
+
|
591
|
+
array.each do |arg|
|
592
|
+
if arg.value.value == :*
|
593
|
+
@required << arg
|
594
|
+
else
|
595
|
+
@defaults << arg
|
596
|
+
end
|
597
|
+
end
|
598
|
+
|
599
|
+
@arguments = array
|
600
|
+
else
|
601
|
+
@arguments = []
|
602
|
+
@names = []
|
603
|
+
end
|
604
|
+
|
605
|
+
case kwrest
|
606
|
+
when Symbol
|
607
|
+
kwrest_name = :"**#{kwrest}"
|
608
|
+
@kwrest = LocalVariableAssignment.new line, kwrest
|
609
|
+
when true
|
610
|
+
kwrest_name = :**
|
611
|
+
@kwrest = true
|
612
|
+
end
|
613
|
+
|
614
|
+
@names << kwrest_name if kwrest_name
|
615
|
+
end
|
616
|
+
|
617
|
+
def required?
|
618
|
+
not @required.empty?
|
619
|
+
end
|
620
|
+
|
621
|
+
def entries
|
622
|
+
entries = []
|
623
|
+
@required.each { |arg| entries << arg.name << true }
|
624
|
+
@defaults.each { |arg| entries << arg.name << false }
|
625
|
+
entries
|
626
|
+
end
|
627
|
+
|
628
|
+
def map_arguments(scope)
|
629
|
+
@arguments.each { |var| scope.assign_local_reference var }
|
630
|
+
|
631
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
632
|
+
scope.assign_local_reference @kwrest
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
def bytecode(g)
|
637
|
+
done = g.new_label
|
638
|
+
check_hash = g.new_label
|
639
|
+
assignments = g.new_label
|
640
|
+
|
641
|
+
@value.bytecode(g)
|
642
|
+
|
643
|
+
g.dup
|
644
|
+
g.push :nil
|
645
|
+
g.swap
|
646
|
+
g.send :equal?, 1, true
|
647
|
+
g.gif check_hash
|
648
|
+
|
649
|
+
g.pop
|
650
|
+
g.push_cpath_top
|
651
|
+
g.find_const :Hash
|
652
|
+
g.send :allocate, 0, true
|
653
|
+
g.goto assignments
|
654
|
+
|
655
|
+
check_hash.set!
|
656
|
+
kind_of_hash(g, assignments)
|
657
|
+
|
658
|
+
discard = g.new_label
|
659
|
+
|
660
|
+
g.dup
|
661
|
+
g.send :to_hash, 0, true
|
662
|
+
kind_of_hash(g, discard)
|
663
|
+
|
664
|
+
g.push_type
|
665
|
+
g.move_down 2
|
666
|
+
g.push_literal :to_hash
|
667
|
+
g.push_cpath_top
|
668
|
+
g.find_const :Hash
|
669
|
+
g.send :coerce_to_type_error, 4, true
|
670
|
+
g.goto done
|
671
|
+
|
672
|
+
discard.set!
|
673
|
+
g.swap
|
674
|
+
g.pop
|
675
|
+
|
676
|
+
missing_value = g.new_label
|
677
|
+
|
678
|
+
assignments.set!
|
679
|
+
|
680
|
+
@required.each do |arg|
|
681
|
+
g.dup
|
682
|
+
g.push_literal arg.name
|
683
|
+
g.send :find_item, 1, true
|
684
|
+
|
685
|
+
g.dup
|
686
|
+
g.gif missing_value
|
687
|
+
|
688
|
+
g.send :value, 0, true
|
689
|
+
|
690
|
+
arg.variable.set_bytecode(g)
|
691
|
+
g.pop
|
692
|
+
end
|
693
|
+
|
694
|
+
defaults = g.new_label
|
695
|
+
g.goto defaults
|
696
|
+
|
697
|
+
missing_value.set!
|
698
|
+
g.pop
|
699
|
+
g.push_rubinius
|
700
|
+
g.find_const :Runtime
|
701
|
+
g.swap
|
702
|
+
g.send :keywords_missing, 1, true
|
703
|
+
g.goto done
|
704
|
+
|
705
|
+
defaults.set!
|
706
|
+
|
707
|
+
extra_keys = g.new_label
|
708
|
+
|
709
|
+
if @defaults.empty?
|
710
|
+
g.dup
|
711
|
+
g.send :size, 0, true
|
712
|
+
g.push @arguments.size
|
713
|
+
g.swap
|
714
|
+
g.send :equal?, 1, true
|
715
|
+
g.gif extra_keys
|
716
|
+
|
717
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
718
|
+
g.push_cpath_top
|
719
|
+
g.find_const :Hash
|
720
|
+
g.send :allocate, 0, true
|
721
|
+
@kwrest.variable.set_bytecode(g)
|
722
|
+
g.pop
|
723
|
+
end
|
724
|
+
|
725
|
+
g.goto done
|
726
|
+
else
|
727
|
+
@defaults.each do |arg|
|
728
|
+
next_value = g.new_label
|
729
|
+
default_value = g.new_label
|
730
|
+
|
731
|
+
g.dup
|
732
|
+
g.push_literal arg.name
|
733
|
+
g.send :find_item, 1, true
|
734
|
+
|
735
|
+
g.dup
|
736
|
+
g.gif default_value
|
737
|
+
|
738
|
+
g.send :value, 0, true
|
739
|
+
arg.variable.set_bytecode(g)
|
740
|
+
g.goto next_value
|
741
|
+
|
742
|
+
default_value.set!
|
743
|
+
g.pop
|
744
|
+
arg.bytecode(g)
|
745
|
+
|
746
|
+
next_value.set!
|
747
|
+
g.pop
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
extra_keys.set!
|
752
|
+
|
753
|
+
g.dup
|
754
|
+
g.push_rubinius
|
755
|
+
g.find_const :Runtime
|
756
|
+
g.swap
|
757
|
+
|
758
|
+
if @kwrest
|
759
|
+
g.push :true
|
760
|
+
else
|
761
|
+
g.push :false
|
762
|
+
end
|
763
|
+
|
764
|
+
g.send :keywords_extra, 2, true
|
765
|
+
if @kwrest.kind_of? LocalVariableAssignment
|
766
|
+
@kwrest.variable.set_bytecode(g)
|
767
|
+
end
|
768
|
+
g.pop
|
769
|
+
|
770
|
+
done.set!
|
771
|
+
end
|
772
|
+
|
773
|
+
def kind_of_hash(g, label)
|
774
|
+
g.dup
|
775
|
+
g.push_cpath_top
|
776
|
+
g.find_const :Hash
|
777
|
+
g.swap
|
778
|
+
g.kind_of
|
779
|
+
g.git label
|
780
|
+
end
|
781
|
+
|
782
|
+
def to_sexp
|
783
|
+
sexp = [:kwargs]
|
784
|
+
sexp << @names unless @names.empty?
|
785
|
+
sexp << @defaults.map { |x| x.to_sexp } unless @defaults.empty?
|
786
|
+
sexp
|
787
|
+
end
|
788
|
+
end
|
789
|
+
|
656
790
|
module LocalVariable
|
657
791
|
attr_accessor :variable
|
658
792
|
end
|