/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.calculator2;

import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import android.text.Spannable;
import android.util.Log;

import com.hp.creals.CR;

import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * This implements the calculator evaluation logic.
 * Logically this maintains a signed integer indexed set of expressions, one of which
 * is distinguished as the main expression.
 * The main expression is constructed and edited with append(), delete(), etc.
 * An evaluation an then be started with a call to evaluateAndNotify() or requireResult().
 * This starts an asynchronous computation, which requests display of the initial result, when
 * available.  When initial evaluation is complete, it calls the associated listener's
 * onEvaluate() method.  This occurs in a separate event, possibly quite a bit later.  Once a
 * result has been computed, and before the underlying expression is modified, the
 * getString(index) method may be used to produce Strings that represent approximations to various
 * precisions.
 *
 * Actual expressions being evaluated are represented as {@link CalculatorExpr}s.
 *
 * The Evaluator holds the expressions and all associated state needed for evaluating
 * them.  It provides functionality for saving and restoring this state.  However the underlying
 * CalculatorExprs are exposed to the client, and may be directly accessed after cancelling any
 * in-progress computations by invoking the cancelAll() method.
 *
 * When evaluation is requested, we invoke the eval() method on the CalculatorExpr from a
 * background AsyncTask.  A subsequent getString() call for the same expression index returns
 * immediately, though it may return a result containing placeholder ' ' characters.  If we had to
 * return palceholder characters, we start a background task, which invokes the onReevaluate()
 * callback when it completes.  In either case, the background task computes the appropriate
 * result digits by evaluating the UnifiedReal returned by CalculatorExpr.eval() to the required
 * precision.
 *
 * We cache the best decimal approximation we have already computed.  We compute generously to
 * allow for some scrolling without recomputation and to minimize the chance of digits flipping
 * from "0000" to "9999".  The best known result approximation is maintained as a string by
 * mResultString (and often in a different format by the CR representation of the result).  When
 * we are in danger of not having digits to display in response to further scrolling, we also
 * initiate a background computation to higher precision, as if we had generated placeholder
 * characters.
 *
 * The code is designed to ensure that the error in the displayed result (excluding any
 * placeholder characters) is always strictly less than 1 in the last displayed digit.  Typically
 * we actually display a prefix of a result that has this property and additionally is computed to
 * a significantly higher precision.  Thus we almost always round correctly towards zero.  (Fully
 * correct rounding towards zero is not computable, at least given our representation.)
 *
 * Initial expression evaluation may time out.  This may happen in the case of domain errors such
 * as division by zero, or for large computations.  We do not currently time out reevaluations to
 * higher precision, since the original evaluation precluded a domain error that could result in
 * non-termination.  (We may discover that a presumed zero result is actually slightly negative
 * when re-evaluated; but that results in an exception, which we can handle.)  The user can abort
 * either kind of computation.
 *
 * We ensure that only one evaluation of either kind (AsyncEvaluator or AsyncReevaluator) is
 * running at a time.
 */
public class Evaluator implements CalculatorExpr.ExprResolver {

    private static Evaluator evaluator;

    public static String TIMEOUT_DIALOG_TAG = "timeout";

    @NonNull
    public static Evaluator getInstance(Context context) {
        if (evaluator == null) {
            evaluator = new Evaluator(context.getApplicationContext());
        }
        return evaluator;
    }

    public interface EvaluationListener {
        /**
         * Called if evaluation was explicitly cancelled or evaluation timed out.
         */
        public void onCancelled(long index);
        /**
         * Called if evaluation resulted in an error.
         */
        public void onError(long index, int errorId);
        /**
         * Called if evaluation completed normally.
         * @param index index of expression whose evaluation completed
         * @param initPrecOffset the offset used for initial evaluation
         * @param msdIndex index of first non-zero digit in the computed result string
         * @param lsdOffset offset of last digit in result if result has finite decimal
         *        expansion
         * @param truncatedWholePart the integer part of the result
         */
        public void onEvaluate(long index, int initPrecOffset, int msdIndex, int lsdOffset,
                String truncatedWholePart);
        /**
         * Called in response to a reevaluation request, once more precision is available.
         * Typically the listener wil respond by calling getString() to retrieve the new
         * better approximation.
         */
        public void onReevaluate(long index);  // More precision is now available; please redraw.
    }

    /**
     * A query interface for derived information based on character widths.
     * This provides information we need to calculate the "preferred precision offset" used
     * to display the initial result. It's used to compute the number of digits we can actually
     * display. All methods are callable from any thread.
     */
    public interface CharMetricsInfo {
        /**
         * Return the maximum number of (adjusted, digit-width) characters that will fit in the
         * result display.  May be called asynchronously from non-UI thread.
         */
       public int getMaxChars();
        /**
         * Return the number of additional digit widths required to add digit separators to
         * the supplied string prefix.
         * The prefix consists of the first len characters of string s, which is presumed to
         * represent a whole number. Callable from non-UI thread.
         * Returns zero if metrics information is not yet available.
         */
        public float separatorChars(String s, int len);
        /**
         * Return extra width credit for presence of a decimal point, as fraction of a digit width.
         * May be called by non-UI thread.
         */
        public float getDecimalCredit();
        /**
         * Return extra width credit for absence of ellipsis, as fraction of a digit width.
         * May be called by non-UI thread.
         */
        public float getNoEllipsisCredit();
    }

    /**
     * A CharMetricsInfo that can be used when we are really only interested in computing
     * short representations to be embedded on formulas.
     */
    private class DummyCharMetricsInfo implements CharMetricsInfo {
        @Override
        public int getMaxChars() {
            return SHORT_TARGET_LENGTH + 10;
        }
        @Override
        public float separatorChars(String s, int len) {
            return 0;
        }
        @Override
        public float getDecimalCredit() {
            return 0;
        }
        @Override
        public float getNoEllipsisCredit() {
            return 0;
        }
    }

    private final DummyCharMetricsInfo mDummyCharMetricsInfo = new DummyCharMetricsInfo();

    public static final long MAIN_INDEX = 0;  // Index of main expression.
    // Once final evaluation of an expression is complete, or when we need to save
    // a partial result, we copy the main expression to a non-zero index.
    // At that point, the expression no longer changes, and is preserved
    // until the entire history is cleared. Only expressions at nonzero indices
    // may be embedded in other expressions.
    // Each expression index can only have one outstanding evaluation request at a time.
    // To avoid conflicts between the history and main View, we copy the main expression
    // to allow independent evaluation by both.
    public static final long HISTORY_MAIN_INDEX = -1;  // Read-only copy of main expression.
    // To update e.g. "memory" contents, we copy the corresponding expression to a permanent
    // index, and then remember that index.
    private long mSavedIndex;  // Index of "saved" expression mirroring clipboard. 0 if unused.
    private long mMemoryIndex;  // Index of "memory" expression. 0 if unused.

    // When naming variables and fields, "Offset" denotes a character offset in a string
    // representing a decimal number, where the offset is relative to the decimal point.  1 =
    // tenths position, -1 = units position.  Integer.MAX_VALUE is sometimes used for the offset
    // of the last digit in an a nonterminating decimal expansion.  We use the suffix "Index" to
    // denote a zero-based absolute index into such a string. (In other contexts, like above,
    // we also use "index" to refer to the key in mExprs below, the list of all known
    // expressions.)

    private static final String KEY_PREF_DEGREE_MODE = "degree_mode";
    private static final String KEY_PREF_SAVED_INDEX = "saved_index";
    private static final String KEY_PREF_MEMORY_INDEX = "memory_index";
    private static final String KEY_PREF_SAVED_NAME = "saved_name";

    // The minimum number of extra digits we always try to compute to improve the chance of
    // producing a correctly-rounded-towards-zero result.  The extra digits can be displayed to
    // avoid generating placeholder digits, but should only be displayed briefly while computing.
    private static final int EXTRA_DIGITS = 20;

    // We adjust EXTRA_DIGITS by adding the length of the previous result divided by
    // EXTRA_DIVISOR.  This helps hide recompute latency when long results are requested;
    // We start the recomputation substantially before the need is likely to be visible.
    private static final int EXTRA_DIVISOR = 5;

    // In addition to insisting on extra digits (see above), we minimize reevaluation
    // frequency by precomputing an extra PRECOMPUTE_DIGITS
    // + <current_precision_offset>/PRECOMPUTE_DIVISOR digits, whenever we are forced to
    // reevaluate.  The last term is dropped if prec < 0.
    private static final int PRECOMPUTE_DIGITS = 30;
    private static final int PRECOMPUTE_DIVISOR = 5;

    // Initial evaluation precision.  Enough to guarantee that we can compute the short
    // representation, and that we rarely have to evaluate nonzero results to MAX_MSD_PREC_OFFSET.
    // It also helps if this is at least EXTRA_DIGITS + display width, so that we don't
    // immediately need a second evaluation.
    private static final int INIT_PREC = 50;

    // The largest number of digits to the right of the decimal point to which we will evaluate to
    // compute proper scientific notation for values close to zero.  Chosen to ensure that we
    // always to better than IEEE double precision at identifying nonzeros. And then some.
    // This is used only when we cannot a priori determine the most significant digit position, as
    // we always can if we have a rational representation.
    private static final int MAX_MSD_PREC_OFFSET = 1100;

