view src/nabble/naml/compiler/RunStateImpl.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.naml.compiler;

import fschmidt.util.java.ArrayStack;
import fschmidt.util.java.Stack;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


final class RunStateImpl implements RunState {
	private final Stack<Object> stack = new ArrayStack<Object>();
	private final Template template;
	private final int callDepth;
	private final Map<String,String> args = new HashMap<String,String>();
	private final Map<String,Object> namespaceMap = new HashMap<String,Object>();
	private final Map<Class,List<JavaNamespace>> extensionMap;
	private Encoder encoder;
	private final Map<Macro,Stack<Map<String,String>>> varsMap = new HashMap<Macro,Stack<Map<String,String>>>();

	RunStateImpl(Template template,int callDepth,Encoder encoder) {
		this.template = template;
		this.callDepth = callDepth;
		this.encoder = encoder;
		this.extensionMap = template.program().extensionMap();
	}

	public Template template() {
		return template;
	}

	public Program program() {
		return template.program();
	}

	public int callDepth() {
		return callDepth;
	}

	public void putArg(String name,String value) {
		args.put(name,value);
	}

	public String getArg(String name) {
		return args.get(name);
	}

	public Object getNamespace(String key) {
		return namespaceMap.get(key);
	}

	public String saveNamespace(Object namespace) {
		String key = namespace.toString();
		namespaceMap.put(key,namespace);
		return key;
	}

	public Object getFromStack(int i) {
		if( i < 0 )
			i = stack.size() + i;
		return stack.get(i);
	}

	public int push(Object scope) {
		return push(stack,extensionMap,scope);
	}

	static int push(Stack<Object> stack,Map<Class,List<JavaNamespace>> extensionMap,Object scope) {
		stack.push(scope);
		int pushed = 1;
		List<JavaNamespace> extensions = extensionMap.get(scope.getClass());
		if( extensions == null )
			return 1;
		for( JavaNamespace extension : extensions ) {
			try {
				stack.push(extension.extensionConstructor.newInstance(scope));
			} catch(InstantiationException e) {
				throw new TemplateRuntimeException(e);
			} catch(IllegalAccessException e) {
				throw new TemplateRuntimeException(e);
			} catch(InvocationTargetException e) {
				throw Compiler.interpFix(e);
			}
		}
		return 1 + extensions.size();
	}

	public void pop(int n) {
		pop(stack,n);
	}

	static void pop(Stack<Object> stack,int n) {
		for( ; n > 0; n-- ) {
			stack.pop();
		}
	}

	public boolean hasNamespace(String namespace) {
		throw new RuntimeException("hasNamespace only works at compile-time");
	}

	public boolean isInCommandStack(String commandName) {
		throw new RuntimeException("isInStack only works at compile-time");
	}

	public Encoder getEncoder() {
		return encoder;
	}

	public void setEncoder(Encoder encoder) {
		this.encoder = encoder;
	}

	public Map<String,String> getVars(Macro macro) {
		return varsMap.get(macro).peek();
	}

	public void pushVars(Macro macro) {
		Stack<Map<String,String>> vars = varsMap.get(macro);
		if( vars == null ) {
			vars = new ArrayStack<Map<String,String>>();
			varsMap.put(macro,vars);
		}
		vars.push(new HashMap<String,String>());
	}

	public void popVars(Macro macro) {
		varsMap.get(macro).pop();
	}

}