class Opal::Nodes::ScopeNode

def add_arg(arg)

def add_arg(arg)
  @args << arg unless @args.include? arg
  arg
end

def add_proto_ivar(ivar)

def add_proto_ivar(ivar)
  @proto_ivars << ivar unless @proto_ivars.include? ivar
end

def add_scope_gvar(gvar)

def add_scope_gvar(gvar)
  @gvars << gvar unless @gvars.include? gvar
end

def add_scope_ivar(ivar)

def add_scope_ivar(ivar)
  if def_in_class?
    @parent.add_proto_ivar ivar
  else
    @ivars << ivar unless @ivars.include? ivar
  end
end

def add_scope_local(local)

def add_scope_local(local)
  return if has_local? local
  @locals << local
end

def add_scope_temp(*tmps)

def add_scope_temp(*tmps)
  @temps.push(*tmps)
end

def class?

Returns true if this is strictly a class scope
def class?
  @type == :class
end

def class_scope?

Returns true if this scope is a class/module body scope
def class_scope?
  @type == :class or @type == :module
end

def def?

def def?
  @type == :def
end

def def_in_class?

class body
used for optimizing ivars as we can set them to nil in the
Is this a normal def method directly inside a class? This is
def def_in_class?
  !@defs && @type == :def && @parent && @parent.class?
end

def find_parent_def

def find_parent_def
  scope = self
  while scope = scope.parent
    if scope.def?
      return scope
    end
  end
  nil
end

def get_super_chain

def get_super_chain
  chain, scope, defn, mid = [], self, 'null', 'null'
  while scope
    if scope.type == :iter
      chain << scope.identify!
      scope = scope.parent if scope.parent
    elsif scope.type == :def
      defn = scope.identify!
      mid  = "'#{scope.mid}'"
      break
    else
      break
    end
  end
  [chain, defn, mid]
end

def has_local?(local)

def has_local?(local)
  return true if @locals.include? local or @args.include? local
  return @parent.has_local?(local) if @parent and @type == :iter
  false
end

def has_temp?(tmp)

def has_temp?(tmp)
  @temps.include? tmp
end

def identify!

def identify!
  return @identity if @identity
  @identity = @compiler.unique_temp
  @parent.add_scope_temp @identity if @parent
  @identity
end

def identity

def identity
  @identity
end

def in_scope(&block)

def in_scope(&block)
  indent do
    @parent = compiler.scope
    compiler.scope = self
    block.call self
    compiler.scope = @parent
  end
end

def in_while?

def in_while?
  !@while_stack.empty?
end

def initialize(*)

def initialize(*)
  super
  @locals   = []
  @temps    = []
  @args     = []
  @ivars    = []
  @gvars    = []
  @parent   = nil
  @queue    = []
  @unique   = 'a'
  @while_stack = []
  @identity = nil
  @defs     = nil
  @methods = []
  @uses_block = false
  # used by classes to store all ivars used in direct def methods
  @proto_ivars = []
end

def iter?

True if a block/iter scope
def iter?
  @type == :iter
end

def module?

True if this is a module scope
def module?
  @type == :module
end

def new_temp

def new_temp
  return @queue.pop unless @queue.empty?
  tmp = next_temp
  @temps << tmp
  tmp
end

def next_temp

def next_temp
  tmp = "$#{@unique}"
  @unique = @unique.succ
  tmp
end

def pop_while

def pop_while
  @while_stack.pop
end

def proto

to where methods are actually added inside a class body.
by this function points to the classes' prototype. This is the target
Inside a class or module scope, the javascript variable name returned
def proto
  "def"
end

def push_while

def push_while
  info = {}
  @while_stack.push info
  info
end

def queue_temp(name)

def queue_temp(name)
  @queue << name
end

def sclass?

def sclass?
  @type == :sclass
end

def to_vars

Vars to use inside each scope
#
def to_vars
  vars = @temps.dup
  vars.push(*@locals.map { |l| "#{l} = nil" })
  iv = ivars.map do |ivar|
    "if (self#{ivar} == null) self#{ivar} = nil;\n"
  end
  gv = gvars.map do |gvar|
    "if ($gvars#{gvar} == null) $gvars#{gvar} = nil;\n"
  end
  indent = @compiler.parser_indent
  str  = vars.empty? ? '' : "var #{vars.join ', '};\n"
  str += "#{indent}#{iv.join indent}" unless ivars.empty?
  str += "#{indent}#{gv.join indent}" unless gvars.empty?
  if class? and !@proto_ivars.empty?
    #raise "FIXME to_vars"
    pvars = @proto_ivars.map { |i| "#{proto}#{i}"}.join(' = ')
    result = "%s\n%s%s = nil;" % [str, indent, pvars]
  else
    result = str
  end
  fragment(result)
end

def top?

Returns true if this is a top scope (main file body)
def top?
  @type == :top
end

def uses_block!

def uses_block!
  if @type == :iter && @parent
    @parent.uses_block!
  else
    @uses_block = true
    identify!
  end
end

def uses_block?

def uses_block?
  @uses_block
end