class Malady::AST::FnNode

Attributes

arguments[R]
body[R]

Public Class Methods

new(filename, line, arguments, body) click to toggle source
# File lib/malady/ast.rb, line 182
def initialize(filename, line, arguments, body)
  @filename = filename
  @line = line
  @arguments = arguments
  @body = body
end

Public Instance Methods

bytecode(g) click to toggle source
# File lib/malady/ast.rb, line 189
def bytecode(g)
  pos(g)

  # get a new scope
  scope = Malady::Scope.new

  # nest the scope in the current context
  state = g.state
  state.scope.nest_scope scope

  # get a new generator for our block
  blk = new_block_generator(g, @arguments)

  # push our scope
  blk.push_state scope

  # setup the state in our block
  blk.state.push_super state.super
  blk.state.push_eval state.eval
  blk.state.push_name blk.name

  # our args are locals in the block
  @arguments.each do |id|
    blk.shift_array
    local = blk.state.scope.new_local(id.to_s)
    blk.set_local local.slot
    blk.pop
  end
  blk.pop if !@arguments.empty?

  # push the block
  blk.state.push_block

  # compile the body of the closure in the block
  body.bytecode(blk)

  # pop the block
  blk.state.pop_block
  blk.ret

  # pop the state
  blk.local_names = blk.state.scope.local_names
  blk.local_count = blk.state.scope.local_count
  blk.pop_state
  blk.close

  # create the block in our current generator
  g.create_block blk
end
new_block_generator(g, arguments) click to toggle source
# File lib/malady/ast.rb, line 239
def new_block_generator(g, arguments)
  blk = g.class.new
  blk.name = g.state.name || :__block__
  blk.file = g.file
  blk.for_block = true

  blk.required_args = arguments.count
  blk.post_args = arguments.count
  blk.total_args = arguments.count
  blk.cast_for_multi_block_arg if !arguments.count.zero?

  blk
end