CodeTools::AST << {

# TODO: remove from AST nodes, as this is just common behavior and has nothing itself to do with syntax
DeclaredScope < CodeTools::Compiler::LocalVariables, Node {
  var name, var body
  var scope_method

  bytecode: |g| {
    pos(g)

    # Register in the AST as a scope for local variable lookup
    # Right now, this just sets @parent to g.state.scope
    # (Necessary to pass local variables from above to memes below)
    g.state.scope.nest_scope(self)

    # This name is arbitrary and is just for the benefit of backtraces
    name = :__declaration__

    meth = new_generator(g, name)

    meth.push_state(self)
    meth.for_module_body = true

    meth.push_self
    meth.add_scope

    meth.state.push_name(name.to_sym)

    self.scope_method && (
      meth.push_scope
      meth.send(self.scope_method, 0)
      meth.pop
    )

    self.body.bytecode(meth)

    meth.state.pop_name

    meth.ret
    meth.close

    meth.local_count = local_count
    meth.local_names = local_names

    meth.pop_state

    g.create_block(meth)
    g.swap
    g.push_scope
    g.push_true
    g.send(:call_under, 3)

    meth
  }

  # Become the AST scope parent of the given AST scope Node .
  # This is only for the benefit of LocalVariableAccessAmbiguous
  # being able to call search_local, and has nothing to do with
  # the scope referenced by g.push_scope or g.add_scope
  nest_scope: |scope| scope.parent = self

  var parent

  # This is an abbreviated form of Block#search_local
  # because no locals can be assigned within the MycoModuleScope
  search_local: |name| {
    reference = self.parent.search_local(name)
    reference && (
      reference.depth = reference.depth + 1
      reference
    )
  }
}

}