LibfooExecutor.java

package edu.udel.cis.vsl.tass.library.libfoo;

import edu.udel.cis.vsl.tass.dynamic.IF.DynamicException;
import edu.udel.cis.vsl.tass.dynamic.IF.cell.ModelCellIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ArrayElementReferenceValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ArrayValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.RecordElementReferenceValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.RecordValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ReferenceValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.ValueIF;
import edu.udel.cis.vsl.tass.dynamic.IF.value.VariableReferenceValueIF;
import edu.udel.cis.vsl.tass.model.IF.ProcessIF;
import edu.udel.cis.vsl.tass.model.IF.expression.ExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.LHSExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.expression.VariableExpressionIF;
import edu.udel.cis.vsl.tass.model.IF.location.LocationIF;
import edu.udel.cis.vsl.tass.model.IF.statement.InvocationStatementIF;
import edu.udel.cis.vsl.tass.semantics.IF.EnvironmentIF;
import edu.udel.cis.vsl.tass.semantics.IF.EvaluatorIF;
import edu.udel.cis.vsl.tass.semantics.IF.ExecutionException;
import edu.udel.cis.vsl.tass.semantics.IF.ExecutionProblem;
import edu.udel.cis.vsl.tass.semantics.IF.ExecutorIF;
import edu.udel.cis.vsl.tass.semantics.IF.LibraryExecutorIF;
import edu.udel.cis.vsl.tass.semantics.IF.ExecutionProblem.Certainty;
import edu.udel.cis.vsl.tass.semantics.IF.ExecutionProblem.ErrorKind;
import edu.udel.cis.vsl.tass.util.Sourceable;

public class LibfooExecutor implements LibraryExecutorIF {

	private ExecutorIF executor;

	public LibfooExecutor(ExecutorIF executor, EvaluatorIF evaluator) {
		this.executor = executor;
	}

	@Override
	public boolean containsFunction(String name) {
		if (name.equals("FOO_f")) {
			return true;
		}
		return false;
	}

	@Override
	public void execute(EnvironmentIF environment,
			InvocationStatementIF invocation) throws ExecutionException {
		LocationIF targetLocation = invocation.targetLocation();
		ProcessIF process = invocation.process();
		EvaluatorIF evaluator = executor.evaluator();
		String name = invocation.callee().name();
		if (name.equals("FOO_f")) {
			// Execute f. This is a constant function. It returns 100 regardless
			// of
			// the formal parameter value.
			LHSExpressionIF lhs = invocation.lhs();
			if (lhs != null && lhs instanceof VariableExpressionIF) {
				assignValue(environment, lhs, evaluator.dynamicFactory()
						.symbolicValue(100), evaluator);
			}
		} else if (name.equals("square")) {
			// Execute square. This returns the square of the parameter.
			LHSExpressionIF lhs = invocation.lhs();
			ExpressionIF arg = invocation.arguments()[0];
			ValueIF argValue = executor.evaluator().evaluate(environment, arg);
			if (lhs != null && lhs instanceof VariableExpressionIF) {
				assignValue(environment, lhs, evaluator.dynamicFactory()
						.multiply(environment.getAssumption(), argValue,
								argValue), evaluator);
			}
		} else if (name.equals("do_nothing")) {
			// Do nothing. This is just here to test the system function guards.
		} else {
			throw new ExecutionException(invocation, ErrorKind.LIBRARY,
					Certainty.MAYBE, "Unknown function: " + name);
		}
		environment.setLocation(process, targetLocation);
	}

	private void assignValue(EnvironmentIF environment,
			ReferenceValueIF reference, ValueIF value, EvaluatorIF evaluator,
			Sourceable sourceable) throws ExecutionProblem {
		ValueIF assumption = environment.getAssumption();

		try {
			if (reference instanceof VariableReferenceValueIF) {
				environment.setValue(
						(ModelCellIF) ((VariableReferenceValueIF) reference)
								.variable(), value);
			} else if (reference instanceof ArrayElementReferenceValueIF) {
				ArrayElementReferenceValueIF elementReference = (ArrayElementReferenceValueIF) reference;
				ReferenceValueIF parent = elementReference.parent();
				ArrayValueIF parentValue = (ArrayValueIF) evaluator
						.dereference(environment, parent, sourceable);
				ValueIF index = elementReference.index();
				ValueIF newParentValue = evaluator.dynamicFactory().arrayWrite(
						assumption, parentValue, index, value);

				assignValue(environment, parent, newParentValue, evaluator,
						sourceable);
			} else if (reference instanceof RecordElementReferenceValueIF) {
				RecordElementReferenceValueIF elementReference = (RecordElementReferenceValueIF) reference;
				ReferenceValueIF parent = elementReference.parent();
				RecordValueIF parentValue = (RecordValueIF) evaluator
						.dereference(environment, parent, sourceable);
				int fieldIndex = elementReference.fieldIndex();
				ValueIF newParentValue = evaluator
						.dynamicFactory()
						.recordWrite(assumption, parentValue, fieldIndex, value);

				assignValue(environment, parent, newParentValue, evaluator,
						sourceable);
			} else {
				throw new IllegalArgumentException("Unknown reference type:\n"
						+ reference);
			}
		} catch (DynamicException error) {
			throw new ExecutionProblem(error, Certainty.NONE);
		}
	}

	private void assignValue(EnvironmentIF environment, LHSExpressionIF lhs,
			ValueIF value, EvaluatorIF evaluator) throws ExecutionException {
		try {
			ReferenceValueIF reference = evaluator.referenceValue(environment,
					lhs);

			assignValue(environment, reference, value, evaluator, lhs);
		} catch (ExecutionException error) {
			throw error;
		} catch (ExecutionProblem error) {
			throw new ExecutionException(lhs, error);
		}
	}

	@Override
	public String name() {
		return "libfoo";
	}

	@Override
	public void initialize(EnvironmentIF environment) throws ExecutionException {
	}

	@Override
	public void wrapUp(EnvironmentIF environment) throws ExecutionException {
	}

}