Class: Opal::Nodes::BlockNode

Inherits:
Base
  • Object
show all
Defined in:
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

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, #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::Base

Instance Method Details

#child_is_expr?(child) ⇒ Boolean


108
109
110
# File 'lib/opal/nodes/definitions.rb', line 108

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

#compileObject


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/opal/nodes/definitions.rb', line 88

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.


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/opal/nodes/definitions.rb', line 137

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


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

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

#stmt_joinObject


104
105
106
# File 'lib/opal/nodes/definitions.rb', line 104

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