view src/nabble/naml/compiler/Template.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.Stack;

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


public final class Template extends Compiler.Traceable {
	private final Program program;
	private final Chunk chunk;
	private final Class[] baseClasses;
	public final Macro macro;

	Template(Compiler compiler,Program program,Chunk chunk,Class[] baseClasses,Macro macro) {
		super(compiler);
		this.program = program;
		this.chunk = chunk;
		this.baseClasses = baseClasses;
		this.macro = macro;
	}

	public String name() {
		return macro.name;
	}

	public final Program program() {
		return program;
	}

	public final void run(IPrintWriter out,Map<String,Object> args,Object... base) {
		run(0,Encoder.TEXT,out,args,base);
		out.flush();
	}

	final void run(int callDepth,Encoder encoder,IPrintWriter out,Map<String,Object> args,Object... base) {
		Set<String> argNames = macro.parameters;
		if( !argNames.containsAll(args.keySet()) ) {
			Set<String> badArgs = new HashSet<String>(args.keySet());
			badArgs.removeAll(argNames);
			throw new RuntimeException("invalid args: "+badArgs);
		}
		Stack<StackTrace> stack = StackTrace.stack();
		stack.push(stackTrace);
		try {
			check(base);
			RunState runState = new RunStateImpl(this,callDepth,encoder);
			for( Object obj : base ) {
				runState.push(obj);
			}
			for( Map.Entry<String,Object> entry : args.entrySet() ) {
				String key = entry.getKey();
				Object value = entry.getValue();
				if( value instanceof String ) {
					runState.putArg( key, (String)value );
				} else {
					runState.putArg( key, runState.saveNamespace(value) );
				}
			}
			chunk.run(out,runState);
		} catch (ExitException e) {
			// do nothing.
		} finally {
			stack.pop();
		}
	}

	private void check(Object[] base) {
		if( base.length != baseClasses.length )
			throw new TemplateRuntimeException("base mismatch base.length="+base.length+" baseClasses.length="+baseClasses.length);
		for( int i=0; i<baseClasses.length; i++ ) {
			if( !baseClasses[i].isInstance(base[i]) )
				throw new TemplateRuntimeException("base mismatch");
		}
	}

//	private static void handle(Exception e) {
//		if( e instanceof RuntimeException )
//			throw (RuntimeException)e;
//		throw new TemplateRuntimeException(e);
//	}

	public static String stringValue(Object obj) {
		if( obj==null )
			return null;
		return obj.toString();
	}

	public static boolean booleanValue(String s)
		throws BooleanFormatException
	{
		if( s.equalsIgnoreCase("true") )
			return true;
		if( s.equalsIgnoreCase("false") )
			return false;
		throw new BooleanFormatException("For input string: \""+s+"\"");
	}

	public static boolean booleanValue(Object obj)
		throws BooleanFormatException
	{
		String s = stringValue(obj);
		if( s==null )
			throw new BooleanFormatException("For input string: null");
		return booleanValue(s);
	}

	public static boolean booleanValue(Object obj,boolean defaultValue)
		throws BooleanFormatException
	{
		String s = stringValue(obj);
		if( s==null )
			return defaultValue;
		return booleanValue(s);
	}

	public static int intValue(Object obj)
		throws NumberFormatException
	{
		String s = stringValue(obj);
		return Integer.parseInt(s);
	}

	public static int intValue(Object obj, int defaultValue)
		throws NumberFormatException
	{
		String s = stringValue(obj);
		if( s==null )
			return defaultValue;
		return Integer.parseInt(s);
	}

	public static long longValue(Object obj)
		throws NumberFormatException
	{
		String s = stringValue(obj);
		return Long.parseLong(s);
	}

}