class Opal::Nodes::DefinedNode

def compile

def compile
  type = value.type
  case type
  when :self, :nil, :false, :true
    push type.to_s.inspect
  when :lasgn, :iasgn, :gasgn, :cvdecl, :masgn, :op_asgn_or, :op_asgn_and
    push "'assignment'"
  when :paren, :not
    push expr(s(:defined, value[1]))
  when :lvar
    push "'local-variable'"
  else
    if respond_to? "compile_#{type}"
      __send__ "compile_#{type}"
    else
      push "'expression'"
    end
  end
end

def compile_call

def compile_call
  mid = mid_to_jsid value[2].to_s
  recv = value[1] ? expr(value[1]) : 'self'
  with_temp do |tmp|
    push "(((#{tmp} = ", recv, "#{mid}) && !#{tmp}.$$stub) || ", recv
    push "['$respond_to_missing?']('#{value[2].to_s}') ? 'method' : nil)"
  end
end

def compile_colon2

def compile_colon2
  # TODO: avoid try/catch, probably a #process_colon2 alternative that
  # does not raise errors is needed
  push "(function(){ try { return (("
  push expr(value)
  push ") != null ? 'constant' : nil); } catch (err) { if (err.$$class"
  push " === Opal.NameError) { return nil; } else { throw(err); }}; })()"
end

def compile_colon3

def compile_colon3
  push "(Opal.Object.$$scope.#{value[1]} == null ? nil : 'constant')"
end

def compile_const

def compile_const
  push "($scope.#{value[1]} != null)"
end

def compile_cvar

def compile_cvar
  push "(Opal.cvars['#{value[1]}'] != null ? 'class variable' : nil)"
end

def compile_gvar

def compile_gvar
  name = value[1].to_s[1..-1]
  if %w[~ !].include? name
    push "'global-variable'"
  elsif %w[` ' + &].include? name
    with_temp do |tmp|
      push "((#{tmp} = $gvars['~'], #{tmp} != null && #{tmp} !== nil) ? "
      push "'global-variable' : nil)"
    end
  else
    push "($gvars[#{name.inspect}] != null ? 'global-variable' : nil)"
  end
end

def compile_ivar

def compile_ivar
  # FIXME: this check should be positive for ivars initialized as nil too.
  # Since currently all known ivars are inialized to nil in the constructor
  # we can't tell if it was the user that put nil and made the ivar #defined?
  # or not.
  with_temp do |tmp|
    name = value[1].to_s[1..-1]
    push "((#{tmp} = self['#{name}'], #{tmp} != null && #{tmp} !== nil) ? "
    push "'instance-variable' : nil)"
  end
end

def compile_nth_ref

def compile_nth_ref
  with_temp do |tmp|
    push "((#{tmp} = $gvars['~'], #{tmp} != null && #{tmp} != nil) ? "
    push "'global-variable' : nil)"
  end
end

def compile_super

def compile_super
  push expr(s(:defined_super, value))
end

def compile_xstr

def compile_xstr
  push expr(value)
  wrap '(typeof(', ') !== "undefined")'
end

def compile_yield

def compile_yield
  push compiler.handle_block_given_call(@sexp)
  wrap '((',  ') != null ? "yield" : nil)'
end