All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.xsemantics.runtime.RuleEnvironment Maven / Gradle / Ivy

There is a newer version: 1.12.1
Show newest version
/**
 * 
 */
package it.xsemantics.runtime;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.xtext.xbase.lib.Functions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;

/**
 * Implements the environment for a typing judgment
 * 
 * @author Lorenzo Bettini
 * 
 */
public class RuleEnvironment {

	protected Map environment = new HashMap();

	protected RuleEnvironment next = null;

	public RuleEnvironment(RuleEnvironment e) {
		if (e == null) {
			environment = new HashMap();
		} else {
			environment = new HashMap(e.getEnvironment());
		}
	}

	public RuleEnvironment() {
	}

	public RuleEnvironment(RuleEnvironmentEntry environmentEntry) {
		add(environmentEntry);
	}

	public RuleEnvironment(RuleEnvironment firstComponent,
			RuleEnvironment secondComponent) {
		this(firstComponent);
		environment.putAll(secondComponent.getEnvironment());
	}

	public Map getEnvironment() {
		return environment;
	}

	public RuleEnvironment getNext() {
		return next;
	}

	public void setNext(RuleEnvironment next) {
		this.next = next;
	}

	public void setNext(RuleEnvironmentEntry runtimeEnvironmentEntry) {
		RuleEnvironment next2 = new RuleEnvironment();
		setNext(next2);
		next2.add(runtimeEnvironmentEntry);
	}

	public void add(RuleEnvironmentEntry runtimeEnvironmentEntry) {
		add(runtimeEnvironmentEntry.getLeft(),
				runtimeEnvironmentEntry.getRight());
	}

	public boolean add(Object o1, Object o2) {
		return add(o1, o2, false);
	}

	/**
	 * If checkExist is true, before inserting, also checks that there is no
	 * other statement in the environment with left equal to the passed
	 * typingStatement left (otherwise returns false=
	 * 
	 * @param typingStatement
	 * @param checkExist
	 * @return
	 */
	public boolean add(Object o1, Object o2, boolean checkExist) {
		if (checkExist && environment.containsKey(o1)) {
			return false;
		}

		environment.put(o1, o2);

		return true;
	}

	/**
	 * If the key is not found in this environment tries recursively with the
	 * next one
	 * 
	 * @param key
	 * @return
	 */
	public Object get(Object key) {
		Object object = environment.get(key);
		if (object == null && next != null) {
			return next.get(key);
		}
		return object;
	}

	/**
	 * Adds all the entries of the passed environment to this one (existing
	 * mappings for the same key will be overwritten).
	 * @param ruleEnvironment
	 */
	public void increment(RuleEnvironment ruleEnvironment) {
		if (ruleEnvironment != null) {
			environment.putAll(ruleEnvironment.getEnvironment());
		}
	}

	/**
	 * Same as add
	 * @param runtimeEnvironmentEntry
	 */
	public void increment(RuleEnvironmentEntry runtimeEnvironmentEntry) {
		increment(runtimeEnvironmentEntry.getLeft(),
				runtimeEnvironmentEntry.getRight());
	}
	
	/**
	 * Same as add
	 * @param o1
	 * @param o2
	 */
	public void increment(Object o1, Object o2) {
		add(o1, o2);
	}

	/**
	 * Removes all the mapping that have as keys the keys of the
	 * passed environment.
	 * @param ruleEnvironment
	 */
	public void decrement(RuleEnvironment ruleEnvironment) {
		if (ruleEnvironment != null) {
			environment.keySet().removeAll(
				ruleEnvironment.getEnvironment().keySet());
		}
	}


	/**
	 * Remove the mapping with the passed object as key
	 * @param o1
	 */
	public void decrement(Object o1) {
		environment.remove(o1);
	}

	/**
	 * Adds all the entries of the passed environment, but it returns false
	 * if there are mappings in the passed environment with the same key
	 * of the current environment; the current environment is NOT restored
	 * to its original state in case of failure.
	 * @param ruleEnvironment if null it's succeeds
	 * @return
	 */
	public boolean union(RuleEnvironment ruleEnvironment) {
		if (ruleEnvironment == null) {
			return true;
		}
		
		Set> entrySet = ruleEnvironment
				.getEnvironment().entrySet();
		for (Entry entry : entrySet) {
			if (!union(entry.getKey(), entry.getValue())) {
				return false;
			}
		}
		return true;
	}

	public boolean union(RuleEnvironmentEntry runtimeEnvironmentEntry) {
		return union(runtimeEnvironmentEntry.getLeft(),
				runtimeEnvironmentEntry.getRight());
	}

	public boolean union(Object o1, Object o2) {
		return add(o1, o2, true);
	}

	@Override
	public String toString() {
		if (isEmpty()) {
			return "";
		}
		
		StringBuilder buffer = new StringBuilder(
			IterableExtensions.join(
				IterableExtensions.map(getEnvironment().entrySet(), 
						new Functions.Function1, String>() {
							@Override
							public String apply(Map.Entry p) {
								return p.getKey() + " -> " + p.getValue();
							}
						}
				),
				", "
			)
		);
		
		if (next != null) {
			buffer.append(" :: [");
			buffer.append(next.toString());
			buffer.append("]");
		}
		return buffer.toString();
	}

	/**
	 * @since 1.5
	 */
	public boolean isEmpty() {
		return environment.isEmpty();
	}

	/**
	 * @since 1.5
	 */
	public int size() {
		return environment.size();
	}

	/**
	 * @since 1.5
	 */
	public void clear() {
		environment.clear();
	}

	/**
	 * @since 1.5
	 */
	public Set keySet() {
		return environment.keySet();
	}

	/**
	 * @since 1.5
	 */
	public Collection values() {
		return environment.values();
	}

	/**
	 * @since 1.5
	 */
	public Set> entrySet() {
		return environment.entrySet();
	}

	/**
	 * If the passed object is a RuleEnvironment then returns equals on the
	 * two {@link Map} contained objects.
	 * 
	 * @since 1.5
	 */
	@Override
	public boolean equals(Object o) {
		if (o instanceof RuleEnvironment) {
			return environment.equals(((RuleEnvironment) o).getEnvironment());
		}
		return super.equals(o);
	}

	/**
	 * @since 1.5
	 */
	@Override
	public int hashCode() {
		return environment.hashCode();
	}

}