Wrapping all soaked chains that are involved in operations.

This commit is contained in:
Tim Jones
2010-05-04 01:04:26 +12:00
committed by Jeremy Ashkenas
parent 4d935efd09
commit ac05f62f2f
2 changed files with 57 additions and 35 deletions

View File

@@ -50,7 +50,9 @@ exports.BaseNode: class BaseNode
compile: (o) ->
@options: merge o or {}
@tab: o.indent
del @options, 'operation' unless this instanceof ValueNode
unless this instanceof ValueNode or this instanceof CallNode
del @options, 'operation'
del @options, 'chain_root' unless this instanceof AccessorNode or this instanceof IndexNode
top: if @top_sensitive() then @options.top else del @options, 'top'
closure: @is_statement() and not @is_pure_statement() and not top and
not @options.as_statement and not (this instanceof CommentNode) and
@@ -302,18 +304,17 @@ exports.ValueNode: class ValueNode extends BaseNode
# operators `?.` interspersed. Then we have to take care not to accidentally
# evaluate a anything twice when building the soak chain.
compile_node: (o) ->
soaked: false
only: del(o, 'only_first')
op: del(o, 'operation')
props: if only then @properties[0...@properties.length - 1] else @properties
baseline: @base.compile o
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
complete: @last: baseline
only: del(o, 'only_first')
op: del(o, 'operation')
props: if only then @properties[0...@properties.length - 1] else @properties
o.chain_root: this unless o.chain_root
baseline: @base.compile o
baseline: "($baseline)" if @base instanceof ObjectNode and @has_properties()
complete: @last: baseline
for prop in props
@source: baseline
if prop.soak_node
soaked: true
if @base instanceof CallNode and prop is props[0]
temp: o.scope.free_variable()
complete: "($temp = $complete)$@SOAK" + (baseline: temp + prop.compile(o))
@@ -324,8 +325,10 @@ exports.ValueNode: class ValueNode extends BaseNode
baseline: + part
complete: + part
@last: part
del o, 'chain_root'
if op and soaked then "($complete)" else complete
if op and @wrapped then "($complete)" else complete
#### CommentNode
@@ -377,11 +380,15 @@ exports.CallNode: class CallNode extends BaseNode
# Compile a vanilla function call.
compile_node: (o) ->
for arg in @args
return @compile_splat(o) if arg instanceof SplatNode
args: (arg.compile(o) for arg in @args).join(', ')
return @compile_super(args, o) if @is_super
"${@prefix()}${@variable.compile(o)}($args)"
o.chain_root: this unless o.chain_root
for arg in @args when arg instanceof SplatNode
compilation: @compile_splat(o)
unless compilation
args: (arg.compile(o) for arg in @args).join(', ')
compilation: if @is_super then @compile_super(args, o)
else "${@prefix()}${@variable.compile(o)}($args)"
del o, 'chain_root'
if o.operation and @wrapped then "($compilation)" else compilation
# `super()` is converted into a call against the superclass's implementation
# of the current function.
@@ -449,6 +456,7 @@ exports.AccessorNode: class AccessorNode extends BaseNode
this
compile_node: (o) ->
o.chain_root.wrapped: or @soak_node
proto_part: if @prototype then 'prototype.' else ''
".$proto_part${@name.compile(o)}"
@@ -462,6 +470,7 @@ exports.IndexNode: class IndexNode extends BaseNode
@soak_node: tag is 'soak'
compile_node: (o) ->
o.chain_root.wrapped: @soak_node
idx: @index.compile o
"[$idx]"