class Opal::Parser::Scope

def add_arg(arg)

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

def add_ivar(ivar)

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

def add_local(local)

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

def add_proto_ivar(ivar)

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

def add_temp(*tmps)

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

def class?

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_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 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 = @parser.unique_temp
  @parent.add_temp @identity
  @identity
end

def identity

def identity
  @identity
end

def in_while?

def in_while?
  !@while_stack.empty?
end

def initialize(type, parser)

def initialize(type, parser)
  @parser  = parser
  @type    = type
  @locals  = []
  @temps   = []
  @args    = []
  @ivars   = []
  @parent  = nil
  @queue   = []
  @unique  = "a"
  @while_stack = []
  @defines_defs = false
  @defines_defn = false
  @methods  = []
  @smethods = []
  @uses_block = false
  # used by classes to store all ivars used in direct def methods
  @proto_ivars = []
end

def iter?

def iter?
  @type == :iter
end

def module?

def module?
  @type == :module
end

def new_temp

def new_temp
  return @queue.pop unless @queue.empty?
  tmp = "__#{@unique}"
  @unique = @unique.succ
  @temps << tmp
  tmp
end

def pop_while

def pop_while
  @while_stack.pop
end

def proto

def proto
  "#{ @name }_prototype"
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 to_donate_methods

Generates code for this module to donate methods
def to_donate_methods
  out = ""
  unless @methods.empty?
    out += "%s;#{@name}._donate([%s]);" %
      [@parser.parser_indent, @methods.map(&:inspect).join(', ')]
  end
  unless @smethods.empty?
    out += "%s;#{@name}._sdonate([%s]);" %
      [@parser.parser_indent, @smethods.map(&:inspect).join(', ')]
  end
  out
end

def to_vars

Vars to use inside each scope
#
def to_vars
  vars = locals.map { |l| "#{l} = nil" }
  vars.push *temps
  iv = ivars.map do |ivar|
   "if (this#{ivar} == null) this#{ivar} = nil;\n"
  end
  indent = @parser.parser_indent
  res = vars.empty? ? '' : "var #{vars.join ', '};"
  str = ivars.empty? ? res : "#{res}\n#{indent}#{iv.join indent}"
  if class? and !@proto_ivars.empty?
    pvars = @proto_ivars.map { |i| "#{proto}#{i}"}.join(' = ')
    "%s\n%s%s = nil;" % [str, indent, pvars]
  else
    str
  end
end

def top?

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