Class: Opal::Nodes::DefNode

Inherits:
ScopeNode show all
Defined in:
opal/lib/opal/nodes/def.rb

Overview

FIXME: needs rewrite

Constant Summary

Constants included from Helpers

Helpers::BASIC_IDENTIFIER_RULES, Helpers::ES3_RESERVED_WORD_EXCLUSIVE, Helpers::ES51_RESERVED_WORD, Helpers::IMMUTABLE_PROPS

Instance Attribute Summary

Attributes inherited from ScopeNode

#block_name, #catch_return, #defs, #gvars, #ivars, #methods, #mid, #name, #parent, #scope_name, #uses_super, #uses_zuper

Attributes inherited from Base

#compiler, #type

Instance Method Summary collapse

Methods inherited from ScopeNode

#add_arg, #add_proto_ivar, #add_scope_gvar, #add_scope_ivar, #add_scope_local, #add_scope_temp, #class?, #class_scope?, #def?, #def_in_class?, #find_parent_def, #get_super_chain, #has_local?, #has_temp?, #identify!, #identity, #in_scope, #in_while?, #initialize, #iter?, #module?, #new_temp, #next_temp, #pop_while, #proto, #push_while, #queue_temp, #sclass?, #should_donate?, #to_donate_methods, #to_vars, #top?, #uses_block!, #uses_block?

Methods inherited from Base

#add_gvar, #add_ivar, #add_local, #add_temp, children, #children, #compile_to_fragments, #error, #expr, #expr?, #expr_or_nil, #fragment, handle, handlers, #helper, #in_while?, #initialize, #process, #push, #recv, #recv?, #s, #scope, #stmt, #stmt?, #unshift, #while_loop, #with_temp, #wrap

Methods included from Helpers

#current_indent, #empty_line, #indent, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #lvar_to_js, #mid_to_jsid, #property, #valid_name?, #variable

Constructor Details

This class inherits a constructor from Opal::Nodes::ScopeNode

Instance Method Details

#arity_check(args, opt, splat, block_name, mid) ⇒ Object

Returns code used in debug mode to check arity of method call



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'opal/lib/opal/nodes/def.rb', line 121

def arity_check(args, opt, splat, block_name, mid)
  meth = mid.to_s.inspect

  arity = args.size - 1
  arity -= (opt.size - 1) if opt
  arity -= 1 if splat
  arity = -arity - 1 if opt or splat

  # $arity will point to our received arguments count
  aritycode = "var $arity = arguments.length;"

  if arity < 0 # splat or opt args
    aritycode + "if ($arity < #{-(arity + 1)}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
  else
    aritycode + "if ($arity !== #{arity}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
  end
end

#compileObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'opal/lib/opal/nodes/def.rb', line 11

def compile
  jsid = mid_to_jsid mid.to_s
  params = nil
  scope_name = nil

  # opt args if last arg is sexp
  opt = args.pop if Sexp === args.last

  argc = args.length - 1

  # block name (&block)
  if args.last.to_s.start_with? '&'
    block_name = variable(args.pop.to_s[1..-1]).to_sym
    argc -= 1
  end

  # splat args *splat
  if args.last.to_s.start_with? '*'
    uses_splat = true
    if args.last == :*
      argc -= 1
    else
      splat = args[-1].to_s[1..-1].to_sym
      args[-1] = splat
      argc -= 1
    end
  end

  if compiler.arity_check?
    arity_code = arity_check(args, opt, uses_splat, block_name, mid)
  end

  in_scope do
    scope.mid = mid
    scope.defs = true if recvr

    if block_name
      scope.uses_block!
      scope.add_arg block_name
    end

    yielder = block_name || '$yield'
    scope.block_name = yielder

    params = process(args)
    stmt_code = stmt(compiler.returns(stmts))

    add_temp 'self = this'

    line "#{variable(splat)} = $slice.call(arguments, #{argc});" if splat

    opt[1..-1].each do |o|
      next if o[2][2] == :undefined
      line "if (#{variable(o[1])} == null) {"
      line '  ', expr(o)
      line "}"
    end if opt

    # must do this after opt args incase opt arg uses yield
    scope_name = scope.identity

    if scope.uses_block?
      add_temp "$iter = #{scope_name}._p"
      add_temp "#{yielder} = $iter || nil"

      line "#{scope_name}._p = null;"
    end

    unshift "\n#{current_indent}", scope.to_vars
    line stmt_code

    unshift arity_code if arity_code

    unshift "var $zuper = $slice.call(arguments, 0);" if scope.uses_zuper

    if scope.catch_return
      unshift "try {\n"
      line "} catch ($returner) { if ($returner === $opal.returner) { return $returner.$v }"
      push " throw $returner; }"
    end
  end

  unshift ") {"
  unshift(params)
  unshift "function("
  unshift "#{scope_name} = " if scope_name
  line "}"

  if recvr
    unshift '$opal.defs(', recv(recvr), ", '$#{mid}', "
    push ')'
  elsif scope.class? and %w(Object BasicObject).include?(scope.name)
    wrap "$opal.defn(self, '$#{mid}', ", ')'
  elsif scope.class_scope?
    scope.methods << "$#{mid}"
    unshift "#{scope.proto}#{jsid} = "
  elsif scope.iter?
    wrap "$opal.defn(self, '$#{mid}', ", ')'
  elsif scope.type == :sclass
    unshift "self._proto#{jsid} = "
  elsif scope.top?
    unshift "$opal.Object._proto#{jsid} = "
  else
    unshift "def#{jsid} = "
  end

  wrap '(', ", nil) && '#{mid}'" if expr?
end