+
+ // The object is not yet evaluated, so call eval() to evaluate
+ // the top level. This will return either
+ // a) the original object with status_flags::evaluated set (when the
+ // eval() implementation calls hold())
+ // or
+ // b) a different expression.
+ //
+ // eval() returns an ex, not a basic&, so this will go through
+ // construct_from_basic() a second time. In case a) we end up in
+ // the "else" branch below. In case b) we end up here again and
+ // apply eval() once more. The recursion stops when eval() calls
+ // hold() or returns an object that already has its "evaluated"
+ // flag set, such as a symbol or a numeric.
+ const ex & tmpex = other.eval(1);
+
+ // Eventually, the eval() recursion goes through the "else" branch
+ // below, which assures that the object pointed to by tmpex.bp is
+ // allocated on the heap (either it was already on the heap or it
+ // is a heap-allocated duplicate of another object).
+ GINAC_ASSERT(tmpex.bp->flags & status_flags::dynallocated);
+
+ // If the original object is not referenced but heap-allocated,
+ // it means that eval() hit case b) above. The original object is
+ // no longer needed (it evaluated into something different), so we
+ // delete it (because nobody else will).
+ if ((other.get_refcount() == 0) && (other.flags & status_flags::dynallocated))
+ delete &other; // yes, you can apply delete to a const pointer
+
+ // We can't return a basic& here because the tmpex is destroyed as
+ // soon as we leave the function, which would deallocate the
+ // evaluated object.
+ return tmpex.bp;
+