FunctionDeclarationNode.java

package edu.udel.cis.vsl.tass.ast.impl.declaration;

import java.io.PrintWriter;
import java.util.NoSuchElementException;

import edu.udel.cis.vsl.tass.ast.IF.ASTNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.AbstractSyntaxTreeIF;
import edu.udel.cis.vsl.tass.ast.IF.IdentifierNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.SequenceNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.FormalVariableDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.declaration.FunctionDeclarationNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.expression.PureExpressionNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.statement.BlockNodeIF;
import edu.udel.cis.vsl.tass.ast.IF.type.TypeNodeIF;
import edu.udel.cis.vsl.tass.ast.impl.ASTNode;

public class FunctionDeclarationNode extends ASTNode implements FunctionDeclarationNodeIF {

	private IdentifierNodeIF identifier;
	private TypeNodeIF outputType;
	private SequenceNodeIF<FormalVariableDeclarationNodeIF> formals;
	private BlockNodeIF body;
	private FunctionDeclarationNodeIF definition;
	private boolean isDefinition;
	private PureExpressionNodeIF guard;
	
	public FunctionDeclarationNode(long id) {
		super(id);
	}
	
	public FunctionDeclarationNode(long id,
								   IdentifierNodeIF identifier,
								   TypeNodeIF outputType,
								   SequenceNodeIF<FormalVariableDeclarationNodeIF> formals,
								   BlockNodeIF body) {
		super(id);
		this.identifier = identifier;
		this.outputType = outputType;
		this.formals = formals;
		this.body = body;
	}

	@Override
	public IdentifierNodeIF identifier() {
		return identifier;
	}

	@Override
	public TypeNodeIF outputType() {
		return outputType;
	}

	@Override
	public SequenceNodeIF<FormalVariableDeclarationNodeIF> formals() {
		return formals;
	}

	@Override
	public FunctionDeclarationNodeIF definition() {
		return definition;
	}

	@Override
	public boolean isDefinition() {
		return isDefinition;
	}

	@Override
	public BlockNodeIF body() {
		return body;
	}

	@Override
	public void setIdentifier(IdentifierNodeIF identifier) {
		this.identifier = identifier;
	}

	@Override
	public void setOutputType(TypeNodeIF outputType) {
		this.outputType = outputType;
	}

	@Override
	public void setFormals(
			SequenceNodeIF<FormalVariableDeclarationNodeIF> formals) {
		this.formals = formals;
	}

	@Override
	public void setDefinition(FunctionDeclarationNodeIF definition) {
		this.definition = definition;
	}

	@Override
	public void setIsDefinition(boolean isDefinition) {
		this.isDefinition = isDefinition;
	}

	@Override
	public void setBody(BlockNodeIF body) {
		this.body = body;
	}
	
	@Override
	public int numChildren() {
		return 4;
	}
	
	/**
	 * Children are: 
	 * 0 : Name 
	 * 1 : Output Type 
	 * 2 : Formals 
	 * 3 : Body
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void setChild(int i, ASTNodeIF child) throws NoSuchElementException {
		switch (i) {
		case 0:
			this.identifier = (IdentifierNodeIF) child;
			break;
		case 1:
			this.outputType = (TypeNodeIF) child;
			break;
		case 2:
			// Java can't type check generics, so check that the child
			// has the correct type.
			for (int j = 0; j < child.numChildren(); j++) {
				assert child.child(0) instanceof FormalVariableDeclarationNodeIF;
			}
			this.formals = (SequenceNodeIF<FormalVariableDeclarationNodeIF>) child;
			break;
		case 3:
			this.body = (BlockNodeIF) child;
			break;
		default:
			throw new NoSuchElementException("Node " + id()
					+ " does not have a child with index " + i + ".");
		}
	}

	@Override
	public ASTNodeIF child(int index) throws NoSuchElementException {
		switch (index) {
		case 0:
			return identifier;
		case 1:
			return outputType;
		case 2:
			return formals;
		case 3:
			return body;
		default:
			throw new NoSuchElementException("Node " + id()
					+ " does not have a child with index " + index + ".");
		}
	}

	@Override
	protected String nodeType() {
		return "Function Declaration Node";
	}

	@Override
	public String toString() {
		return super.toString()
			+ " isDefinition: " + isDefinition;
	}

	@Override
	public void toXml(String prefix, PrintWriter out,AbstractSyntaxTreeIF ast) {
		super.toXml(prefix,out,ast);
		
		out.println(prefix+"<fdn:uniqueFunctionId>"+id()+"</fdn:uniqueFunctionId>");

		out.println(prefix+"<fdn:name>");
		identifier.toXml(prefix+"  ",out,ast);
		out.println(prefix+"</fdn:name>");

		out.println(prefix+"<fdn:outputType>");
		outputType.toXml(prefix+"  ",out,ast);
		out.println("</fdn:outputType>");

		out.println(prefix+"<fdn:formals>");
		formals.toXml(prefix+"  ",out,ast);
		out.println(prefix+"</fdn:formals>");

		if (!isDefinition) {
			assert definition != null;
			out.println(prefix+"<fdn:functionRef>"+
						definition.id()+
						"</fdn:functionRef>");
		} else {
			assert body != null;
			out.println(prefix+"<fdn:body>");
			body.toXml(prefix+"  ",out,ast);
			out.println(prefix+"</fdn:body>");
		}
	}

	@Override
	public PureExpressionNodeIF guard() {
		return guard;
	}

	@Override
	public void setGuard(PureExpressionNodeIF guard) {
		this.guard = guard;
	}
						
}