    // If we can replace an exponent by this many leading zeroes, we do so.  Also used in
    // estimating exponent size for truncating short representation.
    private static final int EXP_COST = 3;

    // Listener that reports changes to the state (empty/filled) of memory. Protected for testing.
    private Callback mCallback;

    // Context for database helper.
    private Context mContext;

    //  A hopefully unique name associated with mSaved.
    private String mSavedName;

    // The main expression may have changed since the last evaluation in ways that would affect its
    // value.
    private boolean mChangedValue;

    // The main expression contains trig functions.
    private boolean mHasTrigFuncs;

    public static final int INVALID_MSD = Integer.MAX_VALUE;

    // Used to represent an erroneous result or a required evaluation. Not displayed.
    private static final String ERRONEOUS_RESULT = "ERR";

    /**
     * An individual CalculatorExpr, together with its evaluation state.
     * Only the main expression may be changed in-place. The HISTORY_MAIN_INDEX expression is
     * periodically reset to be a fresh immutable copy of the main expression.
     * All other expressions are only added and never removed. The expressions themselves are
     * never modified.
     * All fields other than mExpr and mVal are touched only by the UI thread.
     * For MAIN_INDEX, mExpr and mVal may change, but are also only ever touched by the UI thread.
     * For all other expressions, mExpr does not change once the ExprInfo has been (atomically)
     * added to mExprs. mVal may be asynchronously set by any thread, but we take care that it
     * does not change after that. mDegreeMode is handled exactly like mExpr.
     */
    private class ExprInfo {
        public CalculatorExpr mExpr;  // The expression itself.
        public boolean mDegreeMode;  // Evaluating in degree, not radian, mode.
        public ExprInfo(CalculatorExpr expr, boolean dm) {
            mExpr = expr;
            mDegreeMode = dm;
            mVal = new AtomicReference<UnifiedReal>();
        }

        // Currently running expression evaluator, if any.  This is either an AsyncEvaluator
        // (if mResultString == null or it's obsolete), or an AsyncReevaluator.
        // We arrange that only one evaluator is active at a time, in part by maintaining
        // two separate ExprInfo structure for the main and history view, so that they can
        // arrange for independent evaluators.
        public AsyncTask mEvaluator;

        // The remaining fields are valid only if an evaluation completed successfully.
        // mVal always points to an AtomicReference, but that may be null.
        public AtomicReference<UnifiedReal> mVal;
        // We cache the best known decimal result in mResultString.  Whenever that is
        // non-null, it is computed to exactly mResultStringOffset, which is always > 0.
        // Valid only if mResultString is non-null and (for the main expression) !mChangedValue.
        // ERRONEOUS_RESULT indicates evaluation resulted in an error.
        public String mResultString;
        public int mResultStringOffset = 0;
        // Number of digits to which (possibly incomplete) evaluation has been requested.
        // Only accessed by UI thread.
        public int mResultStringOffsetReq = 0;
        // Position of most significant digit in current cached result, if determined.  This is just
        // the index in mResultString holding the msd.
        public int mMsdIndex = INVALID_MSD;
        // Long timeout needed for evaluation?
        public boolean mLongTimeout = false;
        public long mTimeStamp;
    }

    private ConcurrentHashMap<Long, ExprInfo> mExprs = new ConcurrentHashMap<Long, ExprInfo>();

    // The database holding persistent expressions.
    private ExpressionDB mExprDB;

    private ExprInfo mMainExpr;  //  == mExprs.get(MAIN_INDEX)

    private SharedPreferences mSharedPrefs;

    private final Handler mTimeoutHandler;  // Used to schedule evaluation timeouts.

    private void setMainExpr(ExprInfo expr) {
        mMainExpr = expr;
        mExprs.put(MAIN_INDEX, expr);
    }

    Evaluator(Context context) {
        mContext = context;
        setMainExpr(new ExprInfo(new CalculatorExpr(), false));
        mSavedName = "none";
        mTimeoutHandler = new Handler();

        mExprDB = new ExpressionDB(context);
        mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
        mMainExpr.mDegreeMode = mSharedPrefs.getBoolean(KEY_PREF_DEGREE_MODE, false);
        long savedIndex = mSharedPrefs.getLong(KEY_PREF_SAVED_INDEX, 0L);
        long memoryIndex = mSharedPrefs.getLong(KEY_PREF_MEMORY_INDEX, 0L);
        if (savedIndex != 0 && savedIndex != -1 /* Recover from old corruption */) {
            setSavedIndexWhenEvaluated(savedIndex);
        }
        if (memoryIndex != 0 && memoryIndex != -1) {
            setMemoryIndexWhenEvaluated(memoryIndex, false /* no need to persist again */);
        }
        mSavedName = mSharedPrefs.getString(KEY_PREF_SAVED_NAME, "none");
    }

    /**
     * Retrieve minimum expression index.
     * This is the minimum over all expressions, including uncached ones residing only
     * in the data base. If no expressions with negative indices were preserved, this will
     * return a small negative predefined constant.
     * May be called from any thread, but will block until the database is opened.
     */
    public long getMinIndex() {
        return mExprDB.getMinIndex();
    }

    /**
     * Retrieve maximum expression index.
     * This is the maximum over all expressions, including uncached ones residing only
     * in the data base. If no expressions with positive indices were preserved, this will
     * return 0.
     * May be called from any thread, but will block until the database is opened.
     */
    public long getMaxIndex() {
        return mExprDB.getMaxIndex();
    }

    /**
     * Set the Callback for showing dialogs and notifying the UI about memory state changes.
     * @param callback
     */
    public void setCallback(Callback callback) {
        mCallback = callback;
    }

    /**
     * Does the expression index refer to a transient and mutable expression?
     */
    private boolean isMutableIndex(long index) {
        return index == MAIN_INDEX || index == HISTORY_MAIN_INDEX;
    }

    /**
     * Result of initial asynchronous result computation.
     * Represents either an error or a result computed to an initial evaluation precision.
     */
    private static class InitialResult {
        public final int errorResourceId;    // Error string or INVALID_RES_ID.
        public final UnifiedReal val;        // Constructive real value.
        public final String newResultString;       // Null iff it can't be computed.
        public final int newResultStringOffset;
        public final int initDisplayOffset;
        InitialResult(UnifiedReal v, String s, int p, int idp) {
            errorResourceId = Calculator.INVALID_RES_ID;
            val = v;
            newResultString = s;
            newResultStringOffset = p;
            initDisplayOffset = idp;
        }
        InitialResult(int errorId) {
            errorResourceId = errorId;
            val = UnifiedReal.ZERO;
            newResultString = "BAD";
            newResultStringOffset = 0;
            initDisplayOffset = 0;
        }
        boolean isError() {
            return errorResourceId != Calculator.INVALID_RES_ID;
        }
    }

    private void displayCancelledMessage() {
        if (mCallback != null) {
            mCallback.showMessageDialog(0, R.string.cancelled, 0, null);
        }
    }

    // Timeout handling.
    // Expressions are evaluated with a sort timeout or a long timeout.
    // Each implies different maxima on both computation time and bit length.
    // We recheck bit length separetly to avoid wasting time on decimal conversions that are
    // destined to fail.

    /**
     * Return the timeout in milliseconds.
     * @param longTimeout a long timeout is in effect
     */
    private long getTimeout(boolean longTimeout) {
        return longTimeout ? 15000 : 2000;
        // Exceeding a few tens of seconds increases the risk of running out of memory
        // and impacting the rest of the system.
    }

    /**
     * Return the maximum number of bits in the result.  Longer results are assumed to time out.
     * @param longTimeout a long timeout is in effect
     */
    private int getMaxResultBits(boolean longTimeout) {
        return longTimeout ? 700000 : 240000;
    }

    /**
     * Timeout for unrequested, speculative evaluations, in milliseconds.
     */
    private static final long QUICK_TIMEOUT = 1000;

    /**
     * Timeout for non-MAIN expressions. Note that there may be many such evaluations in
     * progress on the same thread or core. Thus the evaluation latency may include that needed
     * to complete previously enqueued evaluations. Thus the longTimeout flag is not very
     * meaningful, and currently ignored.
     * Since this is only used for expressions that we have previously successfully evaluated,
     * these timeouts hsould never trigger.
     */
    private static final long NON_MAIN_TIMEOUT = 100000;

    /**
     * Maximum result bit length for unrequested, speculative evaluations.
     * Also used to bound evaluation precision for small non-zero fractions.
     */
    private static final int QUICK_MAX_RESULT_BITS = 150000;

    private void displayTimeoutMessage(boolean longTimeout) {
        if (mCallback != null) {
            mCallback.showMessageDialog(R.string.dialog_timeout, R.string.timeout,
                    longTimeout ? 0 : R.string.ok_remove_timeout, TIMEOUT_DIALOG_TAG);
        }
    }

    public void setLongTimeout() {
        mMainExpr.mLongTimeout = true;
    }

    /**
     * Compute initial cache contents and result when we're good and ready.
     * We leave the expression display up, with scrolling disabled, until this computation
     * completes.  Can result in an error display if something goes wrong.  By default we set a
     * timeout to catch runaway computations.
     */
    class AsyncEvaluator extends AsyncTask<Void, Void, InitialResult> {
        private boolean mDm;  // degrees
        public boolean mRequired; // Result was requested by user.
        private boolean mQuiet;  // Suppress cancellation message.
        private Runnable mTimeoutRunnable = null;
        private EvaluationListener mListener;  // Completion callback.
        private CharMetricsInfo mCharMetricsInfo;  // Where to get result size information.
        private long mIndex;  //  Expression index.
        private ExprInfo mExprInfo;  // Current expression.

