class Atomy::Code::Define
Public Class Methods
new(name, body = nil, receiver = nil, arguments = [], default_arguments = [], splat_argument = nil, post_arguments = [], proc_argument = nil)
click to toggle source
# File lib/atomy/code/define.rb, line 4 def initialize(name, body = nil, receiver = nil, arguments = [], default_arguments = [], splat_argument = nil, post_arguments = [], proc_argument = nil) @name = name @body = body @receiver = receiver @arguments = arguments @default_arguments = default_arguments @splat_argument = splat_argument @post_arguments = post_arguments @proc_argument = proc_argument end
Private Instance Methods
build_block(scope, mod, name, body)
click to toggle source
# File lib/atomy/code/define.rb, line 63 def build_block(scope, mod, name, body) Atomy::Compiler.generate(mod.file) do |blk| # set method name so calls to super work blk.name = name # close over the outer scope blk.state.scope.parent = scope total_patterns = 0 total_patterns += 1 if @receiver total_patterns += @arguments.size + @default_arguments.size + @post_arguments.size total_patterns += 1 if @splat_argument total_patterns += 1 if @proc_argument blk.total_args = total_patterns * 2 blk.required_args = blk.total_args # this bubbles up to Proc#arity and BlockEnvironment, though it # doesn't appear to change actual behavior of the block blk.arity = blk.total_args arg = 0 if @receiver blk.state.scope.new_local("arg:self:pat") blk.state.scope.new_local("arg:self") end @arguments.size.times do blk.state.scope.new_local(:"arg:#{arg}:pat") blk.state.scope.new_local(:"arg:#{arg}") arg += 1 end @default_arguments.size.times do blk.state.scope.new_local(:"arg:#{arg}:pat") blk.state.scope.new_local(:"arg:#{arg}") arg += 1 end if @splat_argument blk.state.scope.new_local(:"arg:splat:pat") blk.state.scope.new_local(:"arg:splat") end @post_arguments.size.times do blk.state.scope.new_local(:"arg:#{arg}:pat") blk.state.scope.new_local(:"arg:#{arg}") arg += 1 end if @proc_argument blk.state.scope.new_local(:"arg:proc:pat") blk.state.scope.new_local(:"arg:proc") end loc = 0 if p = receiver_pattern(mod) blk.push_local(loc) blk.push_local(loc+1) p.assign(blk) blk.pop_many(2) loc += 2 end pre_argument_patterns(mod).each do |p| blk.push_local(loc) blk.push_local(loc+1) p.assign(blk) blk.pop_many(2) loc += 2 end default_argument_patterns(mod).each do |d, p| assign = blk.new_label # [pat] blk.push_local(loc) # [val, pat] blk.push_local(loc+1) # [val, val, pat] blk.dup # [val, pat] blk.goto_if_not_undefined(assign) # [pat] blk.pop # [val, pat] mod.compile(blk, d.default) assign.set! # [val, pat] p.assign(blk) # [] blk.pop_many(2) loc += 2 end if p = splat_argument_pattern(mod) blk.push_local(loc) blk.push_local(loc+1) p.assign(blk) blk.pop_many(2) loc += 2 end post_argument_patterns(mod).each do |p| blk.push_local(loc) blk.push_local(loc+1) p.assign(blk) blk.pop_many(2) loc += 2 end if p = proc_argument_pattern(mod) blk.push_local(loc) blk.push_local(loc+1) p.assign(blk) blk.pop_many(2) loc += 2 end # build the method branch's body mod.compile(blk, body) end end
default_argument_patterns(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 215 def default_argument_patterns(mod) @default_argument_patterns ||= @default_arguments.collect do |d| [d, mod.pattern(d.node)] end end
post_argument_patterns(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 222 def post_argument_patterns(mod) @post_argument_patterns ||= @post_arguments.collect do |a| mod.pattern(a) end end
pre_argument_patterns(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 208 def pre_argument_patterns(mod) @pre_argument_patterns ||= @arguments.collect do |a| mod.pattern(a) end end
proc_argument_pattern(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 235 def proc_argument_pattern(mod) return unless @proc_argument @proc_argument_pattern ||= mod.pattern(@proc_argument) end
push_branch(gen, mod)
click to toggle source
# File lib/atomy/code/define.rb, line 19 def push_branch(gen, mod) gen.push_cpath_top gen.find_const(:Atomy) gen.find_const(:Method) gen.find_const(:Branch) if @receiver mod.compile(gen, receiver_pattern(mod)) else gen.push_nil end pre_argument_patterns(mod).each do |p| mod.compile(gen, p) end gen.make_array(@arguments.size) default_argument_patterns(mod).each do |d, p| mod.compile(gen, p) end gen.make_array(@default_arguments.size) if p = splat_argument_pattern(mod) mod.compile(gen, p) else gen.push_nil end post_argument_patterns(mod).each do |p| mod.compile(gen, p) end gen.make_array(@post_arguments.size) if p = proc_argument_pattern(mod) mod.compile(gen, p) else gen.push_nil end gen.create_block(build_block(gen.state.scope, mod, @name, @body)) gen.send_with_block(:new, 6) end
receiver_pattern(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 202 def receiver_pattern(mod) return unless @receiver @receiver_pattern ||= mod.pattern(@receiver) end
splat_argument_pattern(mod)
click to toggle source
# File lib/atomy/code/define.rb, line 229 def splat_argument_pattern(mod) return unless @splat_argument @splat_argument_pattern ||= mod.pattern(@splat_argument) end