Class: Opal::Nodes::BlockNode

Inherits:
Base
  • Object
show all
Defined in:
opal/lib/opal/nodes/definitions.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, Helpers::RESERVED_FUNCTION_NAMES

Instance Attribute Summary

Attributes inherited from Base

#compiler, #type

Instance Method Summary collapse

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, #has_rescue_else?, #helper, #in_ensure, #in_ensure?, #in_while?, #initialize, #process, #push, #recv, #recv?, #s, #scope, #stmt, #stmt?, truthy_optimize?, #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::Base

Instance Method Details

#child_is_expr?(child) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'opal/lib/opal/nodes/definitions.rb', line 117

def child_is_expr?(child)
  raw_expression?(child) and [:stmt, :stmt_closure].include?(@level)
end

#compileObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'opal/lib/opal/nodes/definitions.rb', line 97

def compile
  return push "nil" if children.empty?

  children.each_with_index do |child, idx|
    push stmt_join unless idx == 0

    if yasgn = find_inline_yield(child)
      push compiler.process(yasgn, @level)
      push ";"
    end

    push compiler.process(child, @level)
    push ";" if child_is_expr?(child)
  end
end

#find_inline_yield(stmt) ⇒ Sexp

When a block sexp gets generated, any inline yields (i.e. yield statements that are not direct members of the block) need to be generated as a top level member. This is because if a yield is returned by a break statement, then the method must return.

As inline expressions in javascript cannot return, the block must be rewritten.

For example, a yield inside an array:

[1, 2, 3, yield(4)]

Must be rewitten into:

tmp = yield 4
[1, 2, 3, tmp]

This rewriting happens on sexps directly.

Parameters:

  • stmt (Sexp)

    sexps to (maybe) rewrite

Returns:



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'opal/lib/opal/nodes/definitions.rb', line 146

def find_inline_yield(stmt)
  found = nil
  case stmt.first
  when :js_return
    if found = find_inline_yield(stmt[1])
      found = found[2]
    end
  when :array
    stmt[1..-1].each_with_index do |el, idx|
      if el.first == :yield
        found = el
        stmt[idx+1] = s(:js_tmp, '$yielded')
      end
    end
  when :call
    arglist = stmt[3]
    arglist[1..-1].each_with_index do |el, idx|
      if el.first == :yield
        found = el
        arglist[idx+1] = s(:js_tmp, '$yielded')
      end
    end
  end

  if found
    scope.add_temp '$yielded' unless scope.has_temp? '$yielded'
    s(:yasgn, '$yielded', found)
  end
end

#raw_expression?(child) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'opal/lib/opal/nodes/definitions.rb', line 121

def raw_expression?(child)
  ![:xstr, :dxstr].include?(child.type)
end

#stmt_joinObject



113
114
115
# File 'opal/lib/opal/nodes/definitions.rb', line 113

def stmt_join
  scope.class_scope? ? "\n\n#{current_indent}" : "\n#{current_indent}"
end