        AsyncEvaluator(long index, EvaluationListener listener, CharMetricsInfo cmi, boolean dm,
                boolean required) {
            mIndex = index;
            mListener = listener;
            mCharMetricsInfo = cmi;
            mDm = dm;
            mRequired = required;
            mQuiet = !required || mIndex != MAIN_INDEX;
            mExprInfo = mExprs.get(mIndex);
            if (mExprInfo.mEvaluator != null) {
                throw new AssertionError("Evaluation already in progress!");
            }
        }

        private void handleTimeout() {
            // Runs in UI thread.
            boolean running = (getStatus() != AsyncTask.Status.FINISHED);
            if (running && cancel(true)) {
                mExprs.get(mIndex).mEvaluator = null;
                if (mRequired && mIndex == MAIN_INDEX) {
                    // Replace mExpr with clone to avoid races if task still runs for a while.
                    mMainExpr.mExpr = (CalculatorExpr)mMainExpr.mExpr.clone();
                    suppressCancelMessage();
                    displayTimeoutMessage(mExprInfo.mLongTimeout);
                }
            }
        }

        private void suppressCancelMessage() {
            mQuiet = true;
        }

        @Override
        protected void onPreExecute() {
            long timeout = mRequired ? getTimeout(mExprInfo.mLongTimeout) : QUICK_TIMEOUT;
            if (mIndex != MAIN_INDEX) {
                // We evaluated the expression before with the current timeout, so this shouldn't
                // ever time out. We evaluate it with a ridiculously long timeout to avoid running
                // down the battery if something does go wrong. But we only log such timeouts, and
                // invoke the listener with onCancelled.
                timeout = NON_MAIN_TIMEOUT;
            }
            mTimeoutRunnable = new Runnable() {
                @Override
                public void run() {
                    handleTimeout();
                }
            };
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            mTimeoutHandler.postDelayed(mTimeoutRunnable, timeout);
        }

        /**
         * Is a computed result too big for decimal conversion?
         */
        private boolean isTooBig(UnifiedReal res) {
            final int maxBits = mRequired ? getMaxResultBits(mExprInfo.mLongTimeout)
                    : QUICK_MAX_RESULT_BITS;
            return res.approxWholeNumberBitsGreaterThan(maxBits);
        }

        @Override
        protected InitialResult doInBackground(Void... nothing) {
            try {
                // mExpr does not change while we are evaluating; thus it's OK to read here.
                UnifiedReal res = mExprInfo.mVal.get();
                if (res == null) {
                    try {
                        res = mExprInfo.mExpr.eval(mDm, Evaluator.this);
                        if (isCancelled()) {
                            // TODO: This remains very slightly racey. Fix this.
                            throw new CR.AbortedException();
                        }
                        res = putResultIfAbsent(mIndex, res);
                    } catch (StackOverflowError e) {
                        // Absurdly large integer exponents can cause this. There might be other
                        // examples as well. Treat it as a timeout.
                        return new InitialResult(R.string.timeout);
                    }
                }
                if (isTooBig(res)) {
                    // Avoid starting a long uninterruptible decimal conversion.
                    return new InitialResult(R.string.timeout);
                }
                int precOffset = INIT_PREC;
                String initResult = res.toStringTruncated(precOffset);
                int msd = getMsdIndexOf(initResult);
                if (msd == INVALID_MSD) {
                    int leadingZeroBits = res.leadingBinaryZeroes();
                    if (leadingZeroBits < QUICK_MAX_RESULT_BITS) {
                        // Enough initial nonzero digits for most displays.
                        precOffset = 30 +
                                (int)Math.ceil(Math.log(2.0d) / Math.log(10.0d) * leadingZeroBits);
                        initResult = res.toStringTruncated(precOffset);
                        msd = getMsdIndexOf(initResult);
                        if (msd == INVALID_MSD) {
                            throw new AssertionError("Impossible zero result");
                        }
                    } else {
                        // Just try once more at higher fixed precision.
                        precOffset = MAX_MSD_PREC_OFFSET;
                        initResult = res.toStringTruncated(precOffset);
                        msd = getMsdIndexOf(initResult);
                    }
                }
                final int lsdOffset = getLsdOffset(res, initResult, initResult.indexOf('.'));
                final int initDisplayOffset = getPreferredPrec(initResult, msd, lsdOffset,
                        mCharMetricsInfo);
                final int newPrecOffset = initDisplayOffset + EXTRA_DIGITS;
                if (newPrecOffset > precOffset) {
                    precOffset = newPrecOffset;
                    initResult = res.toStringTruncated(precOffset);
                }
                return new InitialResult(res, initResult, precOffset, initDisplayOffset);
            } catch (CalculatorExpr.SyntaxException e) {
                return new InitialResult(R.string.error_syntax);
            } catch (UnifiedReal.ZeroDivisionException e) {
                return new InitialResult(R.string.error_zero_divide);
            } catch(ArithmeticException e) {
                return new InitialResult(R.string.error_nan);
            } catch(CR.PrecisionOverflowException e) {
                // Extremely unlikely unless we're actually dividing by zero or the like.
                return new InitialResult(R.string.error_overflow);
            } catch(CR.AbortedException e) {
                return new InitialResult(R.string.error_aborted);
            }
        }

        @Override
        protected void onPostExecute(InitialResult result) {
            mExprInfo.mEvaluator = null;
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            if (result.isError()) {
                if (result.errorResourceId == R.string.timeout) {
                    // Emulating timeout due to large result.
                    if (mRequired && mIndex == MAIN_INDEX) {
                        displayTimeoutMessage(mExprs.get(mIndex).mLongTimeout);
                    }
                    mListener.onCancelled(mIndex);
                } else {
                    if (mRequired) {
                        mExprInfo.mResultString = ERRONEOUS_RESULT;
                    }
                    mListener.onError(mIndex, result.errorResourceId);
                }
                return;
            }
            // mExprInfo.mVal was already set asynchronously by child thread.
            mExprInfo.mResultString = result.newResultString;
            mExprInfo.mResultStringOffset = result.newResultStringOffset;
            final int dotIndex = mExprInfo.mResultString.indexOf('.');
            String truncatedWholePart = mExprInfo.mResultString.substring(0, dotIndex);
            // Recheck display precision; it may change, since display dimensions may have been
            // unknow the first time.  In that case the initial evaluation precision should have
            // been conservative.
            // TODO: Could optimize by remembering display size and checking for change.
            int initPrecOffset = result.initDisplayOffset;
            mExprInfo.mMsdIndex = getMsdIndexOf(mExprInfo.mResultString);
            final int leastDigOffset = getLsdOffset(result.val, mExprInfo.mResultString,
                    dotIndex);
            final int newInitPrecOffset = getPreferredPrec(mExprInfo.mResultString,
                    mExprInfo.mMsdIndex, leastDigOffset, mCharMetricsInfo);
            if (newInitPrecOffset < initPrecOffset) {
                initPrecOffset = newInitPrecOffset;
            } else {
                // They should be equal.  But nothing horrible should happen if they're not. e.g.
                // because CalculatorResult.MAX_WIDTH was too small.
            }
            mListener.onEvaluate(mIndex, initPrecOffset, mExprInfo.mMsdIndex, leastDigOffset,
                    truncatedWholePart);
        }

        @Override
        protected void onCancelled(InitialResult result) {
            // Invoker resets mEvaluator.
            mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
            if (!mQuiet) {
                displayCancelledMessage();
            } // Otherwise, if mRequired, timeout processing displayed message.
            mListener.onCancelled(mIndex);
            // Just drop the evaluation; Leave expression displayed.
            return;
        }
    }

    /**
     * Check whether a new higher precision result flips previously computed trailing 9s
     * to zeroes.  If so, flip them back.  Return the adjusted result.
     * Assumes newPrecOffset >= oldPrecOffset > 0.
     * Since our results are accurate to < 1 ulp, this can only happen if the true result
     * is less than the new result with trailing zeroes, and thus appending 9s to the
     * old result must also be correct.  Such flips are impossible if the newly computed
     * digits consist of anything other than zeroes.
     * It is unclear that there are real cases in which this is necessary,
     * but we have failed to prove there aren't such cases.
     */
    @VisibleForTesting
    public static String unflipZeroes(String oldDigs, int oldPrecOffset, String newDigs,
            int newPrecOffset) {
        final int oldLen = oldDigs.length();
        if (oldDigs.charAt(oldLen - 1) != '9') {
            return newDigs;
        }
        final int newLen = newDigs.length();
        final int precDiff = newPrecOffset - oldPrecOffset;
        final int oldLastInNew = newLen - 1 - precDiff;
        if (newDigs.charAt(oldLastInNew) != '0') {
            return newDigs;
        }
        // Earlier digits could not have changed without a 0 to 9 or 9 to 0 flip at end.
        // The former is OK.
        if (!newDigs.substring(newLen - precDiff).equals(StringUtils.repeat('0', precDiff))) {
            throw new AssertionError("New approximation invalidates old one!");
        }
        return oldDigs + StringUtils.repeat('9', precDiff);
    }

