package org.mozartoz.truffle.runtime;

import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;

@SuppressWarnings("serial")
public class OzException extends RuntimeException {

	static final RecordFactory ERROR_ARITY = Arity.build("error", 1L, "debug").createFactory();
	static final RecordFactory SYSTEM_ARITY = Arity.build("system", 1L, "debug").createFactory();
	static final RecordFactory FAILURE_ARITY = Arity.build("failure", "debug").createFactory();

	public static DynamicObject newError(Object error) {
		return ERROR_ARITY.newRecord(error, Unit.INSTANCE);
	}

	public static DynamicObject newSystemError(Object error) {
		return SYSTEM_ARITY.newRecord(error, Unit.INSTANCE);
	}

	public static DynamicObject newFailure() {
		return FAILURE_ARITY.newRecord(Unit.INSTANCE);
	}

	private final Object data;

	public OzException(Node currentNode, String message) {
		this(currentNode, newError(message.intern()));
	}

	public OzException(Node currentNode, Object data) {
		super(data.toString());
		OzBacktrace backtrace = OzBacktrace.capture(currentNode);

		Object storedData = data;
		if (data instanceof DynamicObject) {
			DynamicObject dataRecord = (DynamicObject) data;
			boolean hasDebug = dataRecord.containsKey("debug");
			if (hasDebug && dataRecord.get("debug") == Unit.INSTANCE) {
				DynamicObject dataWithDebug = dataRecord.copy(dataRecord.getShape());
				dataWithDebug.getShape().getProperty("debug").setInternal(dataWithDebug, backtrace);
				storedData = dataWithDebug;
			}
		}

		this.data = storedData;
	}

	public Object getData() {
		return data;
	}

	public OzBacktrace getBacktrace() {
		Object debug = ((DynamicObject) data).get("debug");
		return (OzBacktrace) debug;
	}

}

@@ -1651,16 +1651,56 @@
 ace() %7B%0A
+%09%09if (data instanceof DynamicObject) %7B%0A%09
 %09%09Object
@@ -1747,16 +1747,17 @@
 ug%22);%0A%09%09
+%09
 return (
@@ -1776,14 +1776,45 @@
  debug;%0A
+%09%09%7D else %7B%0A%09%09%09return null;%0A%09%09%7D%0A
 %09%7D%0A%0A%7D%0A

Handle a non-DynamicObject for an exception data in getBacktrace()