view src/luan/LuanException.java @ 1654:3f28ea044a32

docs UI
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 04 Apr 2022 22:19:32 -0600
parents a37ffe2d1b14
children 46cf5137cb6b
line wrap: on
line source

package luan;

import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.PrintStream;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;


public final class LuanException extends Exception implements LuanMutable {
	private LuanTable table;
	private Map extra = new HashMap();
	private boolean immutable = false;
	public boolean showCause = true;

	public LuanException(String msg,Throwable cause) {
		super(msg,cause);
	}

	public LuanException(String msg) {
		super(msg);
	}

	public LuanException(Throwable cause) {
		super(cause);
	}

	@Override public boolean isImmutable() {
		return immutable;
	}

	@Override public void makeImmutable() {
		if(immutable)
			return;
		immutable = true;
		LuanMutable.makeImmutable(table);
		LuanMutable.makeImmutable(extra);
	}

	public void put(String key,Object value) throws LuanException {
		if( table == null ) {
			extra.put(key,value);
		} else {
			table.rawPut(key,value);
		}
	}

	public LuanTable table(Luan luan) {
		if( table==null ) {
			try {
				LuanTable Boot = (LuanTable)luan.require("luan:Boot.luan");
				table = (LuanTable)Boot.fn(luan,"new_error_table").call(luan,this );
				for( Object stupid : extra.entrySet() ) {
					Map.Entry entry = (Map.Entry)stupid;
					table.put( luan, entry.getKey(), entry.getValue() );
				}
			} catch(LuanException e) {
				throw new RuntimeException(e);
			}
		}
		return table;
	}

	public void throwThis() throws LuanException {
		throw this;
	}

	public String getJavaStackTraceString() {
		return getJavaStackTraceString(this);
	}

	private static String getJavaStackTraceString(Throwable th) {
		StringWriter sw = new StringWriter();
		th.printStackTrace(new PrintWriter(sw));
		return sw.toString();
	}

	public static List<StackTraceElement> justLuan(StackTraceElement[] orig) {
		List<StackTraceElement> list = new ArrayList<StackTraceElement>();
		for( int i=0; i<orig.length; i++ ) {
			StackTraceElement ste = orig[i];
			if( !ste.getClassName().startsWith("luan.impl.EXP") )
				continue;
			list.add(ste);
			if( !ste.getMethodName().equals("doCall") )
				i++;
		}
		return list;
	}

	public static LuanTable getLuanStackTrace() {
		return new LuanTable( justLuan( Thread.currentThread().getStackTrace() ) );
	}

	public static String toLuanString(StackTraceElement ste) {
		int line = ste.getLineNumber();
		String method = ste.getMethodName();
		boolean hasMethod = !method.equals("doCall");
		if( hasMethod ) {
			int i = method.indexOf('$');
			if( i != -1 ) {
				int n = Integer.parseInt(method.substring(i+1));
				line -= n;
				method = method.substring(0,i);
				if( method.equals("_") )
					hasMethod = false;
			}
		}
		StringBuilder sb = new StringBuilder();
		sb.append( ste.getFileName() ).append( " line " ).append( line );
		if( hasMethod )
			sb.append( " in function '" ).append( method.substring(1) ).append( "'" );
		return sb.toString();
	}

	private StringBuilder luanStackTrace() {
		StringBuilder sb = new StringBuilder();
		sb.append( getMessage() );
		for( StackTraceElement ste : justLuan(getStackTrace()) ) {
			sb.append( "\n\t" ).append( toLuanString(ste) );
		}
		return sb;
	}

	public String getLuanStackTraceString() {
		StringBuilder sb = luanStackTrace();
		Throwable cause = getCause();
		if( showCause && cause != null )
			sb.append( "\nCaused by: " ).append( getJavaStackTraceString(cause) );
		return sb.toString();
	}

	@Override public void printStackTrace(PrintStream s) {
		s.print("Luan: ");
		s.println(luanStackTrace());
		s.print("Caused by: ");
		super.printStackTrace(s);
	}

	@Override public void printStackTrace(PrintWriter s) {
		s.print("Luan: ");
		s.println(luanStackTrace());
		s.print("Caused by: ");
		super.printStackTrace(s);
	}

}