    /**
     * Result of asynchronous reevaluation.
     */
    private static class ReevalResult {
        public final String newResultString;
        public final int newResultStringOffset;
        ReevalResult(String s, int p) {
            newResultString = s;
            newResultStringOffset = p;
        }
    }

    /**
     * Compute new mResultString contents to prec digits to the right of the decimal point.
     * Ensure that onReevaluate() is called after doing so.  If the evaluation fails for reasons
     * other than a timeout, ensure that onError() is called.
     * This assumes that initial evaluation of the expression has been successfully
     * completed.
     */
    private class AsyncReevaluator extends AsyncTask<Integer, Void, ReevalResult> {
        private long mIndex;  // Index of expression to evaluate.
        private EvaluationListener mListener;
        private ExprInfo mExprInfo;

        AsyncReevaluator(long index, EvaluationListener listener) {
            mIndex = index;
            mListener = listener;
            mExprInfo = mExprs.get(mIndex);
        }

        @Override
        protected ReevalResult doInBackground(Integer... prec) {
            try {
                final int precOffset = prec[0].intValue();
                return new ReevalResult(mExprInfo.mVal.get().toStringTruncated(precOffset),
                        precOffset);
            } catch(ArithmeticException e) {
                return null;
            } catch(CR.PrecisionOverflowException e) {
                return null;
            } catch(CR.AbortedException e) {
                // Should only happen if the task was cancelled, in which case we don't look at
                // the result.
                return null;
            }
        }

        @Override
        protected void onPostExecute(ReevalResult result) {
            if (result == null) {
                // This should only be possible in the extremely rare case of encountering a
                // domain error while reevaluating or in case of a precision overflow.  We don't
                // know of a way to get the latter with a plausible amount of user input.
                mExprInfo.mResultString = ERRONEOUS_RESULT;
                mListener.onError(mIndex, R.string.error_nan);
            } else {
                if (result.newResultStringOffset < mExprInfo.mResultStringOffset) {
                    throw new AssertionError("Unexpected onPostExecute timing");
                }
                mExprInfo.mResultString = unflipZeroes(mExprInfo.mResultString,
                        mExprInfo.mResultStringOffset, result.newResultString,
                        result.newResultStringOffset);
                mExprInfo.mResultStringOffset = result.newResultStringOffset;
                mListener.onReevaluate(mIndex);
            }
            mExprInfo.mEvaluator = null;
        }
        // On cancellation we do nothing; invoker should have left no trace of us.
    }

    /**
     * If necessary, start an evaluation of the expression at the given index to precOffset.
     * If we start an evaluation the listener is notified on completion.
     * Only called if prior evaluation succeeded.
     */
    private void ensureCachePrec(long index, int precOffset, EvaluationListener listener) {
        ExprInfo ei = mExprs.get(index);
        if (ei.mResultString != null && ei.mResultStringOffset >= precOffset
                || ei.mResultStringOffsetReq >= precOffset) return;
        if (ei.mEvaluator != null) {
            // Ensure we only have one evaluation running at a time.
            ei.mEvaluator.cancel(true);
            ei.mEvaluator = null;
        }
        AsyncReevaluator reEval = new AsyncReevaluator(index, listener);
        ei.mEvaluator = reEval;
        ei.mResultStringOffsetReq = precOffset + PRECOMPUTE_DIGITS;
        if (ei.mResultString != null) {
            ei.mResultStringOffsetReq += ei.mResultStringOffsetReq / PRECOMPUTE_DIVISOR;
        }
        reEval.execute(ei.mResultStringOffsetReq);
    }

    /**
     * Return the rightmost nonzero digit position, if any.
     * @param val UnifiedReal value of result.
     * @param cache Current cached decimal string representation of result.
     * @param decIndex Index of decimal point in cache.
     * @result Position of rightmost nonzero digit relative to decimal point.
     *         Integer.MIN_VALUE if we cannot determine.  Integer.MAX_VALUE if there is no lsd,
     *         or we cannot determine it.
     */
    static int getLsdOffset(UnifiedReal val, String cache, int decIndex) {
        if (val.definitelyZero()) return Integer.MIN_VALUE;
        int result = val.digitsRequired();
        if (result == 0) {
            int i;
            for (i = -1; decIndex + i > 0 && cache.charAt(decIndex + i) == '0'; --i) { }
            result = i;
        }
        return result;
    }

    // TODO: We may want to consistently specify the position of the current result
    // window using the left-most visible digit index instead of the offset for the rightmost one.
    // It seems likely that would simplify the logic.

    /**
     * Retrieve the preferred precision "offset" for the currently displayed result.
     * May be called from non-UI thread.
     * @param cache Current approximation as string.
     * @param msd Position of most significant digit in result.  Index in cache.
     *            Can be INVALID_MSD if we haven't found it yet.
     * @param lastDigitOffset Position of least significant digit (1 = tenths digit)
     *                  or Integer.MAX_VALUE.
     */
    private static int getPreferredPrec(String cache, int msd, int lastDigitOffset,
            CharMetricsInfo cm) {
        final int lineLength = cm.getMaxChars();
        final int wholeSize = cache.indexOf('.');
        final float rawSepChars = cm.separatorChars(cache, wholeSize);
        final float rawSepCharsNoDecimal = rawSepChars - cm.getNoEllipsisCredit();
        final float rawSepCharsWithDecimal = rawSepCharsNoDecimal - cm.getDecimalCredit();
        final int sepCharsNoDecimal = (int) Math.ceil(Math.max(rawSepCharsNoDecimal, 0.0f));
        final int sepCharsWithDecimal = (int) Math.ceil(Math.max(rawSepCharsWithDecimal, 0.0f));
        final int negative = cache.charAt(0) == '-' ? 1 : 0;
        // Don't display decimal point if result is an integer.
        if (lastDigitOffset == 0) {
            lastDigitOffset = -1;
        }
        if (lastDigitOffset != Integer.MAX_VALUE) {
            if (wholeSize <= lineLength - sepCharsNoDecimal && lastDigitOffset <= 0) {
                // Exact integer.  Prefer to display as integer, without decimal point.
                return -1;
            }
            if (lastDigitOffset >= 0
                    && wholeSize + lastDigitOffset + 1 /* decimal pt. */
                    <= lineLength - sepCharsWithDecimal) {
                // Display full exact number without scientific notation.
                return lastDigitOffset;
            }
        }
        if (msd > wholeSize && msd <= wholeSize + EXP_COST + 1) {
            // Display number without scientific notation.  Treat leading zero as msd.
            msd = wholeSize - 1;
        }
        if (msd > QUICK_MAX_RESULT_BITS) {
            // Display a probable but uncertain 0 as "0.000000000", without exponent.  That's a
            // judgment call, but less likely to confuse naive users.  A more informative and
            // confusing option would be to use a large negative exponent.
            // Treat extremely large msd values as unknown to avoid slow computations.
            return lineLength - 2;
        }
        // Return position corresponding to having msd at left, effectively presuming scientific
        // notation that preserves the left part of the result.
        // After adjustment for the space required by an exponent, evaluating to the resulting
        // precision should not overflow the display.
        int result = msd - wholeSize + lineLength - negative - 1;
        if (wholeSize <= lineLength - sepCharsNoDecimal) {
            // Fits without scientific notation; will need space for separators.
            if (wholeSize < lineLength - sepCharsWithDecimal) {
                result -= sepCharsWithDecimal;
            } else {
                result -= sepCharsNoDecimal;
            }
        }
        return result;
    }

    private static final int SHORT_TARGET_LENGTH  = 8;
    private static final String SHORT_UNCERTAIN_ZERO = "0.00000" + KeyMaps.ELLIPSIS;

