Skip to content

Commit

Permalink
Some more nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Oct 22, 2013
1 parent 137d6e2 commit b003431
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 110 deletions.
3 changes: 2 additions & 1 deletion lib/opal/nodes/helpers.rb
Expand Up @@ -45,7 +45,8 @@ def js_falsy(sexp)
if sexp.type == :call
mid = sexp[2]
if mid == :block_given?
return @parser.handle_block_given(sexp, true)
scope.uses_block!
return "#{scope.block_name} === nil"
end
end

Expand Down
62 changes: 62 additions & 0 deletions lib/opal/nodes/literal.rb
Expand Up @@ -225,5 +225,67 @@ def compile_hash2(keys, values)
wrap "$hash2([#{hash_keys.join ', '}], {", "})"
end
end

class ArrayNode < Node
def compile
return push('[]') if children.empty?

code, work = [], []

children.each do |child|
splat = child.type == :splat
part = expr(child)

if splat
if work.empty?
if code.empty?
code << fragment("[].concat(") << part << fragment(")")
else
code << fragment(".concat(") << part << fragment(")")
end
else
if code.empty?
code << fragment("[") << work << fragment("]")
else
code << fragment(".concat([") << work << fragment("])")
end

code << fragment(".concat(") << part << fragment(")")
end
work = []
else
work << fragment(", ") unless work.empty?
work << part
end
end

unless work.empty?
join = [fragment("["), work, fragment("]")]

if code.empty?
code = join
else
code.push([fragment(".concat("), join, fragment(")")])
end
end

push code
end
end

# def args list
class ArgsNode < Node
def compile
children.each_with_index do |child, idx|
next if child.to_s == '*'

child = child.to_sym
push ', ' unless idx == 0
child = @parser.lvar_to_js child
scope.add_arg child
push child.to_s
end
end
end
end
end
111 changes: 2 additions & 109 deletions lib/opal/parser.rb
Expand Up @@ -50,6 +50,8 @@ def add_handler(klass, *types)
add_handler ExclusiveRangeNode, :dot2
add_handler InclusiveRangeNode, :dot3
add_handler HashNode, :hash
add_handler ArrayNode, :array
add_handler ArgsNode, :args

# variables
add_handler LocalVariableNode, :lvar
Expand Down Expand Up @@ -542,13 +544,6 @@ def js_block_given(sexp, level)
end
end

def handle_block_given(sexp, reverse = false)
@scope.uses_block!
name = @scope.block_name

f((reverse ? "#{ name } === nil" : "#{ name } !== nil"), sexp)
end

# A block/iter with embeded call. Compiles into function
# s(:iter, block_args [, body) => (function() { ... })
def process_iter(sexp, level)
Expand Down Expand Up @@ -926,107 +921,5 @@ def arity_check(args, opt, splat, block_name, mid)
aritycode + "if ($arity !== #{arity}) { $opal.ac($arity, #{arity}, this, #{meth}); }"
end
end

def process_args(exp, level)
args = []

exp.each do |a|
a = a.to_sym
next if a.to_s == '*'
a = lvar_to_js a
@scope.add_arg a
args << a
end

f(args.join(', '), exp)
end

# s(:array [, sexp [, sexp]]) => [...]
def process_array(sexp, level)
return [f("[]", sexp)] if sexp.empty?

code, work = [], []

sexp.each do |current|
splat = current.first == :splat
part = process current

if splat
if work.empty?
if code.empty?
code << f("[].concat(", sexp) << part << f(")", sexp)
else
code << f(".concat(", sexp) << part << f(")", sexp)
end
else
if code.empty?
code << f("[", sexp) << work << f("]", sexp)
else
code << f(".concat([", sexp) << work << f("])", sexp)
end

code << f(".concat(", sexp) << part << f(")", sexp)
end
work = []
else
work << f(", ", current) unless work.empty?
work << part
end
end

unless work.empty?
join = [f("[", sexp), work, f("]", sexp)]

if code.empty?
code = join
else
code.push([f(".concat(", sexp), join, f(")", sexp)])
end
end

code
end

def js_truthy_optimize(sexp)
if sexp.first == :call
mid = sexp[2]
if mid == :block_given?
return process sexp
elsif COMPARE.include? mid.to_s
return process sexp
elsif mid == :"=="
return process sexp
end
elsif [:lvar, :self].include? sexp.first
[process(sexp.dup), f(" !== false && ", sexp), process(sexp.dup), f(" !== nil", sexp)]
end
end

def js_truthy(sexp)
if optimized = js_truthy_optimize(sexp)
return optimized
end

with_temp do |tmp|
[f("(#{tmp} = ", sexp), process(sexp), f(") !== false && #{tmp} !== nil", sexp)]
end
end

def js_falsy(sexp)
if sexp.first == :call
mid = sexp[2]
if mid == :block_given?
return handle_block_given(sexp, true)
end
end

with_temp do |tmp|
result = []
result << f("(#{tmp} = ", sexp)
result << process(sexp)
result << f(") === false || #{tmp} === nil", sexp)
result
end
end
end
end

0 comments on commit b003431

Please sign in to comment.