CellFactory.java

package edu.udel.cis.vsl.tass.dynamic.impl.cell;

import java.util.Vector;

import edu.udel.cis.vsl.tass.dynamic.IF.cell.LiteralCellIF;
import edu.udel.cis.vsl.tass.model.IF.FunctionIF;
import edu.udel.cis.vsl.tass.model.IF.ModelIF;
import edu.udel.cis.vsl.tass.model.IF.ProcessIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ObjectLiteralExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.scope.LocalScopeIF;
import edu.udel.cis.vsl.tass.model.IF.variable.LocalVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.ProcessVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.SharedVariableIF;

public class CellFactory {

	/**
	 * Used to flyweight (store) each object literal (i.e., literal cell of
	 * array, struct, or other composite type) cell that is created. These are
	 * indexed by object literal id.
	 */
	private Vector<LiteralCellIF> literalVector = new Vector<LiteralCellIF>();

	/**
	 * Indexed by model id (unknown extent, hence the use of Vector), then
	 * global id (known extent, hence the use of array).
	 */
	private Vector<SharedCell[]> sharedVector = new Vector<SharedCell[]>();

	/**
	 * Process variable cells. Indexed by model id (extent unknown), pid (extent
	 * known), process variable id (extent known)
	 */
	private Vector<ProcessCell[][]> processVector = new Vector<ProcessCell[][]>();

	/**
	 * Indexed by model id (unknown), stack index (unknown), pid (known),
	 * function id (known), scope id (known), local id (known)
	 */
	private Vector<Vector<LocalCell[][][][]>> localVector = new Vector<Vector<LocalCell[][][][]>>();

	/** Indexed by model id (unknown), heap index (unknown), pid (known) . */
	private Vector<Vector<HeapCell[]>> heapVector = new Vector<Vector<HeapCell[]>>();

	public CellFactory() {
	}

	public LiteralCell literalCell(ObjectLiteralExpressionIF expression) {
		int eid = expression.objectLiteralID();
		LiteralCell result;

		if (eid < literalVector.size()) {
			result = (LiteralCell) literalVector.get(eid);
		} else {
			literalVector.setSize(eid + 1);
			result = null;
		}
		if (result == null) {
			result = new LiteralCell(expression);
			literalVector.set(eid, result);
		}
		return result;
	}

	public SharedCell sharedCell(SharedVariableIF variable) {
		ModelIF model = variable.model();
		int mid = model.id();
		int vid = variable.idInScope();
		SharedCell[] sharedArray = null;
		SharedCell result;

		if (mid < sharedVector.size()) {
			sharedArray = sharedVector.get(mid);
		} else {
			sharedVector.setSize(mid + 1);
		}
		if (sharedArray == null) {
			sharedArray = new SharedCell[model.scope().numVariables()];
			sharedVector.set(mid, sharedArray);
		}
		result = sharedArray[vid];
		if (result == null) {
			result = new SharedCell(variable);
			sharedArray[vid] = result;
		}
		return result;
	}

	public ProcessCell processCell(ProcessVariableIF variable) {
		ModelIF model = variable.model();
		int mid = model.id();
		ProcessCell[][] array1 = null;
		ProcessIF process = variable.scope().process();
		int pid = process.pid();
		int vid = variable.idInScope();
		ProcessCell result = null;

		if (mid < processVector.size()) {
			array1 = processVector.get(mid);
		} else {
			processVector.setSize(mid + 1);
		}
		if (array1 == null) {
			array1 = new ProcessCell[model.numProcs()][];
			processVector.set(mid, array1);
		}

		ProcessCell[] array2 = array1[pid];

		if (array2 == null) {
			array2 = new ProcessCell[process.scope().numVariables()];
			array1[pid] = array2;
		}
		result = array2[vid];
		if (result == null) {
			result = new ProcessCell(variable);
			array2[vid] = result;
		}
		return result;

	}

	public LocalCell dynamicLocalVariable(LocalVariableIF variable,
			int stackIndex) {
		ModelIF model = variable.model();
		int mid = model.id();
		LocalScopeIF scope = variable.scope();
		int scopeId = scope.localId();
		FunctionIF function = scope.function();
		int numScopes = function.numScopes();
		ProcessIF process = function.process();
		int pid = process.pid();
		int fid = function.idInScope();
		int numLocals = scope.numVariables();
		int vid = variable.idInScope();

		assert scopeId < numScopes;
		
		Vector<LocalCell[][][][]> localVector1 = null;

		if (mid < localVector.size()) {
			localVector1 = localVector.get(mid);
		} else {
			localVector.setSize(mid + 1);
		}
		if (localVector1 == null) {
			localVector1 = new Vector<LocalCell[][][][]>();
			localVector.set(mid, localVector1);
		}

		LocalCell[][][][] localArray1 = null;

		if (stackIndex < localVector1.size()) {
			localArray1 = localVector1.get(stackIndex);
		} else {
			localVector1.setSize(stackIndex + 1);
		}
		if (localArray1 == null) {
			localArray1 = new LocalCell[model.numProcs()][][][];
			localVector1.set(stackIndex, localArray1);
		}

		LocalCell[][][] localArray2 = localArray1[pid];

		if (localArray2 == null) {
			localArray2 = new LocalCell[process.scope().numFunctions()][][];
			localArray1[pid] = localArray2;
		}

		LocalCell[][] localArray3 = localArray2[fid];

		if (localArray3 == null) {
			localArray3 = new LocalCell[numScopes][];
			localArray2[fid] = localArray3;
		}

		LocalCell[] localArray4 = localArray3[scopeId];

		if (localArray4 == null) {
			localArray4 = new LocalCell[numLocals];
			localArray3[scopeId] = localArray4;
		}

		LocalCell result = localArray4[vid];

		if (result == null) {
			result = new LocalCell(variable, stackIndex);
			localArray4[vid] = result;
		}
		return result;
	}

	public HeapCell dynamicHeapVariable(ProcessIF process, int heapIndex) {
		ModelIF model = process.model();
		int mid = model.id();
		int pid = process.pid();
		int numProcs = model.numProcs();

		Vector<HeapCell[]> heap1 = null;

		if (mid < heapVector.size()) {
			heap1 = heapVector.get(mid);
		} else {
			heapVector.setSize(mid + 1);
		}
		if (heap1 == null) {
			heap1 = new Vector<HeapCell[]>();
			heapVector.set(mid, heap1);
		}

		HeapCell[] heap2 = null;

		if (heapIndex < heap1.size()) {
			heap2 = heap1.get(heapIndex);
		} else {
			heap1.setSize(heapIndex + 1);
		}
		if (heap2 == null) {
			heap2 = new HeapCell[numProcs];
			heap1.set(heapIndex, heap2);
		}

		HeapCell result = heap2[pid];

		if (result == null) {
			result = new HeapCell(process, heapIndex);
			heap2[pid] = result;
		}
		return result;
	}

}