LibraryComponent.java

package dev.civl.mc.library.common;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import dev.civl.mc.config.IF.CIVLConfiguration;
import dev.civl.mc.dynamic.IF.SymbolicUtility;
import dev.civl.mc.log.IF.CIVLErrorLogger;
import dev.civl.mc.model.IF.CIVLInternalException;
import dev.civl.mc.model.IF.CIVLProperty;
import dev.civl.mc.model.IF.CIVLSource;
import dev.civl.mc.model.IF.CIVLTypeFactory;
import dev.civl.mc.model.IF.CIVLUnimplementedFeatureException;
import dev.civl.mc.model.IF.Model;
import dev.civl.mc.model.IF.ModelFactory;
import dev.civl.mc.model.IF.expression.Expression;
import dev.civl.mc.model.IF.type.CIVLType;
import dev.civl.mc.semantics.IF.Evaluation;
import dev.civl.mc.semantics.IF.Evaluator;
import dev.civl.mc.semantics.IF.LibraryEvaluatorLoader;
import dev.civl.mc.semantics.IF.SymbolicAnalyzer;
import dev.civl.mc.state.IF.State;
import dev.civl.mc.state.IF.UnsatisfiablePathConditionException;
import dev.civl.mc.util.IF.Pair;
import dev.civl.sarl.IF.Reasoner;
import dev.civl.sarl.IF.SymbolicUniverse;
import dev.civl.sarl.IF.ValidityResult.ResultType;
import dev.civl.sarl.IF.expr.ArrayElementReference;
import dev.civl.sarl.IF.expr.BooleanExpression;
import dev.civl.sarl.IF.expr.NumericExpression;
import dev.civl.sarl.IF.expr.NumericSymbolicConstant;
import dev.civl.sarl.IF.expr.ReferenceExpression;
import dev.civl.sarl.IF.expr.SymbolicExpression;
import dev.civl.sarl.IF.expr.SymbolicExpression.SymbolicOperator;
import dev.civl.sarl.IF.number.IntegerNumber;
import dev.civl.sarl.IF.number.Number;
import dev.civl.sarl.IF.object.IntObject;
import dev.civl.sarl.IF.object.SymbolicObject;
import dev.civl.sarl.IF.type.SymbolicArrayType;
import dev.civl.sarl.IF.type.SymbolicCompleteArrayType;
import dev.civl.sarl.IF.type.SymbolicType;
import dev.civl.sarl.IF.type.SymbolicType.SymbolicTypeKind;

/**
 * The LibraryComponent class provides the common data and operations of library
 * evaluator, enabler, and executor.
 * 
 * @author Manchun Zheng (zmanchun)
 * 
 */
public abstract class LibraryComponent {

	/**
	 * A helper class for storaging measurements of an array object, including
	 * dimensions, extent for each dimension and slice size for each sub-array
	 * with lower dimension.
	 * 
	 * There are three fields can be read from an instance of this class:
	 * <ol>
	 * <li>dimensions: number of dimensions in the corresponding array</li>
	 * <li>extents: extents of dimensions in the corresponding array, extents
	 * are saved in a "Java array" which have the same order as order of
	 * declaring the corresponding array.</li>
	 * <li>sliceSizes: sizes of sub-array slices for each lower dimension, sizes
	 * are saved in a "java array" which have the order from largest to the
	 * smallest.</li>
	 * <li>baseType: the base type of the corresponding array, base type must
	 * not be an array type.</li>
	 * </ol>
	 * 
	 * @author ziqing
	 *
	 */
	public class ArrayMeasurement {
		final int dimensions;
		final NumericExpression extents[];
		final NumericExpression sliceSizes[];
		final SymbolicType baseType;

		ArrayMeasurement(SymbolicArrayType arrayType) {
			dimensions = arrayType.dimensions();
			extents = new NumericExpression[dimensions];
			sliceSizes = new NumericExpression[dimensions];
			// Get extents:
			for (int i = 0; i < dimensions; i++) {
				assert arrayType.isComplete();
				SymbolicCompleteArrayType completeType = (SymbolicCompleteArrayType) arrayType;

				extents[i] = completeType.extent();
				if (i < dimensions - 1)
					arrayType = (SymbolicArrayType) arrayType.elementType();
			}
			baseType = arrayType.elementType();
			// Compute slice sizes:
			NumericExpression sliceSize = one;

			for (int i = dimensions; --i >= 0;) {
				sliceSizes[i] = sliceSize;
				sliceSize = universe.multiply(sliceSize, extents[i]);
			}
		}
	}

	// The order of these operations should be consistent with civlc.cvh
	// file.
	/**
	 * Operators:
	 * 
	 * <pre>
	 *   _NO_OP,  // no operation
	 *   _MAX,    // maxinum
	 *   _MIN,    // minimun
	 *   _SUM,    // sum
	 *   _PROD,   // product
	 *   _LAND,   // logical and
	 *   _BAND,   // bit-wise and
	 *   _LOR,    // logical or
	 *   _BOR,    // bit-wise or
	 *   _LXOR,   // logical exclusive or
	 *   _BXOR,   // bit-wise exclusive or
	 *   _MINLOC, // min value and location
	 *   _MAXLOC, // max value and location
	 *   _REPLACE // replace ? TODO: Find definition for this operation
	 * </pre>
	 */
	protected enum CIVLOperator {
		CIVL_NO_OP, // no operation
		CIVL_MAX, // maxinum
		CIVL_MIN, // minimun
		CIVL_SUM, // sum
		CIVL_PROD, // product
		CIVL_LAND, // logical and
		CIVL_BAND, // bit-wise and
		CIVL_LOR, // logical or
		CIVL_BOR, // bit-wise or
		CIVL_LXOR, // logical exclusive or
		CIVL_BXOR, // bit-wise exclusive or
		CIVL_MINLOC, // min value and location
		CIVL_MAXLOC, // max value and location
		CIVL_REPLACE, // replace ? TODO: Find definition for this operation
		CIVL_EQ, // equal to
		CIVL_NEQ, // NOT equal to
	}

	/**
	 * The symbolic expression of one.
	 */
	protected NumericExpression one;

	/**
	 * The symbolic object of integer one.
	 */
	protected IntObject oneObject;

	/**
	 * The symbolic expression of three.
	 */
	protected NumericExpression three;

	/**
	 * The symbolic object of integer three.
	 */
	protected IntObject threeObject;

	/**
	 * The symbolic expression of two.
	 */
	protected NumericExpression two;

	/**
	 * The symbolic object of integer two.
	 */
	protected IntObject twoObject;

	/**
	 * The symbolic expression of zero.
	 */
	protected NumericExpression zero;

	/**
	 * The symbolic object of integer zero.
	 */
	protected IntObject zeroObject;

	/**
	 * The symbolic universe for symbolic computations.
	 */
	protected SymbolicUniverse universe;

	/**
	 * The symbolic universe for symbolic computations.
	 */
	protected SymbolicUtility symbolicUtil;

	/**
	 * The symbolic analyzer for operations on symbolic expressions and states.
	 */
	protected SymbolicAnalyzer symbolicAnalyzer;

	protected String name;

	protected BooleanExpression trueValue;
	protected BooleanExpression falseValue;

	protected LibraryEvaluatorLoader libEvaluatorLoader;

	/**
	 * The model factory of the system.
	 */
	protected ModelFactory modelFactory;

