SimpleScope.java

package edu.udel.cis.vsl.abc.front.common.astgen;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode;
import edu.udel.cis.vsl.abc.front.c.parse.ScopeSymbols;

/**
 * A very simple notion of lexical scope used only in the process of translating
 * from an ANTLR tree to an AST. The scopes form a rooted tree.
 * 
 * @author siegel
 * 
 */
public class SimpleScope {

	private SimpleScope parent;

	private boolean isFunctionScope;

	/**
	 * Mapping from typedef names to corresponding type node in typedef for all
	 * typedefs in this scope.
	 */
	private Map<String, TypeNode> typedefMap = new HashMap<String, TypeNode>();

	private Set<String> enumerationConstants = new HashSet<>();

	/**
	 * Constructs new scope with specified parent scope.
	 * 
	 * @param parent
	 *            the parent scope, i.e., the scope immediately containing this
	 *            scope, or <code>null</code> if this is the root scope
	 * @param isFunctionScope
	 *            is this a function scope, i.e., the outermost scope of the
	 *            function body
	 */
	public SimpleScope(SimpleScope parent, boolean isFunctionScope) {
		this.parent = parent;
		this.isFunctionScope = isFunctionScope;
	}

	/**
	 * Constructs a new non-function scope with specified parent scope.
	 * 
	 * @param parent
	 *            the parent scope of the new scope
	 */
	public SimpleScope(SimpleScope parent) {
		this(parent, false);
	}

	public void addEnumerationConstant(String name) {
		this.enumerationConstants.add(name);
	}

	/**
	 * Declares that there is a typedef in this scope with given name and type
	 * node.
	 * 
	 * @param name
	 *            the typedef name
	 * @param node
	 *            the node representing the type in the typedef
	 */
	public void putMapping(String name, TypeNode node) {
		typedefMap.put(name, node);
	}

	/**
	 * Returns the type node in the typedef in this scope with the given name,
	 * or <code>null</code> if there is no typedef in this scope with that name
	 * 
	 * @param name
	 *            the typedef name
	 * @return the type node in the typedef with that name
	 */
	public TypeNode getReferencedType(String name) {
		return typedefMap.get(name);
	}

	public Set<String> getTypes() {
		return typedefMap.keySet();
	}

	public Set<String> getEnumConstants() {
		return this.enumerationConstants;
	}

	/**
	 * Returns the parent scope of this scope, i.e., the scope immediately
	 * containing this scope, or <code>null</code> if this is the root scope
	 * 
	 * @return the parent scope or <code>null</code>
	 */
	public SimpleScope getParent() {
		return parent;
	}

	/**
	 * Is this a function scope, i.e., the outermost scope of a function body?
	 * 
	 * @return <code>true</code> iff this is a function scope, else
	 *         <code>false</code>
	 */
	public boolean isFunctionScope() {
		return isFunctionScope;
	}

	public Stack<ScopeSymbols> getScopeSymbolStack() {
		Stack<ScopeSymbols> stack = new Stack<>();
		SimpleScope current = this;

		while (current != null) {
			Set<String> myTypes = current.getTypes();
			Set<String> myEnumConsts = current.getEnumConstants();

			stack.add(new ScopeSymbols(myTypes, myEnumConsts));
			current = current.getParent();
		}
		return stack;
	}

	/**
	 * is the given name declared as an enumeration constant in a visible scope
	 * ?
	 * 
	 * @param name
	 *            the name that is to be checked
	 * @return true iff the given name is declared as an enumeration constant in
	 *         some reachable scope.
	 */
	public boolean isEnumerationConstant(String name) {
		if (this.enumerationConstants.contains(name))
			return true;
		if (parent != null)
			return parent.isEnumerationConstant(name);
		return false;
	}
}