package org.mozartoz.truffle.nodes;

import org.mozartoz.truffle.runtime.Arity;
import org.mozartoz.truffle.runtime.OzException;
import org.mozartoz.truffle.runtime.RecordFactory;
import org.mozartoz.truffle.runtime.Unit;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.TypeSystemReference;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.Instrumentable;
import com.oracle.truffle.api.instrumentation.StandardTags.RootTag;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;

@TypeSystemReference(OzTypes.class)
@ImportStatic(OzGuards.class)
@Instrumentable(factory = OzNodeWrapper.class)
public abstract class OzNode extends Node {

	boolean hasRootTag = false;

	private @CompilationFinal SourceSection sourceSection;

	public void setSourceSection(SourceSection sourceSection) {
		CompilerDirectives.transferToInterpreterAndInvalidate();
		this.sourceSection = sourceSection;
	}

	@Override
	public SourceSection getSourceSection() {
		return sourceSection;
	}

	protected static final Object unit = Unit.INSTANCE;

	public abstract Object execute(VirtualFrame frame);

	@Override
	protected boolean isTaggedWith(Class<?> tag) {
		if (tag == RootTag.class) {
			return hasRootTag;
		}
		return false;
	}

	protected Object unimplemented() {
		throw new OzException(this, "unimplemented");
	}

	// Exception helpers

	private static final RecordFactory KERNEL_ERROR_FACTORY2 = Arity.build("kernel", 1L, 2L).createFactory();

	protected OzException kernelError(String kind, Object arg) {
		DynamicObject data = OzException.newError(KERNEL_ERROR_FACTORY2.newRecord(kind, arg));
		return new OzException(this, data);
	}

	private static final RecordFactory KERNEL_ERROR_FACTORY3 = Arity.build("kernel", 1L, 2L, 3L).createFactory();

	protected OzException kernelError(String kind, Object arg1, Object arg2) {
		DynamicObject data = OzException.newError(KERNEL_ERROR_FACTORY3.newRecord(kind, arg1, arg2));
		return new OzException(this, data);
	}

	private static final RecordFactory KERNEL_ERROR_FACTORY4 = Arity.build("kernel", 1L, 2L, 3L, 4L).createFactory();

	protected OzException kernelError(String kind, Object arg1, Object arg2, Object arg3) {
		DynamicObject data = OzException.newError(KERNEL_ERROR_FACTORY4.newRecord(kind, arg1, arg2, arg3));
		return new OzException(this, data);
	}

	private static final RecordFactory KERNEL_ERROR_FACTORY6 = Arity.build("kernel", 1L, 2L, 3L, 4L, 5L, 6L).createFactory();

	protected OzException kernelError(String kind, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
		DynamicObject data = OzException.newError(KERNEL_ERROR_FACTORY6.newRecord(kind, arg1, arg2, arg3, arg4, arg5));
		return new OzException(this, data);
	}
}

@@ -532,29 +532,153 @@
 ntation.
-Instrumentabl
+GenerateWrapper;%0Aimport com.oracle.truffle.api.instrumentation.InstrumentableNode;%0Aimport com.oracle.truffle.api.instrumentation.ProbeNod
 e;%0Aimpor
@@ -958,46 +958,23 @@
 s)%0A@
-Instrumentable(factory = OzNod
+Generat
 eWrapper
 .cla
@@ -969,23 +969,16 @@
 eWrapper
-.class)
 %0Apublic 
@@ -1012,16 +1012,46 @@
 ds Node 
+implements InstrumentableNode 
 %7B%0A%0A%09bool
@@ -1599,16 +1599,16 @@
 ag;%0A%09%09%7D%0A
-
 %09%09return
@@ -1615,24 +1615,208 @@
  false;%0A%09%7D%0A%0A
+%09@Override%0A%09public WrapperNode createWrapper(ProbeNode probeNode) %7B%0A%09%09return new OzNodeWrapper(this, probeNode);%0A%09%7D%0A%0A%09@Override%0A%09public boolean isInstrumentable() %7B%0A%09%09return true;%0A%09%7D%0A%0A
 %09protected O

Fix Instrumentable deprecation