	/**
	 * The static model of the program.
	 */
	protected Model model;

	protected CIVLTypeFactory typeFactory;

	/**
	 * The CIVL configuration object
	 */
	protected CIVLConfiguration civlConfig;

	protected CIVLErrorLogger errorLogger;

	protected Evaluator evaluator;

	/**
	 * Creates a new instance of a library.
	 * 
	 * @param universe
	 *            The symbolic universe to be used.
	 * @param symbolicUtil
	 *            The symbolic utility to be used.
	 * @param symbolicAnalyzer
	 *            The symbolic analyzer to be used.
	 */
	protected LibraryComponent(String name, SymbolicUniverse universe,
			SymbolicUtility symbolicUtil, SymbolicAnalyzer symbolicAnalyzer,
			CIVLConfiguration civlConfig,
			LibraryEvaluatorLoader libEvaluatorLoader,
			ModelFactory modelFactory, CIVLErrorLogger errLogger,
			Evaluator evaluator) {
		this.name = name;
		this.universe = universe;
		this.zero = universe.zeroInt();
		this.one = universe.oneInt();
		this.two = universe.integer(2);
		this.three = universe.integer(3);
		this.zeroObject = universe.intObject(0);
		this.oneObject = universe.intObject(1);
		this.twoObject = universe.intObject(2);
		this.threeObject = universe.intObject(3);
		this.symbolicUtil = symbolicUtil;
		this.symbolicAnalyzer = symbolicAnalyzer;
		this.trueValue = universe.trueExpression();
		this.falseValue = universe.falseExpression();
		this.libEvaluatorLoader = libEvaluatorLoader;
		this.modelFactory = modelFactory;
		this.model = modelFactory.model();
		this.typeFactory = modelFactory.typeFactory();
		this.civlConfig = civlConfig;
		this.errorLogger = errLogger;
		this.evaluator = evaluator;
	}

	/**
	 * Returns the name associated to this library executor or enabler, for
	 * example, "stdio".
	 * 
	 * @return
	 */
	public String name() {
		return this.name;
	}

