class CodeTools::AST::MultipleAssignment
Attributes
block[RW]
left[RW]
post[RW]
right[RW]
splat[RW]
Public Class Methods
new(line, left, right, splat)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 543 def initialize(line, left, right, splat) @line = line @left = left @right = right @splat = nil @block = nil # support for |&b| @post = nil # in `a,*b,c`, c is in post. if splat.kind_of?(PostArg) @fixed = false @post = splat.rest splat = splat.into elsif right.kind_of?(ArrayLiteral) @fixed = right.body.size > 1 else @fixed = false end if splat.kind_of? Node if @left if right @splat = SplatAssignment.new line, splat else @splat = SplatWrapped.new line, splat end elsif @fixed @splat = SplatArray.new line, splat, right.body.size elsif right.kind_of? SplatValue @splat = splat else @splat = SplatWrapped.new line, splat end elsif splat # We need a node for eg { |*| } and { |a, *| } size = @fixed ? right.body.size : 0 @splat = EmptySplat.new line, size end end
Public Instance Methods
assign_values(g, array, index)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 799 def assign_values(g, array, index) array.body.each do |x| get_element(g, index) g.dup if x.kind_of? MultipleAssignment x.bytecode(g) g.pop end end
bytecode(g, array_on_stack=false)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 609 def bytecode(g, array_on_stack=false) declare_local_scope(g.state.scope) case @right when ArrayLiteral, SplatValue @right.bytecode(g) g.dup when ToArray @right.value.bytecode(g) g.dup convert_to_ary(g) when nil convert_to_ary(g) else @right.bytecode(g) g.dup convert_to_ary(g) end size = g.new_stack_local g.dup g.send :size, 0, true g.set_stack_local size g.pop index = g.new_stack_local g.push_int 0 g.set_stack_local index g.pop g.state.push_masgn assign_values g, @left, index if @left if @splat g.dup g.push_stack_local index check_count = g.new_label if @post g.push_stack_local size g.push_int @post.body.size g.send :-, 1, true g.push_stack_local index g.send :-, 1, true g.goto check_count else g.push_stack_local size g.push_stack_local index g.send :-, 1, true g.goto check_count end underflow = g.new_label assign_splat = g.new_label underflow.set! g.pop_many 3 g.make_array 0 g.goto assign_splat check_count.set! g.dup g.push_int 0 g.send :<, 1, true g.goto_if_true underflow g.dup g.push_stack_local index g.send :+, 1, true g.set_stack_local index g.pop g.send :[], 2, true assign_splat.set! # TODO: Fix nodes to work correctly. case @splat when EmptySplat # nothing when SplatArray, SplatWrapped @splat.value.bytecode(g) else @splat.bytecode(g) end g.pop end assign_values g, @post, index if @post g.state.pop_masgn g.pop end
convert_to_ary(g)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 709 def convert_to_ary(g) done = g.new_label coerce = g.new_label make_array = g.new_label dup_as_array = g.new_label instance_of_array(g, done) kind_of_array(g, dup_as_array) g.dup g.push_literal :to_ary g.push_true g.send :respond_to?, 2, true g.goto_if_true coerce make_array.set! g.make_array 1 g.goto done discard = g.new_label dup_as_array.set! g.dup g.push_rubinius g.find_const :Runtime g.swap g.send :dup_as_array, 1, true g.goto discard coerce.set! g.dup g.send :to_ary, 0, true check_array = g.new_label g.dup g.goto_if_not_nil check_array g.pop g.goto make_array check_array.set! kind_of_array(g, discard) g.push_type g.move_down 2 g.push_literal :to_ary g.push_cpath_top g.find_const :Array g.send :coerce_to_type_error, 4, true g.goto done discard.set! g.swap g.pop done.set! end
declare_local_scope(scope)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 586 def declare_local_scope(scope) # Fix the scope for locals introduced by the left. We # do this before running the code for the right so that # right side sees the proper scoping of the locals on the left. if @left @left.body.each do |var| case var when LocalVariable scope.assign_local_reference var when MultipleAssignment var.declare_local_scope(scope) end end end if @splat and @splat.kind_of?(SplatAssignment) if @splat.value.kind_of?(LocalVariable) scope.assign_local_reference @splat.value end end end
defined(g)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 808 def defined(g) g.push_literal "assignment" end
get_element(g, index)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 786 def get_element(g, index) g.dup g.push_stack_local index g.dup g.push_int 1 g.send :+, 1, true g.set_stack_local index g.pop g.send :[], 1, true end
instance_of_array(g, label)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 768 def instance_of_array(g, label) g.dup g.push_cpath_top g.find_const :Array g.swap g.instance_of g.goto_if_true label end
iter_arguments()
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 582 def iter_arguments @iter_arguments = true end
kind_of_array(g, label)
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 777 def kind_of_array(g, label) g.dup g.push_cpath_top g.find_const :Array g.swap g.kind_of g.goto_if_true label end
to_sexp()
click to toggle source
# File lib/rubinius/code/ast/variables.rb, line 812 def to_sexp left = @left ? @left.to_sexp : [:array] case @splat when EmptySplat left << [:splat] when nil else left << [:splat, @splat.to_sexp] end left << @block.to_sexp if @block sexp = [:masgn, left] sexp += @post.body.map { |x| x.to_sexp } if @post sexp << @right.to_sexp if @right sexp end