Skip to content
LASTFactory.java 36.5 KiB
Newer Older
package edg;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.function.BiConsumer;


import edg.LASTBuilder.Where;
import edg.graph.LAST;
import edg.graph.Node;

public abstract class LASTFactory
{
	private LAST last;
	private final Stack<Branch> branches = new Stack<Branch>();
	final protected Map<String,Integer> currentLabels = new HashMap<>();
	final protected Map<String,List<Integer>> unresolvedLabels = new HashMap<>();
	
	private <R> void processElements(R[] elements)
	{	
		for (int elementIndex = 0; elementIndex < elements.length; elementIndex++)
		{
			final R element = elements[elementIndex];
			this.processElement(element, elementIndex + 1, elements.length);
		}
	}
	private void processElement(Object element, int index, int length)
	{
		final Map<String, Object> info = new HashMap<>();
		final Branch parent = this.branches.isEmpty() ? null : this.branches.get(this.branches.size() - 1);
		if (parent != null)
		{
			parent.setIndex(index);
			parent.setLength(length);
		}

		final boolean isPatternZone = this.isPatternZone(this.branches);
		info.put("ancestors", this.branches);
		info.put("parent", parent);
		info.put("patternZone", isPatternZone);

		this.processElement(element, info);
	}
	protected abstract void processElement(Object element, Map<String, Object> info);

	protected <R> LAST createLAST(Iterable<R> classes, LDASTNodeInfo info)
	{
		final R[] classes0 = this.getArray(classes);
		return this.createLAST(true, classes0, info);
	}
	protected <R> LAST createLAST(boolean generateArcs, Iterable<R> classes, LDASTNodeInfo info)
	{
		final R[] classes0 = this.getArray(classes);
		return this.createLAST(generateArcs, classes0, info);
	}
	protected <R> LAST createLAST(R[] classes, LDASTNodeInfo info)
	{
		return this.createLAST(true, classes, info);
	}
	protected <R> LAST createLAST(boolean generateArcs, R[] classes, LDASTNodeInfo info)
	{
		this.branches.clear();
		this.last = LASTBuilder.createLAST(info);
		this.processElements(classes);

		return this.last;
	}
	protected <R> void addModule(String name, Iterable<R> members, LDASTNodeInfo info)
	{
		final R[] members0 = this.getArray(members);
		this.addModule(name, members0, info);
	}
	protected <R> void addModule(String name, R[] members, LDASTNodeInfo info)
	{
		final int moduleId = LASTBuilder.addModule(this.last, name, info);

		this.branches.push(new Branch(moduleId, Node.Type.Module, info));
		this.processElements(members);
		this.branches.pop();
	}

	protected <R> void addRoutine(String name, Iterable<R> clauses, LDASTNodeInfo info)
	{
		final R[] clauses0 = this.getArray(clauses);
		this.addRoutine(name, clauses0, false, info);
	protected <R> void addRoutine(String name, Iterable<R> clauses, boolean anonymous, LDASTNodeInfo info)
	{
		final R[] clauses0 = this.getArray(clauses);
		this.addRoutine(name, clauses0, anonymous, info);
	}
	protected <R> void addRoutine(String name, R[] clauses, boolean anonymous, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final Where where = parent.getWhere();
		final int routineId = LASTBuilder.addRoutine(this.last, parentId, where, name, anonymous, info);

		Node.Type routineType = anonymous ? Node.Type.AnonymousRoutine : Node.Type.Routine;
		this.branches.push(new Branch(routineId, routineType, info));
		this.processElements(clauses);
		this.branches.pop();
	}

	protected <R, S, T> void addClause(Iterable<R> parameters, S guard, T body, LDASTNodeInfo info)
	{
		final R[] parameters0 = this.getArray(parameters);
		this.addClause(parameters0, guard, body, info);
	}
	protected <R, S, T> void addClause(R[] parameters, S guard, T body, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final int clauseId = LASTBuilder.addClause(this.last, parentId, info);
		final Branch branch = this.branches.push(new Branch(clauseId, Node.Type.Clause, info));

		currentLabels.clear(); // Clear Label list when generating a Clause
		
		branch.setWhere(Where.Parameters);
		this.processElements(parameters);
		branch.setWhere(Where.Guard);
		if (guard != null)
			this.processElement(guard, 1, 1);
		branch.setWhere(Where.Body);
		if (body != null)
			this.processElement(body, 1, 1);
		this.branches.pop();
	}
	protected <R, S, T> void addClause(Iterable<R> parameters, S guard, Iterable<T> expressions, LDASTNodeInfo info)
	{
		final R[] parameters0 = this.getArray(parameters);
		final T[] expressions0 = this.getArray(expressions);
		this.addClause(parameters0, guard, expressions0, info);
	}
	protected <R, S, T> void addClause(R[] parameters, S guard, T[] expressions, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();

		boolean previousLockState = this.last.getLockState();

		final int clauseId = LASTBuilder.addClause(this.last, parentId, info);
		final Branch branch = this.branches.push(new Branch(clauseId, Node.Type.Clause, info));

		branch.setWhere(Where.ParameterIn);
		branch.setWhere(Where.Parameters);
		this.processElements(parameters);
		branch.setWhere(Where.ParameterOut);
		branch.setWhere(Where.Guard);
		if (guard != null)
			this.processElement(guard, 1, 1);
		branch.setWhere(Where.Body);
		this.processElements(expressions);
		this.branches.pop();

		this.last.setLockState(previousLockState);
	}

	protected void addVariable(String name, boolean declaration, boolean definition, boolean use, boolean global, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final Where where = parent.getWhere();

		LASTBuilder.addVariable(this.last, parentId, where, name, declaration, definition, use, global, info);
	}

	protected void addVariable(String name, boolean declaration, boolean definition, boolean use, boolean global, boolean shadowed, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final Where where = parent.getWhere();

		LASTBuilder.addVariable(this.last, parentId, where, name, declaration, definition, use, global, shadowed, info);
	}

	protected void addLiteral(String value, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final Where where = parent.getWhere();

		LASTBuilder.addLiteral(this.last, parentId, where, value, info);
	}
	protected <R, S> void addEquality(R left, S right, LDASTNodeInfo info)
	{
		final Branch parent = this.branches.peek();
		final int parentId = parent.getNodeId();
		final Where where = parent.getWhere();
		final int equalityId = LASTBuilder.addEquality(this.last, parentId, where, info);

		boolean previousLockState = last.getLockState();
		this.last.lockSDGid();

		this.branches.push(new Branch(equalityId, Node.Type.Equality, info));
		this.processElement(left, 1, 2);
Loading
Loading full blame...