package org.metaborg.meta.lang.dynsem.interpreter.nodes.rules.premises.reduction;

import org.metaborg.meta.lang.dynsem.interpreter.nodes.building.TermBuild;
import org.metaborg.meta.lang.dynsem.interpreter.terms.ITerm;

import com.github.krukow.clj_lang.IPersistentStack;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;

@NodeChildren({ @NodeChild(value = "termBuild", type = TermBuild.class) })
public abstract class TermExpansion extends Node {

	public abstract Object[] execute(VirtualFrame frame);

	@Specialization
	public Object[] doConBuild(final ITerm term) {
		int arity = term.arity();
		Object[] terms = new Object[arity + 1];
		terms[0] = term;

		System.arraycopy(term.allSubterms(), 0, terms, 1, arity);

		return terms;
	}

	@Specialization
	public Object[] doListBuild(@SuppressWarnings("rawtypes") final IPersistentStack list) {
		return new Object[] { list };
	}
}

@@ -266,16 +266,58 @@
 tStack;%0A
+import com.oracle.truffle.api.dsl.Cached;%0A
 import c
@@ -735,32 +735,61 @@
 %09@Specialization
+(guards=%22term == cachedTerm%22)
 %0A%09public Object%5B
@@ -817,16 +817,285 @@
 erm term
+, @Cached(%22term%22) ITerm cachedTerm) %7B%0A%09%09return doConBuildForReal(cachedTerm);%0A%09%7D%0A%0A%09@Specialization(contains=%22doConBuild%22)%0A%09public Object%5B%5D doConBuildCacheMiss(final ITerm term)%7B%0A%09%09return doConBuildForReal(term);%0A%09%7D%0A%09%0A%09private Object%5B%5D doConBuildForReal(ITerm cachedTerm
 ) %7B%0A%09%09in
@@ -1104,17 +1104,23 @@
 arity = 
-t
+cachedT
 erm.arit
@@ -1179,17 +1179,23 @@
 ms%5B0%5D = 
-t
+cachedT
 erm;%0A%0A%09%09
@@ -1211,17 +1211,23 @@
 raycopy(
-t
+cachedT
 erm.allS

Add cache specialization to term expansion nodes