LinkTable.java

/*
 * #%L
 * prolobjectlink-jpi-jtrolog
 * %%
 * Copyright (C) 2012 - 2018 WorkLogic Project
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
 * #L%
 */
package jTrolog.engine;

import jTrolog.terms.Term;

/**
 * @author ivar.orstavik@hist.no
 */
class LinkTable {

	private int depth = 8;
	private int width = Engine.STARTUP_STACK_SIZE;

	// Links are stored in a set of two dimensional arrays.
	// The terms and their ctx id are stored as individual dimensions.
	// The negative duplicates are used for terms with ctx id that are generated
	// by library methods.
	private Term[][] linkToTerm = new Term[depth][width];
	private int[][] linkToCtx = new int[depth][width];

	LinkTable() {
		for (int i = 0; i < depth; i++) {
			linkToTerm[i] = new Term[width];
			linkToCtx[i] = new int[width];
		}
	}

	final Term getTerm(final int vNr, final int vCtx) {
		return vNr >= depth || vCtx >= width ? null : linkToTerm[vNr][vCtx];
	}

	final int getCtx(final int vNr, final int vCtx) {
		return linkToCtx[vNr][vCtx];
	}

	final void put(final int vNr, int vCtx, final Term link, final int linkCtx) {
		if (vNr >= depth)
			expandLinkTableDepth(vNr * 2);

		// mark vNr and vCtx under the given execCtx
		linkToTerm[vNr][vCtx] = link;
		linkToCtx[vNr][vCtx] = linkCtx;
	}

	private void expandLinkTableDepth(final int newSize) {
		linkToTerm = LinkTable.expandMap(linkToTerm, newSize);
		linkToCtx = LinkTable.expandMap(linkToCtx, newSize);
		for (int i = depth; i < newSize; i++) {
			linkToTerm[i] = new Term[width];
			linkToCtx[i] = new int[width];
		}
		depth = newSize;
	}

	final void reset(int vNr, int vCtx) {
		linkToTerm[vNr][vCtx] = null;
		linkToCtx[vNr][vCtx] = 0;
	}

	final void doubleWidth(final int newSize) {
		for (int i = 0; i < depth; i++) {
			linkToTerm[i] = LinkTable.expandArray(linkToTerm[i], newSize);
			linkToCtx[i] = LinkTable.expandArray(linkToCtx[i], newSize);
		}
		width = newSize;
	}

	public int getWidth() {
		return width;
	}

	static int[][] expandMap(final int[][] array, final int newSize) {
		int[][] newArray = new int[newSize][];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	static int[] expandArray(int[] array, final int newSize) {
		int[] newArray = new int[newSize];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	static Term[][] expandMap(final Term[][] array, final int newSize) {
		Term[][] newArray = new Term[newSize][];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

	static Term[] expandArray(Term[] array, final int newSize) {
		Term[] newArray = new Term[newSize];
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}
}