	/**
	 * <p>
	 * <b>Summary: </b> Apply a CIVL operation on a pair of operands.
	 * </p>
	 * 
	 * @param state
	 *            The current state
	 * @param pid
	 *            The identifier of the current process
	 * @param process
	 *            The String identifier of the current process
	 * @param operands
	 *            An array of two operands: <code>{operand0, operand1}</code>
	 * @param CIVLOp
	 *            A integer code represents a CIVL operation
	 * @param count
	 *            The number of pairs of operands.
	 * @param elementType
	 *            The {@link SymbolicType} of elements of one operand
	 * @param countStep
	 *            The number of elements in one operand
	 * @param civlsource
	 *            The {@link CIVLSource} of this operation
	 * @return A {@link SymbolicExpression} results after the operation.
	 * @throws UnsatisfiablePathConditionException
	 *             when types of operands are invalid for operations.
	 */
	protected SymbolicExpression applyCIVLOperation(State state, int pid,
			String process, SymbolicExpression operands[], CIVLOperator CIVLOp,
			NumericExpression count, SymbolicType elementType,
			CIVLSource civlsource) throws UnsatisfiablePathConditionException {
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));
		Number concCount = reasoner.extractNumber(count);
		SymbolicExpression operand0 = operands[0];
		SymbolicExpression operand1 = operands[1];
		int countStep = 1;

		if (CIVLOp == CIVLOperator.CIVL_MINLOC
				|| CIVLOp == CIVLOperator.CIVL_MAXLOC)
			countStep = 2;

		if (concCount == null) {
			SymbolicExpression[] singleOperand0 = new SymbolicExpression[countStep];
			SymbolicExpression[] singleOperand1 = new SymbolicExpression[countStep];
			SymbolicExpression[] result = new SymbolicExpression[countStep];
			NumericExpression totalUnits = universe.multiply(count,
					universe.integer(countStep));
			NumericSymbolicConstant identifier = (NumericSymbolicConstant) universe
					.symbolicConstant(universe.stringObject("j"),
							universe.integerType());

			for (int w = 0; w < countStep; w++) {
				singleOperand0[w] = universe.arrayRead(operand0,
						universe.add(identifier, universe.integer(w)));
				singleOperand1[w] = universe.arrayRead(operand1,
						universe.add(identifier, universe.integer(w)));
			}
			result = singleApplyCIVLOperation(state, pid, process,
					singleOperand0, singleOperand1, CIVLOp, countStep,
					civlsource);
			if (countStep == 1) {
				// optimization
				return universe.arrayLambda(
						universe.arrayType(elementType, totalUnits),
						universe.lambda(identifier, result[0]));
			} else {
				// When an operand contains more than one basic elements (e.g.
				// MINLOC or MAXLOC), the return the value will be constructed
				// as follows:
				// For the result of an single operation:
				// R := {a[j], b[x(j)], c[y(j)]...}, where j is a symbolic
				// constant and x(j) ,y(j) is a (integer->integer) function on
				// j.
				//
				// For the whole array w which consists of "count" Rs, given a
				// valid index i, it should return w[i].
				// w[i] := R[i - i%step]; Where R[k] := is the k-th element of R
				// with a substitution on j with k.

				// j % countStep:
				NumericExpression identOffset = universe.modulo(identifier,
						universe.integer(countStep));
				// j - j % countStep:
				NumericExpression identBase = universe.subtract(identifier,
						identOffset);
				SymbolicExpression function;

				// For R := {a[j], b[x(j)], c[y(j)]...}, giving a index k, R' is
				// computed by update all elements in R with a substitution on j
				// with k. Note here k := i - i % countStep, i is an arbitrary
				// valid index on the whole array w:
				for (int i = 0; i < countStep; i++)
					result[i] = universe.apply(
							universe.lambda(identifier, result[i]),
							Arrays.asList(identBase));
				// make R' an array:
				function = universe.array(elementType, result);
				function = universe.lambda(identifier,
						universe.arrayRead(function, identOffset));
				return universe.arrayLambda(
						universe.arrayType(elementType, totalUnits), function);
			}
		} else {
			int countInt = ((IntegerNumber) concCount).intValue();

			if (countInt <= 0)
				return universe.emptyArray(elementType);

			int totalUnits = countInt * countStep;
			SymbolicExpression[] singleOperand0 = new SymbolicExpression[countStep];
			SymbolicExpression[] singleOperand1 = new SymbolicExpression[countStep];
			SymbolicExpression[] result = new SymbolicExpression[totalUnits];
			SymbolicExpression[] singleResult;

			for (int i = 0; i < totalUnits; i = i + countStep) {
				for (int w = 0; w < countStep; w++) {
					singleOperand0[w] = universe.arrayRead(operand0,
							universe.integer(i + w));
					singleOperand1[w] = universe.arrayRead(operand1,
							universe.integer(i + w));
				}

				singleResult = singleApplyCIVLOperation(state, pid, process,
						singleOperand0, singleOperand1, CIVLOp, countStep,
						civlsource);
				System.arraycopy(singleResult, 0, result, i, countStep);
			}
			return universe.array(elementType, result);
		}
	}

	/**
	 * Completing an operation (which is included in CIVLOperation enumerator).
	 * 
	 * @author Ziqing Luo
	 * @param arg0
	 *            The new data got from the bundle
	 * @param arg1
	 *            The data has already been received previously
	 * @param op
	 *            The CIVL Operation
	 * @return
	 * @throws UnsatisfiablePathConditionException
	 */
	private SymbolicExpression[] singleApplyCIVLOperation(State state, int pid,
			String process, SymbolicExpression op0[], SymbolicExpression op1[],
			CIVLOperator op, int numElementsInOperand, CIVLSource civlsource)
			throws UnsatisfiablePathConditionException {
		BooleanExpression claim;
		SymbolicExpression[] result = new SymbolicExpression[numElementsInOperand];

		/*
		 * For MAX and MIN operation, if CIVL cannot figure out a concrete
		 * result, make a abstract function for it.
		 */
		try {
			switch (op) {
				// TODO: consider using heuristic to switch to abstract
				// functions if these expressions get too big (max,min):
				case CIVL_MAX :
					claim = universe.lessThan((NumericExpression) op1[0],
							(NumericExpression) op0[0]);
					result[0] = universe.cond(claim, op0[0], op1[0]);
					break;
				case CIVL_MIN :
					claim = universe.lessThan((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					result[0] = universe.cond(claim, op0[0], op1[0]);
					break;
				case CIVL_SUM :
					result[0] = universe.add((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_PROD :
					result[0] = universe.multiply((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_LAND :
					BooleanExpression aop0 = op0[0].isZero()
							? universe.falseExpression()
							: universe.trueExpression();
					BooleanExpression aop1 = op1[0].isZero()
							? universe.falseExpression()
							: universe.trueExpression();

					result[0] = universe.and(aop0, aop1);
					break;
				case CIVL_LOR :
					BooleanExpression oop0 = op0[0].isZero()
							? universe.falseExpression()
							: universe.trueExpression();
					BooleanExpression oop1 = op1[0].isZero()
							? universe.falseExpression()
							: universe.trueExpression();

					result[0] = universe.or(oop0, oop1);
					break;
				case CIVL_LXOR :
					BooleanExpression notNewData = universe
							.not((BooleanExpression) op0[0]);
					BooleanExpression notPrevData = universe
							.not((BooleanExpression) op1[0]);

					result[0] = universe.or(
							universe.and(notNewData,
									(BooleanExpression) op0[0]),
							universe.and((BooleanExpression) op1[0],
									notPrevData));
					break;
				case CIVL_MINLOC :
					return applyMINOrMAXLOC(state, process, op0, op1, true,
							civlsource);
				case CIVL_MAXLOC :
					return applyMINOrMAXLOC(state, process, op0, op1, false,
							civlsource);
				case CIVL_REPLACE :
				case CIVL_BAND :
					result[0] = universe.bitand((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_BOR :
					result[0] = universe.bitor((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_BXOR :
					result[0] = universe.bitxor((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_EQ :
					result[0] = universe.equals((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				case CIVL_NEQ :
					result[0] = universe.neq((NumericExpression) op0[0],
							(NumericExpression) op1[0]);
					break;
				default :
					throw new CIVLUnimplementedFeatureException(
							"CIVLOperation: " + op.name());
			}
			return result;
		} catch (ClassCastException e) {
			errorLogger.logSimpleError(civlsource, state, pid, process,
					symbolicAnalyzer.stateToString(state), CIVLProperty.OTHER,
					"Invalid operands type for CIVL Operation: " + op.name());
			throw new UnsatisfiablePathConditionException();
		}
	}

	/**
	 * Returns the count of objects in one operand in a CIVL operation. e.g.
	 * MINLOC or MAXLOC needs 2 objects for 1 operand
	 * 
	 * @param op
	 *            The {@link CIVLOperator}
	 * @return
	 */
	protected NumericExpression operandCounts(CIVLOperator civlOp) {
		if (civlOp == CIVLOperator.CIVL_MAXLOC
				|| civlOp == CIVLOperator.CIVL_MINLOC)
			return two;
		else
			return one;
	}

	protected CIVLOperator translateOperator(int op) {
		return CIVLOperator.values()[op];
	}

	/**
	 * <p>
	 * <b>Summary: </b> Apply MIN_LOC or MAX_LOC operation on two operands.
	 * </p>
	 * 
	 * @param state
	 *            The current state
	 * @param process
	 *            The String identifier of the process
	 * @param operands
	 *            An array of all operands:
	 *            <code>{loc0, idx0, loc1, idx1}</code>
	 * @param isMin
	 *            A flag, true for MIN_LOC operation, false for MAX_LOC
	 *            operation.
	 * @param civlsource
	 *            {@link CIVLSource} of the operation
	 * @return
	 * @throws UnsatisfiablePathConditionException
	 */
	private SymbolicExpression[] applyMINOrMAXLOC(State state, String process,
			SymbolicExpression[] operand0, SymbolicExpression[] operand1,
			boolean isMin, CIVLSource civlsource)
			throws UnsatisfiablePathConditionException {
		NumericExpression locations[] = {(NumericExpression) operand0[0],
				(NumericExpression) operand1[0]};
		NumericExpression indices[] = {(NumericExpression) operand0[1],
				(NumericExpression) operand1[1]};

		assert (operand0.length == 2) && (operand1.length == 2);
		return isMin
				? applyMinLocOperation(locations, indices)
				: applyMaxLocOperation(locations, indices);
	}

	/**
	 * <p>
	 * <b>Summary: </b> Apply a MINLOC operation on two operands: [loc0, idx0]
	 * and [loc1, idx1]
	 * </p>
	 * 
	 * @param locations
	 *            Location array which consists of a "location0" and a
	 *            "location1"
	 * @param indices
	 *            Index array which consists of a "index0" and a "index1"
	 * @return loc0 \lt loc1 ? [loc0, idx0] : loc0 != loc1 ? [loc1, idx1] : idx0
	 *         \lt idx1 ? [loc0, idx0]: [loc1, idx1]
	 */
	private SymbolicExpression[] applyMinLocOperation(
			NumericExpression locations[], NumericExpression indices[]) {
		BooleanExpression loc0LTloc1 = universe.lessThan(locations[0],
				locations[1]);
		BooleanExpression loc0NEQloc1 = universe
				.not(universe.equals(locations[0], locations[1]));
		BooleanExpression idx0LTidx1 = universe.lessThan(indices[0],
				indices[1]);
		SymbolicExpression locResult, idxResult;

		// optimize:
		if (loc0LTloc1.isTrue() && loc0NEQloc1.isTrue()) {
			SymbolicExpression[] result = {locations[0], indices[0]};

			return result;
		} else {
			locResult = universe.cond(loc0LTloc1, locations[0], locations[1]);
			idxResult = universe.cond(loc0LTloc1, indices[0],
					universe.cond(loc0NEQloc1, indices[1],
							universe.cond(idx0LTidx1, indices[0], indices[1])));

			SymbolicExpression[] result = {locResult, idxResult};

			return result;
		}
	}

	/**
	 * <p>
	 * <b>Summary: </b> Apply a MAXLOC operation on two operands: [loc0, idx0]
	 * and [loc1, idx1]
	 * </p>
	 * 
	 * 
	 * @param locations
	 *            Location array which consists of a "location0" and a
	 *            "location1"
	 * @param indices
	 *            Index array which consists of a "index0" and a "index1"
	 * @return loc0 \gt loc1 ? [loc0, idx0] : loc0 != loc1 ? [loc1, idx1] : idx0
	 *         \lt idx1 ? [loc0, idx0]: [loc1, idx1]
	 * @return
	 */
	private SymbolicExpression[] applyMaxLocOperation(
			NumericExpression locations[], NumericExpression indices[]) {
		BooleanExpression loc0GTloc1 = universe.lessThan(locations[1],
				locations[0]);
		BooleanExpression loc0NEQloc1 = universe
				.not(universe.equals(locations[0], locations[1]));
		BooleanExpression idx0LTidx1 = universe.lessThan(indices[0],
				indices[1]);
		SymbolicExpression locResult, idxResult;

		// optimize:
		if (loc0GTloc1.isTrue() && loc0NEQloc1.isTrue()) {
			SymbolicExpression[] result = {locations[0], indices[0]};

			return result;
		} else {
			locResult = universe.cond(loc0GTloc1, locations[0], locations[1]);
			idxResult = universe.cond(loc0GTloc1, indices[0],
					universe.cond(loc0NEQloc1, indices[1],
							universe.cond(idx0LTidx1, indices[0], indices[1])));

			SymbolicExpression[] result = {locResult, idxResult};

			return result;

		}
	}

	protected Pair<State, SymbolicExpression[]> evaluateArguments(State state,
			int pid, Expression[] arguments)
			throws UnsatisfiablePathConditionException {
		int numArgs = arguments.length;
		SymbolicExpression[] argumentValues = new SymbolicExpression[numArgs];

		for (int i = 0; i < numArgs; i++) {
			Evaluation eval = null;

			eval = evaluator.evaluate(state, pid, arguments[i]);
			argumentValues[i] = eval.value;
			state = eval.state;
		}
		return new Pair<>(state, argumentValues);

	}

	/**
	 * Pre-conditions:
	 * <ol>
	 * <li>"pointer" is a valid pointer</li>
	 * <li>"count" greater than zero</li>
	 * <li>"dataArray" is an one dimensional array</li>
	 * <li>"pointer" must points to a compatible type with the "dataArray"</li>
	 * </ol>
	 * post_condition:
	 * <ol>
	 * <li>Return a sequence of data with length "count" from the pointed object
	 * starting from the pointed position</li>
	 * </ol>
	 * Setting a sequence of data starting from a pointer
	 * 
	 * @param state
	 *            The current state
	 * @param process
	 *            The information of the process
	 * @param pointer
	 *            The pointer to the start position
	 * @param count
	 *            The number of cells in the array of data
	 * @param dataArray
	 *            The sequence of data is going to be set
	 * @param checkOutput
	 *            Flag for check output variable
	 * @param source
	 *            CIVL source of the statement
	 * @return A pair of evaluation and pointer.The data in form of an array
	 *         which can be assigned to the returned pointer.
	 * @throws UnsatisfiablePathConditionException
	 */
	public Pair<Evaluation, SymbolicExpression> setDataFrom(State state,
			int pid, String process, Expression ptrExpr,
			SymbolicExpression pointer, NumericExpression count,
			SymbolicExpression dataArray, boolean checkOutput,
			CIVLSource source) throws UnsatisfiablePathConditionException {
		NumericExpression[] arraySlicesSizes;
		NumericExpression startPos;
		NumericExpression dataSeqLength = universe.length(dataArray);
		SymbolicExpression startPtr, endPtr;
		Evaluation eval;
		Pair<Evaluation, NumericExpression[]> eval_and_slices;
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));
		ReferenceExpression symref;
		BooleanExpression claim;
		ResultType resultType;
		int dim;

		// If data length > count, report an error:
		if (!this.civlConfig.svcomp()) {
			claim = universe.lessThan(dataSeqLength, count);
			resultType = reasoner.valid(claim).getResultType();
			if (resultType.equals(ResultType.YES)
					&& civlConfig.isPropertyToggled(CIVLProperty.OUT_OF_BOUNDS))
				reportOutOfBoundError(state, pid, claim, resultType, pointer,
						dataSeqLength, count, source);
		}
		// If the type of the object is exact same as the dataArray, then do a
		// directly assignment:
		SymbolicType objType = symbolicAnalyzer
				.dynamicTypeOfObjByPointer(source, state, pointer);

		if (dataArray.type().equals(objType))
			return new Pair<>(new Evaluation(state, dataArray), pointer);

		// "pointer" may not point to a memory base type object yet
		symref = symbolicAnalyzer.getLeafNodeReference(state, pointer, source);

		// If count is one:
		if (reasoner.isValid(universe.equals(count, one))) {
			SymbolicExpression data = universe.arrayRead(dataArray, zero);

			return new Pair<>(new Evaluation(state, data),
					symbolicUtil.makePointer(pointer, symref));
		}
		// Else, count greater than one:
		if (!symref.isArrayElementReference()) {
			if (reasoner.isValid(universe.equals(count, one)))
				return new Pair<>(
						new Evaluation(state,
								universe.arrayRead(dataArray, zero)),
						symbolicUtil.makePointer(pointer, symref));
			if (civlConfig.isPropertyToggled(CIVLProperty.OUT_OF_BOUNDS)) {
				// report error:
				CIVLType integerType;

				integerType = typeFactory.integerType();
				errorLogger.logSimpleError(source, state, pid, process,
						symbolicAnalyzer.stateInformation(state),
						CIVLProperty.OUT_OF_BOUNDS,
						"$bundle_unpack out of bound: \nPointer: "
								+ symbolicAnalyzer.symbolicExpressionToString(
										source, state,
										ptrExpr.getExpressionType(), pointer)
								+ "\nSize: "
								+ symbolicAnalyzer.symbolicExpressionToString(
										source, state, integerType, count)
								+ "\n");
			}
		}
		eval_and_slices = evaluator.arrayElementReferenceAdd(state, pid,
				pointer, count, source);
		eval = eval_and_slices.left;
		endPtr = eval.value;
		state = eval.state;
		arraySlicesSizes = eval_and_slices.right;
		// If the pointer addition happens to be done within the minimal array
		// slice, the "arraySlicesSizes" is null and we don't really need it.
		// Otherwise, we can reuse it.
		if (arraySlicesSizes == null) {
			arraySlicesSizes = new NumericExpression[1];
			arraySlicesSizes[0] = one;
		}
		dim = arraySlicesSizes.length;
		startPtr = symbolicUtil.makePointer(pointer, symref);
		startPos = zero;
		if (symref.isArrayElementReference()) {
			NumericExpression[] startIndices = symbolicUtil
					.extractArrayIndicesFrom(startPtr);
			int numIndices = startIndices.length;

			assert numIndices >= dim;
			// Loop until startPtr and endPtr point to the common array slice:
			for (int i = 1; !startPtr.equals(endPtr); i++) {
				startPtr = symbolicUtil.parentPointer(startPtr);
				endPtr = symbolicUtil.parentPointer(endPtr);
				startPos = universe.add(startPos,
						universe.multiply(startIndices[numIndices - i],
								arraySlicesSizes[dim - i]));
			}
		}
		eval = evaluator.dereference(source, state, pid, process, startPtr,
				false, true);
		state = eval.state;
		if (eval.value.type().typeKind().equals(SymbolicTypeKind.ARRAY)) {
			eval = setDataBetween(state, pid, eval.value, arraySlicesSizes,
					startPos, count, pointer, dataArray, source);
		} else if (civlConfig.isPropertyToggled(CIVLProperty.UNDEFINED_VALUE)) {
			reportOutOfBoundError(state, pid, null, null, startPtr, one, count,
					source);
		}
		return new Pair<>(eval, startPtr);
	}

	/**
	 * Pre-condition:
	 * <ol>
	 * <li>"pointer" is valid</li>
	 * <li>"count" >= 0</li>
	 * </ol>
	 * post_condition:
	 * <ol>
	 * <li>Return a sequence of data with length "count" from the pointed object
	 * starting from the pointed position</li>
	 * </ol>
	 * Get a sequence of data starting from a pointer.
	 * 
	 * @param state
	 *            The current state
	 * @param process
	 *            The information of the process
	 * @param pointer
	 *            The pointer to the start position of a sequence of data
	 * @param count
	 *            The number of cells in the array of data
	 * @param checkOutput
	 *            Flag for check output variable
	 * @param source
	 *            CIVL source of the statement
	 * @return Evaluation contains the sequence of data which is in form of a
	 *         one dimensional array.
	 * @throws UnsatisfiablePathConditionException
	 */
	public Evaluation getDataFrom(State state, int pid, String process,
			Expression pointerExpr, SymbolicExpression pointer,
			NumericExpression count, boolean toBase, boolean checkOutput,
			CIVLSource source) throws UnsatisfiablePathConditionException {
		ReferenceExpression symref;
		Evaluation eval;
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));

		// If "count" == 1:
		if (reasoner.isValid(universe.equals(count, one))) {
			eval = evaluator.dereference(source, state, pid, process, pointer,
					true, true);
			if (civlConfig.isPropertyToggled(CIVLProperty.UNDEFINED_VALUE)
					&& eval.value.isNull())
				reportUndefinedValueError(state, pid,
						symbolicUtil.getSymRef(pointer).isIdentityReference(),
						pointerExpr);
			eval.value = universe.array(eval.value.type(),
					Arrays.asList(eval.value));
			eval.value = arrayFlatten(state, pid, eval.value,
					new ArrayMeasurement((SymbolicArrayType) eval.value.type()),
					source);
			return eval;
		}
		// Else "count" > 1:
		SymbolicExpression rootPointer, rootArray;
		List<NumericExpression> indicesList = new LinkedList<>();
		NumericExpression indices[];
		boolean isHeap = symbolicUtil.isPointerToHeap(pointer);

		symref = symbolicUtil.getSymRef(pointer);
		while (symref.isArrayElementReference()) {
			indicesList.add(((ArrayElementReference) symref).getIndex());
			symref = ((ArrayElementReference) symref).getParent();
			// Special handling for memory heap:
			if (isHeap)
				break;
		}
		rootPointer = symbolicUtil.makePointer(pointer, symref);
		eval = evaluator.dereference(source, state, pid, process, rootPointer,
				false, true);
		state = eval.state;
		rootArray = eval.value;
		if (civlConfig.isPropertyToggled(CIVLProperty.UNDEFINED_VALUE)
				&& rootArray.isNull())
			reportUndefinedValueError(state, pid,
					symbolicUtil.getSymRef(pointer).isIdentityReference(),
					pointerExpr);
		indices = new NumericExpression[indicesList.size()];
		indicesList.toArray(indices);
		// reverse so that the order satisfies the requirements of the
		// arraySliceRead method:
		for (int i = (indices.length / 2) - 1; i >= 0; i--) {
			NumericExpression tmp = indices[i];
			indices[i] = indices[indices.length - i - 1];
			indices[indices.length - i - 1] = tmp;
		}
		eval.value = arraySliceRead(state, pid, rootArray, indices, count,
				source);
		return eval;
	}

	/**
	 * <p>
	 * Report an attempt to read undefined (or uninitialized) object error
	 * </p>
	 * 
	 * @param state
	 *            The current state when calling this method
	 * @param pid
	 *            The PID of the process who calls this method
	 * @param isVariable
	 *            If the object is an variable
	 * @param expression
	 *            The expression associates to this error. Error reporting will
	 *            be on the {@link CIVLSource} of this expression.
	 * @throws UnsatisfiablePathConditionException
	 *             always.
	 */
	public void reportUndefinedValueError(State state, int pid,
			boolean isVariable, Expression expression)
			throws UnsatisfiablePathConditionException {
		String kind = "undefined";
		String process = state.getProcessState(pid).name();

		if (isVariable)
			kind = "uninitialized";
		errorLogger.logSimpleError(expression.getSource(), state, pid, process,
				symbolicAnalyzer.stateInformation(state),
				CIVLProperty.UNDEFINED_VALUE,
				"Attempt to read an object with " + kind + " value");
	}

	/**
	 * <p>
	 * <b>Pre-condition</b> <br>
	 * 1. The dimensions of the array must be greater than or equal to
	 * "indices.length"; <br>
	 * 2. Values in "indices" array are ordered from left to right as same as
	 * subscript order. (e.g. A[a][b][c] ==> {a,b,c})
	 * </p>
	 * 
	 * <p>
	 * Given a group of indices I, an array a and a number c. Read c consequent
	 * elements start from a[I]. If size of I less than the dimension of a, it
	 * will be supplemented with zeros. e.g. Given an array a[4][5][6] and a
	 * ordered set of indices {2, 1}. The indices locate the element [2][1][0]
	 * in array a.
	 * </p>
	 * 
	 * @param state
	 *            The current state when calling this method
	 * @param pid
	 *            The PID of the current process
	 * @param arrayType
	 *            The {@link CIVLType} of the array
	 * @param array
	 *            The array that will be read
	 * @param indices
	 *            The start indices of the element in the array.
	 * @param count
	 *            The number of elements will be read
	 * @param source
	 *            The {@link CIVLSource} associates to this method call.
	 * @return A sequence of elements (A one dimensional array)
	 * @throws UnsatisfiablePathConditionException
	 *             When array out of bound happens.
	 */
	public SymbolicExpression arraySliceRead(State state, int pid,
			SymbolicExpression array, NumericExpression indices[],
			NumericExpression count, CIVLSource source)
			throws UnsatisfiablePathConditionException {
		NumericExpression pos = zero, step = one;
		SymbolicExpression flattenArray;
		ArrayMeasurement arrayMeasure = new ArrayMeasurement(
				(SymbolicArrayType) array.type());
		NumericExpression sliceSizes[] = arrayMeasure.sliceSizes;
		int i;

		// Attempt to avoid array flatten for multi-dimensional arrays.
		// If the size of the smallest (1 dimentional, if single cell is NOT
		// counted as an array slice) array slice is greater than or equal to
		// the index (or 'offset') of the smallest array slice plus the count,
		// then directly return a sub-array of that slice ...
		if (arrayMeasure.dimensions > 1) {
			// The size of the smallest array slice:
			NumericExpression minSliceSize = sliceSizes[sliceSizes.length - 2];
			// The index of the smallest array slice:
			NumericExpression index = indices.length == arrayMeasure.dimensions
					? indices[indices.length - 1]
					: zero;
			BooleanExpression indexPlusCountLteSize = universe
					.lessThanEquals(universe.add(index, count), minSliceSize);
			Reasoner reasoner = universe
					.reasoner(state.getPathCondition(universe));

			if (reasoner.isValid(indexPlusCountLteSize)) {
				for (i = 0; i < arrayMeasure.dimensions - 1; i++)
					array = i < indices.length
							? universe.arrayRead(array, indices[i])
							: universe.arrayRead(array, zero);
				return symbolicAnalyzer.getSubArray(state, pid, array, index,
						universe.add(index, count), source);
			}
		}
		flattenArray = arrayFlatten(state, pid, array, arrayMeasure, source);
		for (i = 0; i < indices.length; i++)
			pos = universe.add(pos,
					universe.multiply(indices[i], sliceSizes[i]));
		// valid subscript: d < indices.length <= dimension && sliceSizes.length
		// == dimension
		step = i > 0 ? sliceSizes[i - 1] : sliceSizes[0];
		return symbolicAnalyzer.getSubArray(state, pid, flattenArray, pos,
				universe.add(pos, universe.multiply(count, step)), source);
	}

	/**
	 * <p>
	 * <b>Pre-condition:</b> <br>
	 * length(targetArray) >= length(dataArray) + index;<br>
	 * elementTypeOf(targetArray) == elementTypeOf(dataArray)
	 * </p>
	 * <p>
	 * Writes the sequence of elements in "dataArray" to the "targetArray" from
	 * the "index" of the "targetArray". This operation only will be done within
	 * one dimension, i.e. both "dataArray" and "targetArray" represent a
	 * sequence of elements, no matter the type of the elements is a scalar
	 * type, an array type or a complex structure.
	 * 
	 * For example, writes b[2][3] into a[3][3] start from index 0, the results
	 * will be:
	 * 
	 * a[3][3] = {b[0][0], b[0][1], b[0][2], b[1][0], b[1][1], b[1][2], a[2][0],
	 * a[2][1], a[2][2]}
	 * 
	 * </p>
	 * 
	 * @param state
	 *            The current state when this method is called
	 * @param pid
	 *            The PID of the process
	 * @param targetArray
	 *            The target array that will be written
	 * @param dataArray
	 *            The sequence of data that will be insert into the targetArray
	 * @param index
	 *            The start index of this write operation
	 * @param source
	 *            The {@link CIVLSource} related with this method call
	 * @return
	 */
	public SymbolicExpression arraySliceWrite1d(State state, int pid,
			SymbolicExpression targetArray, SymbolicExpression dataArray,
			NumericExpression index, CIVLSource source) {
		NumericExpression dataLength = universe.length(dataArray);
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));
		Number concreteDataLength = reasoner.extractNumber(dataLength);

		// If the data array has a non-concrete length, use array lambda:
		if (concreteDataLength == null) {
			NumericSymbolicConstant symConst = (NumericSymbolicConstant) universe
					.symbolicConstant(universe.stringObject("i"),
							universe.integerType());
			BooleanExpression hiCond = universe.lessThan(symConst,
					universe.add(index, dataLength));
			BooleanExpression loCond = universe.lessThanEquals(index, symConst);
			SymbolicExpression elementLambda;
			SymbolicCompleteArrayType targetArrayType = (SymbolicCompleteArrayType) targetArray
					.type();

			elementLambda = universe.lambda(symConst,
					universe.cond(universe.and(hiCond, loCond),
							universe.arrayRead(dataArray, symConst),
							universe.arrayRead(targetArray, symConst)));
			return universe.arrayLambda(targetArrayType, elementLambda);
		} else {
			int intDataLength = ((IntegerNumber) concreteDataLength).intValue();

			for (int i = 0; i < intDataLength; i++) {
				NumericExpression I = universe.integer(i);
				NumericExpression IplusIndex = universe.add(I, index);

				targetArray = universe.arrayWrite(targetArray, IplusIndex,
						universe.arrayRead(dataArray, I));
			}
			return targetArray;
		}
	}

	/**
	 * Cast an array to another array. The two arrays before and after casting
	 * must be able to hold same number of non-array elements.<br>
	 * e.g. For arrays <code>int a[2][2]; int b[4]; int c[5]</code>, a and b can
	 * be casted into each other but both of them can not be casted to c.
	 * 
	 * @author Ziqing Luo
	 * @param state
	 *            The current state
	 * @param pid
	 *            The PID of the calling process
	 * @param oldArray
	 *            The array before casting
	 * @param oldArrayMeasurement
	 *            The {@link ArrayMeasurement} of the oldArray
	 * @param targetType
	 *            The target type that the oldArray will be casted to
	 * @param source
	 *            The CIVL source of the oldArray or the pointer to OldArray
	 * @return casted array
	 * @throws UnsatisfiablePathConditionException
	 */
	public SymbolicExpression arrayCasting(State state, int pid,
			SymbolicExpression oldArray, ArrayMeasurement oldArrayMeasurement,
			SymbolicCompleteArrayType targetType, CIVLSource source)
			throws UnsatisfiablePathConditionException {
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));
		int[] targetExtentNumbers;
		int dim;

		// Straightforward Optimizations:
		if (oldArray.type().equals(targetType))
			return oldArray;
		// Optimization: if oldArray is a symbolic constant, just change type:
		if (oldArray.operator() == SymbolicOperator.SYMBOLIC_CONSTANT) {
			SymbolicObject[] args = {oldArray.argument(1)};

			return universe.make(SymbolicOperator.SYMBOLIC_CONSTANT, targetType,
					args);
		}

		ArrayMeasurement targetArrayMeasurement = new ArrayMeasurement(
				targetType);

		dim = targetArrayMeasurement.dimensions;
		targetExtentNumbers = new int[dim];
		for (int d = 0; d < dim; ++d) {
			IntegerNumber extent = (IntegerNumber) reasoner
					.extractNumber(targetArrayMeasurement.extents[d]);

			if (extent == null)
				throw new CIVLUnimplementedFeatureException(
						"Transform symbolic array " + oldArray + " of type "
								+ oldArray.type() + "to another type "
								+ targetType);
			targetExtentNumbers[d] = extent.intValue();
		}

		SymbolicExpression flattenArray = arrayFlatten(state, pid, oldArray,
				oldArrayMeasurement, source);

		return flattenToMultiDimensionalArray(targetExtentNumbers,
				oldArrayMeasurement.baseType, flattenArray);
	}

	/**
	 * Transform an flatten array a to a multiple dimensional array b. The
	 * extent of a equals to the product of the extents of b.
	 * 
	 * @param extents
	 *            An array of extents {e<sub>0</sub>, e<sub>1</sub>, ..., e
	 *            <sub>n-1</sub>} for a multi-dimensional array
	 *            <code>T b[e<sub>0</sub>][e<sub>1</sub>][..][e<sub>n-1</sub>]</code>
	 * @param baseType
	 *            The base type T of the multi-dimensional array
	 *            <code>T b[e<sub>0</sub>][e<sub>1</sub>][..][e<sub>n-1</sub>]</code>
	 * @param flatArray
	 *            The flatten array T a[e<sub>0</sub> * e<sub>1</sub> * ... * e
	 *            <sub>n-1</sub>];
	 * @return The multi-dimensional array b.
	 */
	SymbolicExpression flattenToMultiDimensionalArray(int extents[],
			SymbolicType baseType, SymbolicExpression flatArray) {
		return this.flattenToMultiDimensionalArrayWorker(extents, 0, baseType,
				flatArray, 0).left;
	}
	/**
	 * The recursive worker method of
	 * {@link #flattenToMultiDimensionalArray(int[], SymbolicType, SymbolicExpression)}
	 * .
	 * 
	 * @param extents
	 *            An array of extents {e<sub>0</sub>, e<sub>1</sub>, ..., e
	 *            <sub>n-1</sub>} for a multi-dimensional array
	 *            <code>T b[e<sub>0</sub>][e<sub>1</sub>][..][e<sub>n-1</sub>]</code>
	 * @param dim
	 *            current dimension. This method recursively creates elements
	 *            for each dimension, this parameter represents the current
	 *            dimension of this method execution.
	 * @param baseType
	 *            The base type T of the multi-dimensional array
	 *            <code>T b[e<sub>0</sub>][e<sub>1</sub>][..][e<sub>n-1</sub>]</code>
	 * @param flatArray
	 *            The flatten array T a[e<sub>0</sub> * e<sub>1</sub> * ... * e
	 *            <sub>n-1</sub>];
	 * @param flatArrayOffset
	 *            Each recursive execution creates an element from a segment on
	 *            the flatten array. This flatArrayOffset is the start index of
	 *            the segment.
	 * @return A sub-array and the number of base elements in this sub-array.
	 */
	private Pair<SymbolicExpression, Integer> flattenToMultiDimensionalArrayWorker(
			int extents[], int dim, SymbolicType baseType,
			SymbolicExpression flatArray, int flatArrayOffset) {
		List<SymbolicExpression> components = new LinkedList<>();
		SymbolicExpression result;

		if (dim < extents.length - 1) {
			// If this is not the base case...
			int step = 1;

			for (int i = 0; i < extents[dim]; i++) {
				Pair<SymbolicExpression, Integer> subResult = flattenToMultiDimensionalArrayWorker(
						extents, dim + 1, baseType, flatArray, flatArrayOffset);

				step = subResult.right;
				flatArrayOffset += step;
				components.add(subResult.left);
			}
			// components shall never be empty since the extent of an array
			// shall never be zero:
			return new Pair<>(
					universe.array(components.get(0).type(), components),
					extents[dim] * step);
		} else {
			// base case:
			for (int i = 0; i < extents[dim]; i++)
				components.add(universe.arrayRead(flatArray,
						universe.integer(flatArrayOffset++)));
			result = universe.array(baseType, components);
			return new Pair<>(result, extents[dim]);
		}
	}

	/**
	 * <p>
	 * <b>Pre-condition:</b>'array' must be a complete array object. <br>
	 * 'arrayMeasurement' is an {@link ArrayMeasurement} object associates to
	 * the 'array'.
	 * </p>
	 * <p>
	 * Flatten an array to a one-dimensional array whose elements must have
	 * non-array type.
	 * </p>
	 * 
	 * @param state
	 *            The current state when this method is called
	 * @param pid
	 *            The PID of the calling process.
	 * @param array
	 *            The complete array object
	 * @param arrayMeasurement
	 *            The {@link ArrayMeasurement} of the array.
	 * @param civlsource
	 *            The {@link CIVLSource} associates to this method.
	 * @return
	 * @throws UnsatisfiablePathConditionException
	 */
	public SymbolicExpression arrayFlatten(State state, int pid,
			SymbolicExpression array, ArrayMeasurement arrayMeasurement,
			CIVLSource civlsource) throws UnsatisfiablePathConditionException {
		Queue<SymbolicExpression> subTreeQueue = new LinkedList<>();
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));
		SymbolicType baseType = arrayMeasurement.baseType;
		NumericExpression extents[] = arrayMeasurement.extents;
		NumericExpression sliceSizes[] = arrayMeasurement.sliceSizes;
		int dimensions = arrayMeasurement.dimensions;

		subTreeQueue.add(array);
		// If any extent of the array is non-concrete, use lambdaFlatten:
		for (int d = 0; d < dimensions; d++)
			if (reasoner.extractNumber(extents[d]) == null)
				return arrayLambdaFlatten2(state, array, sliceSizes, extents,
						civlsource);
		// If the totoal size of the array is concrete:
		for (int d = 0; d < dimensions; d++) {
			int prevExtent = subTreeQueue.size();
			NumericExpression extent;
			Number concExtent;
			int intExtent;

			extent = extents[d];
			concExtent = reasoner.extractNumber(extent);
			// TODO: it's possible that an array 'a[1/N][N]' will be falttened
			// as an array having concrete extents, but it should be really rare
			// case so just throw a internal error here for now. It it realy
			// happens, change the code here.
			if (concExtent == null)
				throw new CIVLInternalException(
						"Unexpected exception during flatten an array of concrete extents.",
						civlsource);
			intExtent = ((IntegerNumber) concExtent).intValue();
			for (int i = 0; i < prevExtent; i++) {
				array = subTreeQueue.poll();
				for (int j = 0; j < intExtent; j++)
					subTreeQueue.add(
							universe.arrayRead(array, universe.integer(j)));
			}
		}
		return universe.array(baseType, subTreeQueue);
	}

	/**
	 * Pre-condition:
	 * <ol>
	 * <li>"pointer" points to the start position</li>
	 * <li>"count" > 0</li>
	 * <li>"count" >= length(dataSequence)</li>
	 * <li>"array" has {@link SymbolicCompleteArrayType}</li>
	 * <li>"dataSequence" is an one dimensional array</li>
	 * </ol>
	 * Post-condition:
	 * <ol>
	 * <li>left side of the pair: Return the new value of the pointed object
	 * after assigning the given data sequence from pointed position</li>
	 * <li>right side of the pair: Return the pointer which can be assigned with
	 * the new value</li>
	 * </ol>
	 * Setting a sequence of data between two array element references. Returns
	 * the settled new array and the pointer to that array.
	 * 
	 * Pre-condition: start pointer and end pointer should point to the same
	 * object.
	 * 
	 * @param state
	 *            The current state
	 * @param pid
	 *            The PID of the calling process
	 * @param startPtr
	 *            The pointer to the start position
	 * @param endPtr
	 *            The pointer to the end position
	 * @param dataSequence
	 *            The sequence of data which is going to be set
	 * @param arraySlicesSizes
	 *            The capacity information of the array pointed by the startPtr
	 *            or endPtr(These two pointers point to the same object).<br>
	 *            Note: Here capacity information of an array means that for one
	 *            cell in each dimension of an array how many non-array elements
	 *            it can hold. e.g. For array <code>int a[2][2];</code>, the one
	 *            cell in deepest dimension can only hold one element while one
	 *            cell in the second deepest dimension can hold 2 elements. Here
	 *            we use 0 marking (which is key in the given map) the deepest
	 *            dimension and 1 marking the second deepest dimension and so
	 *            forth.
	 * @param source
	 *            The CIVL source of the start pointer.
	 * @return the settled new array and the pointer to that array.
	 * @throws UnsatisfiablePathConditionException
	 * @author Ziqing Luo
	 */
	private Evaluation setDataBetween(State state, int pid,
			SymbolicExpression array, NumericExpression[] arraySlicesSizes,
			NumericExpression startPos, NumericExpression count,
			SymbolicExpression pointer, SymbolicExpression dataSequence,
			CIVLSource source) throws UnsatisfiablePathConditionException {
		SymbolicExpression flattenArray;
		NumericExpression dataSize;
		NumericExpression i;
		BooleanExpression claim;
		Reasoner reasoner = universe.reasoner(state.getPathCondition(universe));

		dataSize = universe.length(dataSequence);
		// Direct assignment conditions:
		// 1. start position is zero.
		// 2. Interval between pointers equals to data size.
		// 3. The least common array capacity equals to data size.
		if (reasoner.isValid(universe.equals(startPos, zero))
				&& arraySlicesSizes.length == 1) {
			NumericExpression arraySize = universe.length(array);

			claim = universe.and(universe.equals(dataSize, count),
					universe.equals(dataSize, arraySize));
			if (reasoner.isValid(claim))
				return new Evaluation(state, dataSequence);
		} // TODO: what if the length of dataSize is non-concrete and cannot be
			// decided by reasoner?
		flattenArray = arrayFlatten(state, pid, array,
				new ArrayMeasurement((SymbolicArrayType) array.type()), source);
		i = startPos;

		Number dataSizeConcrete = reasoner.extractNumber(dataSize);

		if (dataSizeConcrete == null) {
			// TODO: only if flattenArray has dimension 1:
			NumericSymbolicConstant idx = (NumericSymbolicConstant) universe
					.symbolicConstant(universe.stringObject("i"),
							universe.integerType());
			BooleanExpression condition = universe.and(
					universe.lessThanEquals(startPos, idx),
					universe.lessThan(idx, universe.add(startPos, dataSize)));
			SymbolicExpression function = universe.cond(condition,
					universe.arrayRead(dataSequence,
							universe.subtract(idx, startPos)),
					universe.arrayRead(flattenArray, idx));

			flattenArray = universe.arrayLambda(
					(SymbolicCompleteArrayType) flattenArray.type(),
					universe.lambda(idx, function));
			return new Evaluation(state, flattenArray);
			// throw new CIVLInternalException(
			// "Array write with a non-concrete length", source);
		}
		int dataSizeInt = ((IntegerNumber) dataSizeConcrete).intValue();
		for (int j = 0; j < dataSizeInt; j++) {
			SymbolicExpression elementInDataArray = null;
			NumericExpression jVal = universe.integer(j);

			elementInDataArray = universe.arrayRead(dataSequence, jVal);
			flattenArray = universe.arrayWrite(flattenArray, i,
					elementInDataArray);
			i = universe.add(i, one);
		}
		flattenArray = arrayCasting(state, pid, flattenArray,
				new ArrayMeasurement((SymbolicArrayType) flattenArray.type()),
				(SymbolicCompleteArrayType) array.type(), source);
		return new Evaluation(state, flattenArray);
	}

	/**
	 * <p>
	 * Pre-condition: array has a complete array type. <br>
	 * dimension(array) == arraySliceSizes.length
	 * </p>
	 * <p>
	 * Given a complete array a[N0][N1]..[Nn] (n >= 0), flatten a to a
	 * one-dimensional array a'[N0 * N1 * .. * Nn]. The value of a' will be
	 * <code>
	 * let f(i, j) := Ni * Ni+1 * .. * Nj (j > i);
	 * 
	 * lambda int i : a[i/f(1,n)][i%f(1,n)/f(2,n)][i%f(1,n)%f(2,n)/f(3,n)]...[i%f(1,n)%..%f(n-1,n)]
	 * </code> <br>
	 * This method is used to flatten a multiple dimensional array with
	 * non-concrete size into an one-dimensional array.
	 * </p>
	 * 
	 * @param state
	 *            The current state when this method is called
	 * @param array
	 *            The array that will be flattened.
	 * @param arraySliceSizes
	 *            An sequence of size of slices of the parameter 'array'
	 * @param arrayExtents
	 *            An sequence of extents of the parameter 'array'
	 * @param civlsource
	 *            The {@link CIVLSource} corresponding to this method call
	 * @return A flattened array
	 */
	private SymbolicExpression arrayLambdaFlatten2(State state,
			SymbolicExpression array, NumericExpression[] arraySliceSizes,
			NumericExpression[] arrayExtents, CIVLSource civlsource) {
		SymbolicCompleteArrayType arrayType = (SymbolicCompleteArrayType) array
				.type();
		int dim = arrayType.dimensions();
		int newDim;
		// pre-process: preprocess an array
		// a[1][1][...][1][n][...][m] to a'[n][...][m]:
		for (int i = 0; i < dim - 1; i++)
			if (arrayExtents[i].isOne()) {
				array = universe.arrayRead(array, zero);
			} else
				break;
		// this cast is guaranteed to be correct since the loop above loops from
		// 0 to dim - 1...
		arrayType = (SymbolicCompleteArrayType) array.type();
		newDim = arrayType.dimensions();
		if (newDim == 1)
			return array;
		if (newDim < dim) {
			arraySliceSizes = Arrays.copyOfRange(arraySliceSizes, dim - newDim,
					dim);
			dim = newDim;
		}
		// end of pre-process

		NumericSymbolicConstant symConst = (NumericSymbolicConstant) universe
				.symbolicConstant(universe.stringObject("i"),
						universe.integerType());
		NumericExpression extent = arrayType.extent();
		NumericExpression index = symConst;
		SymbolicExpression arrayReadFunc = array;

		for (int d = 0; d < dim; d++) {
			arrayReadFunc = universe.arrayRead(arrayReadFunc,
					universe.divide(index, arraySliceSizes[d]));
			index = universe.modulo(index, arraySliceSizes[d]);
		}
		arrayType = universe.arrayType(arrayReadFunc.type(),
				universe.multiply(arraySliceSizes[0], extent));
		return universe.arrayLambda(arrayType,
				universe.lambda(symConst, arrayReadFunc));
	}

	/**
	 * Helper function of report an out of bound error.
	 * 
	 * @param state
	 *            The current state
	 * @param process
	 *            The string identifier of the process
	 * @param claim
	 *            The {@link BooleanExpression} of the predicate (optional, can
	 *            be null)
	 * @param resultType
	 *            The {@link ResultType} of reasoning the predicate (optional,
	 *            can be null)
	 * @param pointer
	 *            The pointer to the array
	 * @param arrayLength
	 *            The length of the array
	 * @param offset
	 *            The offset of the element from the position pointed by pointer
	 * @param source
	 * @return
	 * @throws UnsatisfiablePathConditionException
	 */
	private void reportOutOfBoundError(State state, int pid,
			BooleanExpression claim, ResultType resultType,
			SymbolicExpression pointer, NumericExpression arrayLength,
			NumericExpression offset, CIVLSource source)
			throws UnsatisfiablePathConditionException {
		String message = "Out of bound error may happen when access on an array element.\n"
				+ "Pointer:"
				+ symbolicAnalyzer.symbolicExpressionToString(source, state,
						null, pointer)
				+ "\n" + "Offset:"
				+ symbolicAnalyzer.symbolicExpressionToString(source, state,
						null, offset)
				+ "\n" + "Array length:"
				+ symbolicAnalyzer.symbolicExpressionToString(source, state,
						null, arrayLength);

		if (claim != null && resultType != null)
			state = errorLogger.logError(source, state, pid,
					symbolicAnalyzer.stateInformation(state), claim, resultType,
					CIVLProperty.OUT_OF_BOUNDS, message);
		else
			errorLogger.logSimpleError(source, state, pid,
					state.getProcessState(pid).name(),
					symbolicAnalyzer.stateInformation(state),
					CIVLProperty.OUT_OF_BOUNDS, message);
		throw new UnsatisfiablePathConditionException();
	}
}