lib/opal/nodes/definitions.rb
# frozen_string_literal: true
require 'opal/nodes/base'
module Opal
module Nodes
class UndefNode < Base
handle :undef
children :value
def compile
children.each do |child|
line "Opal.udef(#{scope.self}, '$' + ", expr(child), ');'
end
end
end
class AliasNode < Base
handle :alias
children :new_name, :old_name
def compile
# We only need to check one type, because parser otherwise denies invalid expressions
case new_name.type
when :gvar # This is a gvar alias: alias $a $b
helper :alias_gvar
new_name_str = new_name.children.first.to_s[1..-1].inspect
old_name_str = old_name.children.first.to_s[1..-1].inspect
push '$alias_gvar(', new_name_str, ', ', old_name_str, ')'
when :dsym, :sym # This is a method alias: alias a b
helper :alias
compiler.record_method_call old_name.children.last if old_name.type == :sym
push "$alias(#{scope.self}, ", expr(new_name), ', ', expr(old_name), ')'
else # Nothing else is available, but just in case, drop an error
error "Opal doesn't know yet how to alias with #{new_name.type}"
end
end
end
class BeginNode < ScopeNode
handle :begin
def compile
return push 'nil' if children.empty?
if stmt?
compile_children(children, @level)
elsif simple_children?
compile_inline_children(children, @level)
wrap '(', ')' if children.size > 1
elsif children.size == 1
compile_inline_children(returned_children, @level)
else
in_closure do
compile_children(returned_children, @level)
end
if scope.parent&.await_encountered
wrap '(await (async function() {', '})())'
else
wrap '(function() {', '})()'
end
end
end
def returned_children
@returned_children ||= begin
*rest, last_child = *children
if last_child
rest + [compiler.returns(last_child)]
else
[s(:nil)]
end
end
end
def compile_children(children, level)
children.each do |child|
line process(child, level), fragment(';', loc: false)
end
end
COMPLEX_CHILDREN = %i[while while_post until until_post js_return].freeze
def simple_children?
children.none? do |child|
COMPLEX_CHILDREN.include?(child.type)
end
end
def compile_inline_children(children, level)
processed_children = children.map do |child|
process(child, level)
end
processed_children.reject(&:empty?).each_with_index do |child, idx|
push fragment(', ', loc: false) unless idx == 0
push child
end
end
end
class KwBeginNode < BeginNode
handle :kwbegin
end
end
end