Process.java

package edu.udel.cis.vsl.tass.model.impl;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.Vector;

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.SyntaxException;
import edu.udel.cis.vsl.tass.model.IF.location.LocationIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF;
import edu.udel.cis.vsl.tass.model.IF.type.TypeIF.TypeKind;
import edu.udel.cis.vsl.tass.model.IF.variable.ProcessVariableIF;
import edu.udel.cis.vsl.tass.model.IF.variable.VariableIF;
import edu.udel.cis.vsl.tass.model.impl.scope.ProcessScope;

public class Process implements ProcessIF {

	private ProcessScope scope;

	private ModelIF model;

	private int pid;

	private FunctionIF mainFunction = null;

	public Process(ModelIF model, int pid) {
		if (model == null)
			throw new NullPointerException("null model");
		this.model = model;
		this.pid = pid;
		this.scope = new ProcessScope(this);
	}

	public int pid() {
		return pid;
	}

	public ModelIF model() {
		return model;
	}

	public void addFunction(FunctionIF function) throws SyntaxException {
		scope.addFunction(function);
	}

	public void addProcessVariable(ProcessVariableIF variable)
			throws SyntaxException {
		scope.addVariable(variable);
	}

	public Collection<LocationIF> locationsWithLabel(String label) {
		Vector<LocationIF> result = new Vector<LocationIF>();

		for (FunctionIF function : scope.functions()) {
			result.addAll(function.locationsWithLabel(label));
		}
		return result;
	}

	public void complete() throws SyntaxException {
		scope.complete();
		for (VariableIF variable : scope.variables()) {
			if (variable.type().kind() == TypeKind.ARRAY) {
				if (variable.dimensionExpressions() == null) {
					throw new SyntaxException(variable,
							"Need to set dimensions of this array variable");
				}
			}
		}
		if (mainFunction == null)
			throw new SyntaxException("Process " + this
					+ " does not have main function");
	}

	public void setMainFunction(FunctionIF function) throws SyntaxException {
		if (function == null)
			throw new NullPointerException("null function");
		if (!this.equals(function.process()))
			throw new IllegalArgumentException(
					"Function belongs to other process: " + function.process()
							+ ", not this process " + this);
		if (function.numFormals() == 2) {
			if (function.formal(0).type().kind() != TypeIF.TypeKind.INTEGER
					|| function.formal(1).type().kind() != TypeIF.TypeKind.ARRAY)
				throw new SyntaxException(
						function,
						"Main function can either have no formal parameters or exactly two, an int and a character pointer array.");
		} else if (function.numFormals() != 0)
			throw new SyntaxException(
					function,
					"Main function can either have no formal parameters or exactly two, an int and a character pointer array.");
		if (function.returnType().kind() != TypeIF.TypeKind.VOID
				&& function.returnType().kind() != TypeIF.TypeKind.INTEGER)
			throw new SyntaxException(function,
					"Return type of main function must be void or int, not "
							+ function.returnType());
		mainFunction = function;
	}

	public FunctionIF mainFunction() {
		return mainFunction;
	}

	public void print(String prefix, PrintWriter out) {
		print(prefix, out, false);
	}

	public void print(String prefix, PrintWriter out, boolean withSource) {
		Collection<VariableIF> variables = scope.variables();
		Collection<FunctionIF> functions = scope.functions();

		out.println(prefix + "begin process " + pid);
		out.println(prefix + "| main function : " + mainFunction() + ";");
		if (!variables.isEmpty()) {
			out.println(prefix + "| begin process variables");
			for (VariableIF variable : variables) {
				out.println(prefix + "| | " + variable + " : "
						+ variable.decl() + ";");
				out.println(prefix + "| | | " + variable.getSource());
			}
			out.println(prefix + "| end process variables;");
		}
		for (FunctionIF function : functions) {
			((Function) function).print(prefix + "| ", out, withSource);
		}
		out.println(prefix + "end process " + pid + ";");
		out.flush();
	}

	public String toString() {
		return "process " + pid + " of model " + model;
	}

	@Override
	public ProcessScope scope() {
		return scope;
	}
}