   # operands are only evaluated once, even though we have to reference them
   # more than once.
   compileAssignment: (o) ->
-    [first, second] = [@first.compile(o), @second.compile(o)]
+    [first, firstVar] = @first.compileReference o, precompile: yes, assignment: yes
+    second = @second.compile o
     o.scope.find(first) if first.match(IDENTIFIER)
-    return "#first = #{ ExistenceNode.compileTest(o, @first) } ? #first : #second" if @operator is '?='
-    "#first = #first #{ @operator.substr(0, 2) } #second"
+    return "#first = #{ ExistenceNode.compileTest(o, @first) } ? #firstVar : #second" if @operator is '?='
+    "#first = #firstVar #{ @operator.substr(0, 2) } #second"
 
   # If this is an existence operator, we delegate to `ExistenceNode.compileTest`
   # to give us the safe references for the variables.

    node = o.chainRoot.base or o.chainRoot.variable
    while node instanceof CallNode then node = node.variable
    node is this

  # Override compile to unwrap the value when possible.
  compile: (o) ->

  # in multiple places, ensure that the expression is only ever evaluated once,
  # by assigning it to a temporary variable.
  compileReference: (o, options) ->
    options or= {}
    pair = if not ((this instanceof CallNode or @contains((n) -> n instanceof CallNode)) or
                  (this instanceof ValueNode and (not (@base instanceof LiteralNode) or @hasProperties())))
      [this, this]
    else if this instanceof ValueNode and options.assignment
      this.cacheIndexes(o)
    else
      reference = literal o.scope.freeVariable()
      compiled  = new AssignNode reference, this
      [compiled, reference]
    return [pair[0].compile(o), pair[1].compile(o)] if options.precompile
    pair

  # Convenience method to grab the current indentation level, plus tabbing in.
  idt: (tabs) ->