    /**
     * Get a short representation of the value represented by the string cache.
     * We try to match the CalculatorResult code when the result is finite
     * and small enough to suit our needs.
     * The result is not internationalized.
     * @param cache String approximation of value.  Assumed to be long enough
     *              that if it doesn't contain enough significant digits, we can
     *              reasonably abbreviate as SHORT_UNCERTAIN_ZERO.
     * @param msdIndex Index of most significant digit in cache, or INVALID_MSD.
     * @param lsdOffset Position of least significant digit in finite representation,
     *            relative to decimal point, or MAX_VALUE.
     */
    private static String getShortString(String cache, int msdIndex, int lsdOffset) {
        // This somewhat mirrors the display formatting code, but
        // - The constants are different, since we don't want to use the whole display.
        // - This is an easier problem, since we don't support scrolling and the length
        //   is a bit flexible.
        // TODO: Think about refactoring this to remove partial redundancy with CalculatorResult.
        final int dotIndex = cache.indexOf('.');
        final int negative = cache.charAt(0) == '-' ? 1 : 0;
        final String negativeSign = negative == 1 ? "-" : "";

        // Ensure we don't have to worry about running off the end of cache.
        if (msdIndex >= cache.length() - SHORT_TARGET_LENGTH) {
            msdIndex = INVALID_MSD;
        }
        if (msdIndex == INVALID_MSD) {
            if (lsdOffset < INIT_PREC) {
                return "0";
            } else {
                return SHORT_UNCERTAIN_ZERO;
            }
        }
        // Avoid scientific notation for small numbers of zeros.
        // Instead stretch significant digits to include decimal point.
        if (lsdOffset < -1 && dotIndex - msdIndex + negative <= SHORT_TARGET_LENGTH
            && lsdOffset >= -CalculatorResult.MAX_TRAILING_ZEROES - 1) {
            // Whole number that fits in allotted space.
            // CalculatorResult would not use scientific notation either.
            lsdOffset = -1;
        }
        if (msdIndex > dotIndex) {
            if (msdIndex <= dotIndex + EXP_COST + 1) {
                // Preferred display format in this case is with leading zeroes, even if
                // it doesn't fit entirely.  Replicate that here.
                msdIndex = dotIndex - 1;
            } else if (lsdOffset <= SHORT_TARGET_LENGTH - negative - 2
                    && lsdOffset <= CalculatorResult.MAX_LEADING_ZEROES + 1) {
                // Fraction that fits entirely in allotted space.
                // CalculatorResult would not use scientific notation either.
                msdIndex = dotIndex -1;
            }
        }
        int exponent = dotIndex - msdIndex;
        if (exponent > 0) {
            // Adjust for the fact that the decimal point itself takes space.
            exponent--;
        }
        if (lsdOffset != Integer.MAX_VALUE) {
            final int lsdIndex = dotIndex + lsdOffset;
            final int totalDigits = lsdIndex - msdIndex + negative + 1;
            if (totalDigits <= SHORT_TARGET_LENGTH && dotIndex > msdIndex && lsdOffset >= -1) {
                // Fits, no exponent needed.
                final String wholeWithCommas = StringUtils.addCommas(cache, msdIndex, dotIndex);
                return negativeSign + wholeWithCommas + cache.substring(dotIndex, lsdIndex + 1);
            }
            if (totalDigits <= SHORT_TARGET_LENGTH - 3) {
                return negativeSign + cache.charAt(msdIndex) + "."
                        + cache.substring(msdIndex + 1, lsdIndex + 1) + "E" + exponent;
            }
        }
        // We need to abbreviate.
        if (dotIndex > msdIndex && dotIndex < msdIndex + SHORT_TARGET_LENGTH - negative - 1) {
            final String wholeWithCommas = StringUtils.addCommas(cache, msdIndex, dotIndex);
            return negativeSign + wholeWithCommas
                    + cache.substring(dotIndex, msdIndex + SHORT_TARGET_LENGTH - negative - 1)
                    + KeyMaps.ELLIPSIS;
        }
        // Need abbreviation + exponent
        return negativeSign + cache.charAt(msdIndex) + "."
                + cache.substring(msdIndex + 1, msdIndex + SHORT_TARGET_LENGTH - negative - 4)
                + KeyMaps.ELLIPSIS + "E" + exponent;
    }

    /**
     * Return the most significant digit index in the given numeric string.
     * Return INVALID_MSD if there are not enough digits to prove the numeric value is
     * different from zero.  As usual, we assume an error of strictly less than 1 ulp.
     */
    public static int getMsdIndexOf(String s) {
        final int len = s.length();
        int nonzeroIndex = -1;
        for (int i = 0; i < len; ++i) {
            char c = s.charAt(i);
            if (c != '-' && c != '.' && c != '0') {
                nonzeroIndex = i;
                break;
            }
        }
        if (nonzeroIndex >= 0 && (nonzeroIndex < len - 1 || s.charAt(nonzeroIndex) != '1')) {
            return nonzeroIndex;
        } else {
            return INVALID_MSD;
        }
    }

    /**
     * Return most significant digit index for the result of the expressin at the given index.
     * Returns an index in the result character array.  Return INVALID_MSD if the current result
     * is too close to zero to determine the result.
     * Result is almost consistent through reevaluations: It may increase by one, once.
     */
    private int getMsdIndex(long index) {
        ExprInfo ei = mExprs.get(index);
        if (ei.mMsdIndex != INVALID_MSD) {
            // 0.100000... can change to 0.0999999...  We may have to correct once by one digit.
            if (ei.mResultString.charAt(ei.mMsdIndex) == '0') {
                ei.mMsdIndex++;
            }
            return ei.mMsdIndex;
        }
        if (ei.mVal.get().definitelyZero()) {
            return INVALID_MSD;  // None exists
        }
        int result = INVALID_MSD;
        if (ei.mResultString != null) {
            result = ei.mMsdIndex = getMsdIndexOf(ei.mResultString);
        }
        return result;
    }

    // Refuse to scroll past the point at which this many digits from the whole number
    // part of the result are still displayed.  Avoids sily displays like 1E1.
    private static final int MIN_DISPLAYED_DIGS = 5;

    /**
     * Return result to precOffset[0] digits to the right of the decimal point.
     * PrecOffset[0] is updated if the original value is out of range.  No exponent or other
     * indication of precision is added.  The result is returned immediately, based on the current
     * cache contents, but it may contain blanks for unknown digits.  It may also use
     * uncertain digits within EXTRA_DIGITS.  If either of those occurred, schedule a reevaluation
     * and redisplay operation.  Uncertain digits never appear to the left of the decimal point.
     * PrecOffset[0] may be negative to only retrieve digits to the left of the decimal point.
     * (precOffset[0] = 0 means we include the decimal point, but nothing to the right.
     * precOffset[0] = -1 means we drop the decimal point and start at the ones position.  Should
     * not be invoked before the onEvaluate() callback is received.  This essentially just returns
     * a substring of the full result; a leading minus sign or leading digits can be dropped.
     * Result uses US conventions; is NOT internationalized.  Use getResult() and UnifiedReal
     * operations to determine whether the result is exact, or whether we dropped trailing digits.
     *
     * @param index Index of expression to approximate
     * @param precOffset Zeroth element indicates desired and actual precision
     * @param maxPrecOffset Maximum adjusted precOffset[0]
     * @param maxDigs Maximum length of result
     * @param truncated Zeroth element is set if leading nonzero digits were dropped
     * @param negative Zeroth element is set of the result is negative.
     * @param listener EvaluationListener to notify when reevaluation is complete.
     */
    public String getString(long index, int[] precOffset, int maxPrecOffset, int maxDigs,
            boolean[] truncated, boolean[] negative, EvaluationListener listener) {
        ExprInfo ei = mExprs.get(index);
        int currentPrecOffset = precOffset[0];
        // Make sure we eventually get a complete answer
        if (ei.mResultString == null) {
            ensureCachePrec(index, currentPrecOffset + EXTRA_DIGITS, listener);
            // Nothing else to do now; seems to happen on rare occasion with weird user input
            // timing; Will repair itself in a jiffy.
            return " ";
        } else {
            ensureCachePrec(index, currentPrecOffset + EXTRA_DIGITS + ei.mResultString.length()
                    / EXTRA_DIVISOR, listener);
        }
        // Compute an appropriate substring of mResultString.  Pad if necessary.
        final int len = ei.mResultString.length();
        final boolean myNegative = ei.mResultString.charAt(0) == '-';
        negative[0] = myNegative;
        // Don't scroll left past leftmost digits in mResultString unless that still leaves an
        // integer.
            int integralDigits = len - ei.mResultStringOffset;
                            // includes 1 for dec. pt
            if (myNegative) {
                --integralDigits;
            }
            int minPrecOffset = Math.min(MIN_DISPLAYED_DIGS - integralDigits, -1);
            currentPrecOffset = Math.min(Math.max(currentPrecOffset, minPrecOffset),
                    maxPrecOffset);
            precOffset[0] = currentPrecOffset;
        int extraDigs = ei.mResultStringOffset - currentPrecOffset; // trailing digits to drop
        int deficit = 0;  // The number of digits we're short
        if (extraDigs < 0) {
            extraDigs = 0;
            deficit = Math.min(currentPrecOffset - ei.mResultStringOffset, maxDigs);
        }
        int endIndex = len - extraDigs;
        if (endIndex < 1) {
            return " ";
        }
        int startIndex = Math.max(endIndex + deficit - maxDigs, 0);
        truncated[0] = (startIndex > getMsdIndex(index));
        String result = ei.mResultString.substring(startIndex, endIndex);
        if (deficit > 0) {
            result += StringUtils.repeat(' ', deficit);
            // Blank character is replaced during translation.
            // Since we always compute past the decimal point, this never fills in the spot
            // where the decimal point should go, and we can otherwise treat placeholders
            // as though they were digits.
        }
        return result;
    }

    /**
     * Clear the cache for the main expression.
     */
    private void clearMainCache() {
        mMainExpr.mVal.set(null);
        mMainExpr.mResultString = null;
        mMainExpr.mResultStringOffset = mMainExpr.mResultStringOffsetReq = 0;
        mMainExpr.mMsdIndex = INVALID_MSD;
    }


    public void clearMain() {
        mMainExpr.mExpr.clear();
        mHasTrigFuncs = false;
        clearMainCache();
        mMainExpr.mLongTimeout = false;
    }

    public void clearEverything() {
        boolean dm = mMainExpr.mDegreeMode;
        cancelAll(true);
        setSavedIndex(0);
        setMemoryIndex(0);
        mExprDB.eraseAll();
        mExprs.clear();
        setMainExpr(new ExprInfo(new CalculatorExpr(), dm));
    }

    /**
     * Start asynchronous evaluation.
     * Invoke listener on successful completion. If the result is required, invoke
     * onCancelled() if cancelled.
     * @param index index of expression to be evaluated.
     * @param required result was explicitly requested by user.
     */
    private void evaluateResult(long index, EvaluationListener listener, CharMetricsInfo cmi,
            boolean required) {
        ExprInfo ei = mExprs.get(index);
        if (index == MAIN_INDEX) {
            clearMainCache();
        }  // Otherwise the expression is immutable.
        AsyncEvaluator eval =  new AsyncEvaluator(index, listener, cmi, ei.mDegreeMode, required);
        ei.mEvaluator = eval;
        eval.execute();
        if (index == MAIN_INDEX) {
            mChangedValue = false;
        }
    }

