Class: Opal::Nodes::IterNode

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

Constant Summary

Constants included from Helpers

Helpers::BASIC_IDENTIFIER_RULES, Helpers::ES3_RESERVED_WORD_EXCLUSIVE, Helpers::ES51_RESERVED_WORD, Helpers::IMMUTABLE_PROPS, Helpers::PROTO_SPECIAL_METHODS, Helpers::PROTO_SPECIAL_PROPS

Instance Attribute Summary

Attributes inherited from ScopeNode

#block_name, #catch_return, #defs, #gvars, #ivars, #locals, #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?, #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, #ivar, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #lvar_to_js, #mid_to_jsid, #property, #valid_ivar_name?, #valid_name?, #variable

Constructor Details

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

Instance Method Details

#argsObject



99
100
101
102
103
104
105
106
107
# File 'opal/lib/opal/nodes/iter.rb', line 99

def args
  if Fixnum === args_sexp or args_sexp.nil?
    s(:array)
  elsif args_sexp.type == :lasgn
    s(:array, args_sexp)
  else
    args_sexp[1]
  end
end

#args_to_params(sexp) ⇒ Object

Maps block args into array of jsid. Adds $ suffix to invalid js identifiers.

s(:args, parts...) => ["a", "b", "break$"]



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'opal/lib/opal/nodes/iter.rb', line 117

def args_to_params(sexp)
  result = []
  sexp.each do |arg|
    if arg[0] == :lasgn
      ref = variable(arg[1])
      next if ref == :_ && result.include?(ref)
      self.add_arg ref
      result << ref
    elsif arg[0] == :array
      result << scope.next_temp
    else
      raise "Bad js_block_arg: #{arg[0]}"
    end
  end

  result
end

#bodyObject



109
110
111
# File 'opal/lib/opal/nodes/iter.rb', line 109

def body
  compiler.returns(body_sexp || s(:nil))
end

#compileObject



10
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
# File 'opal/lib/opal/nodes/iter.rb', line 10

def compile
  opt_args  = extract_opt_args
  block_arg = extract_block_arg

  # find any splat args
  if args.last.is_a?(Sexp) and args.last.type == :splat
    splat = args.last[1][1]
    args.pop
    len = args.length
  end

  params = args_to_params(args[1..-1])
  params << splat if splat

  to_vars = identity = body_code = nil

  in_scope do
    identity = scope.identify!
    add_temp "self = #{identity}.$$s || this"

    compile_args(args[1..-1], opt_args, params)

    if splat
      scope.add_arg splat
      push "#{splat} = $slice.call(arguments, #{len - 1});"
    end

    if block_arg
      scope.block_name = block_arg
      scope.add_temp block_arg
      scope_name = scope.identify!

      line "#{block_arg} = #{scope_name}.$$p || nil, #{scope_name}.$$p = null;"
    end

    body_code = stmt(body)
    to_vars = scope.to_vars
  end

  line body_code

  unshift to_vars

  unshift "(#{identity} = function(#{params.join ', '}){"
  push "}, #{identity}.$$s = self, #{identity})"
end

#compile_args(args, opt_args, params) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'opal/lib/opal/nodes/iter.rb', line 57

def compile_args(args, opt_args, params)
  args.each_with_index do |arg, idx|
    if arg.type == :lasgn
      arg = variable(arg[1])

      if opt_args and current_opt = opt_args.find { |s| s[1] == arg.to_sym }
        push "if (#{arg} == null) #{arg} = ", expr(current_opt[2]), ";"
      else
        push "if (#{arg} == null) #{arg} = nil;"
      end
    elsif arg.type == :array
      vars = {}
      arg[1..-1].each_with_index do |_arg, _idx|
        _arg = variable(_arg[1])
        unless vars.has_key?(_arg) || params.include?(_arg)
          vars[_arg] = "#{params[idx]}[#{_idx}]"
        end
      end
      push "var #{ vars.map{|k, v| "#{k} = #{v}"}.join(', ') };"
    else
      raise "Bad block arg type"
    end
  end
end

#extract_block_argObject

does this iter define a block_pass



92
93
94
95
96
97
# File 'opal/lib/opal/nodes/iter.rb', line 92

def extract_block_arg
  if args.last.is_a?(Sexp) and args.last.type == :block_pass
    block_arg = args.pop
    block_arg = block_arg[1][1].to_sym
  end
end

#extract_opt_argsObject

opt args are last (if present) and are a s(:block)



83
84
85
86
87
88
89
# File 'opal/lib/opal/nodes/iter.rb', line 83

def extract_opt_args
  if args.last.is_a?(Sexp) and args.last.type == :block
    opt_args = args.pop
    opt_args.shift
    opt_args
  end
end