class Atomy::Method
Attributes
branches[R]
name[R]
Public Class Methods
new(name)
click to toggle source
# File lib/atomy/method.rb, line 84 def initialize(name) @name = name @branches = [] end
Public Instance Methods
add_branch(branch)
click to toggle source
# File lib/atomy/method.rb, line 91 def add_branch(branch) @branches << branch if branch.method? @@tick += 1 branch.name = :"#{@name}:branch:#{@@tick}" end branch end
build()
click to toggle source
# File lib/atomy/method.rb, line 102 def build Atomy::Compiler.package(:__wrapper__) do |gen| gen.name = @name pre, default, splat, post = argument_form gen.total_args = pre + default + post gen.required_args = pre + post gen.splat_index = splat gen.post_args = post arg = 0 pre.times do gen.state.scope.new_local(:"arg:#{arg}") arg += 1 end default.times do gen.state.scope.new_local(:"arg:#{arg}") arg += 1 end if gen.splat_index gen.state.scope.new_local(:"arg:splat") end post.times do gen.state.scope.new_local(:"arg:#{arg}") arg += 1 end done = gen.new_label build_branches(gen, done) try_super(gen, done) unless @name == :initialize raise_mismatch(gen) gen.push_nil done.set! end.tap do |cm| cm.scope = Rubinius::LexicalScope.new(Object) end end
Private Instance Methods
argument_form()
click to toggle source
# File lib/atomy/method.rb, line 162 def argument_form return [0, 0, nil, 0] if @branches.empty? raise InconsistentArgumentForms unless uniform_argument_forms? [ @branches.collect(&:pre_arguments_count).first, @branches.collect(&:default_arguments_count).max, @branches.collect(&:splat_index).first, @branches.collect(&:post_arguments_count).first, ] end
build_branches(gen, done)
click to toggle source
# File lib/atomy/method.rb, line 175 def build_branches(gen, done) @branches.each do |b| skip = gen.new_label # check for too few arguments gen.passed_arg(b.pre_arguments_count - 1) gen.goto_if_false(skip) # check for too many arguments unless b.splat_index gen.passed_arg(b.pre_arguments_count + b.default_arguments_count + b.post_arguments_count) gen.goto_if_true(skip) end if b.receiver gen.push_self b.receiver.inline_matches?(gen) gen.goto_if_false(skip) end arg = 0 b.arguments.each do |pat| gen.push_local(arg) pat.inline_matches?(gen) gen.goto_if_false(skip) arg += 1 end b.default_arguments.each do |pat| skip_check = gen.new_label gen.push_local(arg) gen.goto_if_undefined(skip_check) gen.push_local(arg) pat.inline_matches?(gen) gen.goto_if_false(skip) skip_check.set! arg += 1 end if b.splat_argument gen.push_local(b.splat_index) b.splat_argument.inline_matches?(gen) gen.goto_if_false(skip) arg += 1 end b.post_arguments.each do |pat| gen.push_local(arg) pat.inline_matches?(gen) gen.goto_if_false(skip) arg += 1 end if b.proc_argument gen.push_proc b.proc_argument.inline_matches?(gen) gen.goto_if_false(skip) end branch_args = 0 method_arg = 0 if pat = b.receiver gen.push_literal(pat) gen.push_self branch_args += 2 end b.arguments.each do |pat| gen.push_literal(pat) gen.push_local(method_arg) method_arg += 1 branch_args += 2 end b.default_arguments.each do |pat| gen.push_literal(pat) gen.push_local(method_arg) method_arg += 1 branch_args += 2 end if pat = b.splat_argument gen.push_literal(pat) gen.push_local(b.splat_index) method_arg += 1 branch_args += 2 end b.post_arguments.each do |pat| gen.push_literal(pat) gen.push_local(method_arg) method_arg += 1 branch_args += 2 end if pat = b.proc_argument gen.push_literal(pat) gen.push_proc branch_args += 2 end if b.name gen.push_self gen.move_down(branch_args) gen.send(b.name, branch_args, true) else gen.push_literal(b.as_method) gen.move_down(branch_args) gen.push_literal(@name) gen.move_down(branch_args) gen.push_literal(b.body.lexical_scope.module) gen.move_down(branch_args) gen.push_self gen.move_down(branch_args) gen.make_array(branch_args) gen.push_nil gen.send(:invoke, 5) end gen.goto(done) skip.set! end end
raise_mismatch(gen)
click to toggle source
# File lib/atomy/method.rb, line 329 def raise_mismatch(gen) gen.push_cpath_top gen.find_const(:Atomy) gen.find_const(:MessageMismatch) gen.push_literal(@name) gen.push_self gen.send(:new, 2) gen.raise_exc end
try_super(gen, done)
click to toggle source
# File lib/atomy/method.rb, line 315 def try_super(gen, done) no_super = gen.new_label gen.invoke_primitive(:vm_check_super_callable, 0) gen.goto_if_false(no_super) gen.push_proc gen.zsuper(@name) gen.goto(done) no_super.set! end
uniform_argument_forms?()
click to toggle source
# File lib/atomy/method.rb, line 149 def uniform_argument_forms? return true if @branches.empty? return false unless @branches.collect(&:pre_arguments_count).uniq.size == 1 return false unless @branches.collect(&:splat_index).uniq.size == 1 return false unless @branches.collect(&:post_arguments_count).uniq.size == 1 # permit varying default argument counts; as long as the rest are the # same it's unambiguous true end