    /**
     * Notify listener of a previously completed evaluation.
     */
    void notifyImmediately(long index, ExprInfo ei, EvaluationListener listener,
            CharMetricsInfo cmi) {
        final int dotIndex = ei.mResultString.indexOf('.');
        final String truncatedWholePart = ei.mResultString.substring(0, dotIndex);
        final int leastDigOffset = getLsdOffset(ei.mVal.get(), ei.mResultString, dotIndex);
        final int msdIndex = getMsdIndex(index);
        final int preferredPrecOffset = getPreferredPrec(ei.mResultString, msdIndex,
                leastDigOffset, cmi);
        listener.onEvaluate(index, preferredPrecOffset, msdIndex, leastDigOffset,
                truncatedWholePart);
    }

    /**
     * Start optional evaluation of expression and display when ready.
     * @param index of expression to be evaluated.
     * Can quietly time out without a listener callback.
     * No-op if cmi.getMaxChars() == 0.
     */
    public void evaluateAndNotify(long index, EvaluationListener listener, CharMetricsInfo cmi) {
        if (cmi.getMaxChars() == 0) {
            // Probably shouldn't happen. If it does, we didn't promise to do anything anyway.
            return;
        }
        ExprInfo ei = ensureExprIsCached(index);
        if (ei.mResultString != null && ei.mResultString != ERRONEOUS_RESULT
                && !(index == MAIN_INDEX && mChangedValue)) {
            // Already done. Just notify.
            notifyImmediately(MAIN_INDEX, mMainExpr, listener, cmi);
            return;
        } else if (ei.mEvaluator != null) {
            // We only allow a single listener per expression, so this request must be redundant.
            return;
        }
        evaluateResult(index, listener, cmi, false);
    }

    /**
     * Start required evaluation of expression at given index and call back listener when ready.
     * If index is MAIN_INDEX, we may also directly display a timeout message.
     * Uses longer timeouts than optional evaluation.
     * Requires cmi.getMaxChars() != 0.
     */
    public void requireResult(long index, EvaluationListener listener, CharMetricsInfo cmi) {
        if (cmi.getMaxChars() == 0) {
            throw new AssertionError("requireResult called too early");
        }
        ExprInfo ei = ensureExprIsCached(index);
        if (ei.mResultString == null || (index == MAIN_INDEX && mChangedValue)) {
            if (index == HISTORY_MAIN_INDEX) {
                // We don't want to compute a result for HISTORY_MAIN_INDEX that was
                // not already computed for the main expression. Pretend we timed out.
                // The error case doesn't get here.
                listener.onCancelled(index);
            } else if ((ei.mEvaluator instanceof AsyncEvaluator)
                    && ((AsyncEvaluator)(ei.mEvaluator)).mRequired) {
                // Duplicate request; ignore.
            } else {
                // (Re)start evaluator in requested mode, i.e. with longer timeout.
                cancel(ei, true);
                evaluateResult(index, listener, cmi, true);
            }
        } else if (ei.mResultString == ERRONEOUS_RESULT) {
            // Just re-evaluate to generate a new notification.
            cancel(ei, true);
            evaluateResult(index, listener, cmi, true);
        } else {
            notifyImmediately(index, ei, listener, cmi);
        }
    }

    /**
     * Whether this expression has explicitly been evaluated (User pressed "=")
     */
    public boolean hasResult(long index) {
        final ExprInfo ei = ensureExprIsCached(index);
        return ei.mResultString != null;
    }

    /**
     * Is a reevaluation still in progress?
     */
    public boolean evaluationInProgress(long index) {
        ExprInfo ei = mExprs.get(index);
        return ei != null && ei.mEvaluator != null;
    }

    /**
     * Cancel any current background task associated with the given ExprInfo.
     * @param quiet suppress cancellation message
     * @return true if we cancelled an initial evaluation
     */
    private boolean cancel(ExprInfo expr, boolean quiet) {
        if (expr.mEvaluator != null) {
            if (quiet && (expr.mEvaluator instanceof AsyncEvaluator)) {
                ((AsyncEvaluator)(expr.mEvaluator)).suppressCancelMessage();
            }
            // Reevaluation in progress.
            if (expr.mVal.get() != null) {
                expr.mEvaluator.cancel(true);
                expr.mResultStringOffsetReq = expr.mResultStringOffset;
                // Backgound computation touches only constructive reals.
                // OK not to wait.
                expr.mEvaluator = null;
            } else {
                expr.mEvaluator.cancel(true);
                if (expr == mMainExpr) {
                    // The expression is modifiable, and the AsyncTask is reading it.
                    // There seems to be no good way to wait for cancellation.
                    // Give ourselves a new copy to work on instead.
                    mMainExpr.mExpr = (CalculatorExpr)mMainExpr.mExpr.clone();
                    // Approximation of constructive reals should be thread-safe,
                    // so we can let that continue until it notices the cancellation.
                    mChangedValue = true;    // Didn't do the expected evaluation.
                }
                expr.mEvaluator = null;
                return true;
            }
        }
        return false;
    }

    /**
     * Cancel any current background task associated with the given ExprInfo.
     * @param quiet suppress cancellation message
     * @return true if we cancelled an initial evaluation
     */
    public boolean cancel(long index, boolean quiet)
    {
        ExprInfo ei = mExprs.get(index);
        if (ei == null) {
            return false;
        } else {
            return cancel(ei, quiet);
        }
    }

    public void cancelAll(boolean quiet) {
        // TODO: May want to keep active evaluators in a HashSet to avoid traversing
        // all expressions we've looked at.
        for (ExprInfo expr: mExprs.values()) {
            cancel(expr, quiet);
        }
    }

    /**
     * Quietly cancel all evaluations associated with expressions other than the main one.
     * These are currently the evaluations associated with the history fragment.
     */
    public void cancelNonMain() {
        // TODO: May want to keep active evaluators in a HashSet to avoid traversing
        // all expressions we've looked at.
        for (ExprInfo expr: mExprs.values()) {
            if (expr != mMainExpr) {
                cancel(expr, true);
            }
        }
    }

    /**
     * Restore the evaluator state, including the current expression.
     */
    public void restoreInstanceState(DataInput in) {
        mChangedValue = true;
        try {
            mMainExpr.mDegreeMode = in.readBoolean();
            mMainExpr.mLongTimeout = in.readBoolean();
            mMainExpr.mExpr = new CalculatorExpr(in);
            mHasTrigFuncs = hasTrigFuncs();
        } catch (IOException e) {
            Log.v("Calculator", "Exception while restoring:\n" + e);
        }
    }

    /**
     * Save the evaluator state, including the expression and any saved value.
     */
    public void saveInstanceState(DataOutput out) {
        try {
            out.writeBoolean(mMainExpr.mDegreeMode);
            out.writeBoolean(mMainExpr.mLongTimeout);
            mMainExpr.mExpr.write(out);
        } catch (IOException e) {
            Log.v("Calculator", "Exception while saving state:\n" + e);
        }
    }


