   # 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 unless options and options.precompile
-    [pair[0].compile(o), pair[1].compile(o)]
+    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) ->

    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) ->

  # operands are only evaluated once, even though we have to reference them
  # more than once.
  compileAssignment: (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) } ? #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.