    /**
     * Append a button press to the main expression.
     * @param id Button identifier for the character or operator to be added.
     * @return false if we rejected the insertion due to obvious syntax issues, and the expression
     * is unchanged; true otherwise
     */
    public boolean append(int id) {
        if (id == R.id.fun_10pow) {
            add10pow();  // Handled as macro expansion.
            return true;
        } else {
            mChangedValue = mChangedValue || !KeyMaps.isBinary(id);
            if (mMainExpr.mExpr.add(id)) {
                if (!mHasTrigFuncs) {
                    mHasTrigFuncs = KeyMaps.isTrigFunc(id);
                }
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * Delete last taken from main expression.
     */
    public void delete() {
        mChangedValue = true;
        mMainExpr.mExpr.delete();
        if (mMainExpr.mExpr.isEmpty()) {
            mMainExpr.mLongTimeout = false;
        }
        mHasTrigFuncs = hasTrigFuncs();
    }

    /**
     * Set degree mode for main expression.
     */
    public void setDegreeMode(boolean degreeMode) {
        mChangedValue = true;
        mMainExpr.mDegreeMode = degreeMode;

        mSharedPrefs.edit()
                .putBoolean(KEY_PREF_DEGREE_MODE, degreeMode)
                .apply();
    }

    /**
     * Return an ExprInfo for a copy of the expression with the given index.
     * We remove trailing binary operators in the copy.
     * mTimeStamp is not copied.
     */
    private ExprInfo copy(long index, boolean copyValue) {
        ExprInfo fromEi = mExprs.get(index);
        ExprInfo ei = new ExprInfo((CalculatorExpr)fromEi.mExpr.clone(), fromEi.mDegreeMode);
        while (ei.mExpr.hasTrailingBinary()) {
            ei.mExpr.delete();
        }
        if (copyValue) {
            ei.mVal = new AtomicReference<UnifiedReal>(fromEi.mVal.get());
            ei.mResultString = fromEi.mResultString;
            ei.mResultStringOffset = ei.mResultStringOffsetReq = fromEi.mResultStringOffset;
            ei.mMsdIndex = fromEi.mMsdIndex;
        }
        ei.mLongTimeout = fromEi.mLongTimeout;
        return ei;
    }

    /**
     * Return an ExprInfo corresponding to the sum of the expressions at the
     * two indices.
     * index1 should correspond to an immutable expression, and should thus NOT
     * be MAIN_INDEX. Index2 may be MAIN_INDEX. Both expressions are presumed
     * to have been evaluated.  The result is unevaluated.
     * Can return null if evaluation resulted in an error (a very unlikely case).
     */
    private ExprInfo sum(long index1, long index2) {
        return generalized_sum(index1, index2, R.id.op_add);
    }

    /**
     * Return an ExprInfo corresponding to the subtraction of the value at the subtrahend index
     * from value at the minuend index (minuend - subtrahend = result). Both are presumed to have
     * been previously evaluated. The result is unevaluated. Can return null.
     */
    private ExprInfo difference(long minuendIndex, long subtrahendIndex) {
        return generalized_sum(minuendIndex, subtrahendIndex, R.id.op_sub);
    }

    private ExprInfo generalized_sum(long index1, long index2, int op) {
        // TODO: Consider not collapsing expr2, to save database space.
        // Note that this is a bit tricky, since our expressions can contain unbalanced lparens.
        CalculatorExpr result = new CalculatorExpr();
        CalculatorExpr collapsed1 = getCollapsedExpr(index1);
        CalculatorExpr collapsed2 = getCollapsedExpr(index2);
        if (collapsed1 == null || collapsed2 == null) {
            return null;
        }
        result.append(collapsed1);
        result.add(op);
        result.append(collapsed2);
        ExprInfo resultEi = new ExprInfo(result, false /* dont care about degrees/radians */);
        resultEi.mLongTimeout = mExprs.get(index1).mLongTimeout
                || mExprs.get(index2).mLongTimeout;
        return resultEi;
    }

    /**
     * Add the expression described by the argument to the database.
     * Returns the new row id in the database.
     * Fills in timestamp in ei, if it was not previously set.
     * If in_history is true, add it with a positive index, so it will appear in the history.
     */
    private long addToDB(boolean in_history, ExprInfo ei) {
        byte[] serializedExpr = ei.mExpr.toBytes();
        ExpressionDB.RowData rd = new ExpressionDB.RowData(serializedExpr, ei.mDegreeMode,
                ei.mLongTimeout, 0);
        long resultIndex = mExprDB.addRow(!in_history, rd);
        if (mExprs.get(resultIndex) != null) {
            throw new AssertionError("result slot already occupied! + Slot = " + resultIndex);
        }
        // Add newly assigned date to the cache.
        ei.mTimeStamp = rd.mTimeStamp;
        if (resultIndex == MAIN_INDEX) {
            throw new AssertionError("Should not store main expression");
        }
        mExprs.put(resultIndex, ei);
        return resultIndex;
    }

    /**
     * Preserve a copy of the expression at old_index at a new index.
     * This is useful only of old_index is MAIN_INDEX or HISTORY_MAIN_INDEX.
     * This assumes that initial evaluation completed suceessfully.
     * @param in_history use a positive index so the result appears in the history.
     * @return the new index
     */
    public long preserve(long old_index, boolean in_history) {
        ExprInfo ei = copy(old_index, true);
        if (ei.mResultString == null || ei.mResultString == ERRONEOUS_RESULT) {
            throw new AssertionError("Preserving unevaluated expression");
        }
        return addToDB(in_history, ei);
    }

    /**
     * Preserve a copy of the current main expression as the most recent history entry,
     * assuming it is already in the database, but may have been lost from the cache.
     */
    public void represerve() {
        long resultIndex = getMaxIndex();
        // This requires database access only if the local state was preserved, but we
        // recreated the Evaluator.  That excludes the common cases of device rotation, etc.
        // TODO: Revisit once we deal with database failures. We could just copy from
        // MAIN_INDEX instead, but that loses the timestamp.
        ensureExprIsCached(resultIndex);
    }

    /**
     * Discard previous expression in HISTORY_MAIN_INDEX and replace it by a fresh copy
     * of the main expression. Note that the HISTORY_MAIN_INDEX expresssion is not preserved
     * in the database or anywhere else; it is always reconstructed when needed.
     */
    public void copyMainToHistory() {
        cancel(HISTORY_MAIN_INDEX, true /* quiet */);
        ExprInfo ei = copy(MAIN_INDEX, true);
        mExprs.put(HISTORY_MAIN_INDEX, ei);
    }

    /**
     * @return the {@link CalculatorExpr} representation of the result of the given
     * expression.
     * The resulting expression contains a single "token" with the pre-evaluated result.
     * The client should ensure that this is never invoked unless initial evaluation of the
     * expression has been completed.
     */
    private CalculatorExpr getCollapsedExpr(long index) {
        long real_index = isMutableIndex(index) ? preserve(index, false) : index;
        final ExprInfo ei = mExprs.get(real_index);
        final String rs = ei.mResultString;
        // An error can occur here only under extremely unlikely conditions.
        // Check anyway, and just refuse.
        // rs *should* never be null, but it happens. Check as a workaround to protect against
        // crashes until we find the root cause (b/34801142)
        if (rs == ERRONEOUS_RESULT || rs == null) {
            return null;
        }
        final int dotIndex = rs.indexOf('.');
        final int leastDigOffset = getLsdOffset(ei.mVal.get(), rs, dotIndex);
        return ei.mExpr.abbreviate(real_index,
                getShortString(rs, getMsdIndexOf(rs), leastDigOffset));
    }

    /**
     * Abbreviate the indicated expression to a pre-evaluated expression node,
     * and use that as the new main expression.
     * This should not be called unless the expression was previously evaluated and produced a
     * non-error result.  Pre-evaluated expressions can never represent an expression for which
     * evaluation to a constructive real diverges.  Subsequent re-evaluation will also not
     * diverge, though it may generate errors of various kinds.  E.g.  sqrt(-10^-1000) .
     */
    public void collapse(long index) {
        final boolean longTimeout = mExprs.get(index).mLongTimeout;
        final CalculatorExpr abbrvExpr = getCollapsedExpr(index);
        clearMain();
        mMainExpr.mExpr.append(abbrvExpr);
        mMainExpr.mLongTimeout = longTimeout;
        mChangedValue = true;
        mHasTrigFuncs = false;  // Degree mode no longer affects expression value.
    }

    /**
     * Mark the expression as changed, preventing next evaluation request from being ignored.
     */
    public void touch() {
        mChangedValue = true;
    }

    private abstract class SetWhenDoneListener implements EvaluationListener {
        private void badCall() {
            throw new AssertionError("unexpected callback");
        }
        abstract void setNow();
        @Override
        public void onCancelled(long index) {}  // Extremely unlikely; leave unset.
        @Override
        public void onError(long index, int errorId) {}  // Extremely unlikely; leave unset.
        @Override
        public void onEvaluate(long index, int initPrecOffset, int msdIndex, int lsdOffset,
                String truncatedWholePart) {
            setNow();
        }
        @Override
        public void onReevaluate(long index) {
            badCall();
        }
    }

    private class SetMemoryWhenDoneListener extends SetWhenDoneListener {
        final long mIndex;
        final boolean mPersist;
        SetMemoryWhenDoneListener(long index, boolean persist) {
            mIndex = index;
            mPersist = persist;
        }
        @Override
        void setNow() {
            if (mMemoryIndex != 0) {
                throw new AssertionError("Overwriting nonzero memory index");
            }
            if (mPersist) {
                setMemoryIndex(mIndex);
            } else {
                mMemoryIndex = mIndex;
            }
        }
    }

    private class SetSavedWhenDoneListener extends SetWhenDoneListener {
        final long mIndex;
        SetSavedWhenDoneListener(long index) {
            mIndex = index;
        }
        @Override
        void setNow() {
            mSavedIndex = mIndex;
        }
    }

    /**
     * Set the local and persistent memory index.
     */
    private void setMemoryIndex(long index) {
        mMemoryIndex = index;
        mSharedPrefs.edit()
                .putLong(KEY_PREF_MEMORY_INDEX, index)
                .apply();

        if (mCallback != null) {
            mCallback.onMemoryStateChanged();
        }
    }

    /**
     * Set the local and persistent saved index.
     */
    private void setSavedIndex(long index) {
        mSavedIndex = index;
        mSharedPrefs.edit()
                .putLong(KEY_PREF_SAVED_INDEX, index)
                .apply();
    }

    /**
     * Set mMemoryIndex (possibly including the persistent version) to index when we finish
     * evaluating the corresponding expression.
     */
    void setMemoryIndexWhenEvaluated(long index, boolean persist) {
        requireResult(index, new SetMemoryWhenDoneListener(index, persist), mDummyCharMetricsInfo);
    }

    /**
     * Set mSavedIndex (not the persistent version) to index when we finish evaluating
     * the corresponding expression.
     */
    void setSavedIndexWhenEvaluated(long index) {
        requireResult(index, new SetSavedWhenDoneListener(index), mDummyCharMetricsInfo);
    }

    /**
     * Save an immutable version of the expression at the given index as the saved value.
     * mExpr is left alone.  Return false if result is unavailable.
     */
    private boolean copyToSaved(long index) {
        if (mExprs.get(index).mResultString == null
                || mExprs.get(index).mResultString == ERRONEOUS_RESULT) {
            return false;
        }
        setSavedIndex(isMutableIndex(index) ? preserve(index, false) : index);
        return true;
    }

    /**
     * Save an immutable version of the expression at the given index as the "memory" value.
     * The expression at index is presumed to have been evaluated.
     */
    public void copyToMemory(long index) {
        setMemoryIndex(isMutableIndex(index) ? preserve(index, false) : index);
    }

    /**
     * Save an an expression representing the sum of "memory" and the expression with the
     * given index. Make mMemoryIndex point to it when we complete evaluating.
     */
    public void addToMemory(long index) {
        ExprInfo newEi = sum(mMemoryIndex, index);
        if (newEi != null) {
            long newIndex = addToDB(false, newEi);
            mMemoryIndex = 0;  // Invalidate while we're evaluating.
            setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
        }
    }

    /**
     * Save an an expression representing the subtraction of the expression with the given index
     * from "memory." Make mMemoryIndex point to it when we complete evaluating.
     */
    public void subtractFromMemory(long index) {
        ExprInfo newEi = difference(mMemoryIndex, index);
        if (newEi != null) {
            long newIndex = addToDB(false, newEi);
            mMemoryIndex = 0;  // Invalidate while we're evaluating.
            setMemoryIndexWhenEvaluated(newIndex, true /* persist */);
        }
    }

    /**
     * Return index of "saved" expression, or 0.
     */
    public long getSavedIndex() {
        return mSavedIndex;
    }

    /**
     * Return index of "memory" expression, or 0.
     */
    public long getMemoryIndex() {
        return mMemoryIndex;
    }

    private Uri uriForSaved() {
        return new Uri.Builder().scheme("tag")
                                .encodedOpaquePart(mSavedName)
                                .build();
    }

    /**
     * Save the index expression as the saved location and return a URI describing it.
     * The URI is used to distinguish this particular result from others we may generate.
     */
    public Uri capture(long index) {
        if (!copyToSaved(index)) return null;
        // Generate a new (entirely private) URI for this result.
        // Attempt to conform to RFC4151, though it's unclear it matters.
        final TimeZone tz = TimeZone.getDefault();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setTimeZone(tz);
        final String isoDate = df.format(new Date());
        mSavedName = "calculator2.android.com," + isoDate + ":"
                + (new Random().nextInt() & 0x3fffffff);
        mSharedPrefs.edit()
                .putString(KEY_PREF_SAVED_NAME, mSavedName)
                .apply();
        return uriForSaved();
    }

    public boolean isLastSaved(Uri uri) {
        return mSavedIndex != 0 && uri.equals(uriForSaved());
    }

    /**
     * Append the expression at index as a pre-evaluated expression to the main expression.
     */
    public void appendExpr(long index) {
        ExprInfo ei = mExprs.get(index);
        mChangedValue = true;
        mMainExpr.mLongTimeout |= ei.mLongTimeout;
        CalculatorExpr collapsed = getCollapsedExpr(index);
        if (collapsed != null) {
            mMainExpr.mExpr.append(getCollapsedExpr(index));
        }
    }

    /**
     * Add the power of 10 operator to the main expression.
     * This is treated essentially as a macro expansion.
     */
    private void add10pow() {
        CalculatorExpr ten = new CalculatorExpr();
        ten.add(R.id.digit_1);
        ten.add(R.id.digit_0);
        mChangedValue = true;  // For consistency.  Reevaluation is probably not useful.
        mMainExpr.mExpr.append(ten);
        mMainExpr.mExpr.add(R.id.op_pow);
    }

    /**
     * Ensure that the expression with the given index is in mExprs.
     * We assume that if it's either already in mExprs or mExprDB.
     * When we're done, the expression in mExprs may still contain references to other
     * subexpressions that are not yet cached.
     */
    private ExprInfo ensureExprIsCached(long index) {
        ExprInfo ei = mExprs.get(index);
        if (ei != null) {
            return ei;
        }
        if (index == MAIN_INDEX) {
            throw new AssertionError("Main expression should be cached");
        }
        ExpressionDB.RowData row = mExprDB.getRow(index);
        DataInputStream serializedExpr =
                new DataInputStream(new ByteArrayInputStream(row.mExpression));
        try {
            ei = new ExprInfo(new CalculatorExpr(serializedExpr), row.degreeMode());
            ei.mTimeStamp = row.mTimeStamp;
            ei.mLongTimeout = row.longTimeout();
        } catch(IOException e) {
            throw new AssertionError("IO Exception without real IO:" + e);
        }
        ExprInfo newEi = mExprs.putIfAbsent(index, ei);
        return newEi == null ? ei : newEi;
    }

    @Override
    public CalculatorExpr getExpr(long index) {
        return ensureExprIsCached(index).mExpr;
    }

    /*
     * Return timestamp associated with the expression in milliseconds since epoch.
     * Yields zero if the expression has not been written to or read from the database.
     */
    public long getTimeStamp(long index) {
        return ensureExprIsCached(index).mTimeStamp;
    }

    @Override
    public boolean getDegreeMode(long index) {
        return ensureExprIsCached(index).mDegreeMode;
    }

    @Override
    public UnifiedReal getResult(long index) {
        return ensureExprIsCached(index).mVal.get();
    }

    @Override
    public UnifiedReal putResultIfAbsent(long index, UnifiedReal result) {
        ExprInfo ei = mExprs.get(index);
        if (ei.mVal.compareAndSet(null, result)) {
            return result;
        } else {
            // Cannot change once non-null.
            return ei.mVal.get();
        }
    }

    /**
     * Does the current main expression contain trig functions?
     * Might its value depend on DEG/RAD mode?
     */
    public boolean hasTrigFuncs() {
        return mHasTrigFuncs;
    }

    /**
     * Maximum number of characters in a scientific notation exponent.
     */
    private static final int MAX_EXP_CHARS = 8;

    /**
     * Return the index of the character after the exponent starting at s[offset].
     * Return offset if there is no exponent at that position.
     * Exponents have syntax E[-]digit* .  "E2" and "E-2" are valid.  "E+2" and "e2" are not.
     * We allow any Unicode digits, and either of the commonly used minus characters.
     */
    public static int exponentEnd(String s, int offset) {
        int i = offset;
        int len = s.length();
        if (i >= len - 1 || s.charAt(i) != 'E') {
            return offset;
        }
        ++i;
        if (KeyMaps.keyForChar(s.charAt(i)) == R.id.op_sub) {
            ++i;
        }
        if (i == len || !Character.isDigit(s.charAt(i))) {
            return offset;
        }
        ++i;
        while (i < len && Character.isDigit(s.charAt(i))) {
            ++i;
            if (i > offset + MAX_EXP_CHARS) {
                return offset;
            }
        }
        return i;
    }

    /**
     * Add the exponent represented by s[begin..end) to the constant at the end of current
     * expression.
     * The end of the current expression must be a constant.  Exponents have the same syntax as
     * for exponentEnd().
     */
    public void addExponent(String s, int begin, int end) {
        int sign = 1;
        int exp = 0;
        int i = begin + 1;
        // We do the decimal conversion ourselves to exactly match exponentEnd() conventions
        // and handle various kinds of digits on input.  Also avoids allocation.
        if (KeyMaps.keyForChar(s.charAt(i)) == R.id.op_sub) {
            sign = -1;
            ++i;
        }
        for (; i < end; ++i) {
            exp = 10 * exp + Character.digit(s.charAt(i), 10);
        }
        mMainExpr.mExpr.addExponent(sign * exp);
        mChangedValue = true;
    }

    /**
     * Generate a String representation of the expression at the given index.
     * This has the side effect of adding the expression to mExprs.
     * The expression must exist in the database.
     */
    public String getExprAsString(long index) {
        return getExprAsSpannable(index).toString();
    }

    public Spannable getExprAsSpannable(long index) {
        return getExpr(index).toSpannableStringBuilder(mContext);
    }

    /**
     * Generate a String representation of all expressions in the database.
     * Debugging only.
     */
    public String historyAsString() {
        final long startIndex = getMinIndex();
        final long endIndex = getMaxIndex();
        final StringBuilder sb = new StringBuilder();
        for (long i = getMinIndex(); i < ExpressionDB.MAXIMUM_MIN_INDEX; ++i) {
            sb.append(i).append(": ").append(getExprAsString(i)).append("\n");
        }
        for (long i = 1; i < getMaxIndex(); ++i) {
            sb.append(i).append(": ").append(getExprAsString(i)).append("\n");
        }
        sb.append("Memory index = ").append(getMemoryIndex());
        sb.append(" Saved index = ").append(getSavedIndex()).append("\n");
        return sb.toString();
    }

    /**
     * Wait for pending writes to the database to complete.
     */
    public void waitForWrites() {
        mExprDB.waitForWrites();
    }

    /**
     * Destroy the current evaluator, forcing getEvaluator to allocate a new one.
     * This is needed for testing, since Robolectric apparently doesn't let us preserve
     * an open databse across tests. Cf. https://github.com/robolectric/robolectric/issues/1890 .
     */
    public void destroyEvaluator() {
        mExprDB.close();
        evaluator = null;
    }

    public interface Callback {
        void onMemoryStateChanged();
        void showMessageDialog(@StringRes int title, @StringRes int message,
                @StringRes int positiveButtonLabel, String tag);
    }
}
