package org.strategoxt.imp.runtime.stratego;

import org.eclipse.core.resources.IProject;
import org.eclipse.imp.language.Language;
import org.eclipse.imp.language.LanguageRegistry;
import org.spoofax.interpreter.core.IContext;
import org.spoofax.interpreter.core.InterpreterException;
import org.spoofax.interpreter.library.AbstractPrimitive;
import org.spoofax.interpreter.library.ssl.SSLLibrary;
import org.spoofax.interpreter.stratego.Strategy;
import org.spoofax.interpreter.terms.IStrategoString;
import org.spoofax.interpreter.terms.IStrategoTerm;
import org.strategoxt.imp.runtime.Environment;
import org.strategoxt.imp.runtime.dynamicloading.BadDescriptorException;
import org.strategoxt.imp.runtime.dynamicloading.Descriptor;
import org.strategoxt.imp.runtime.services.StrategoObserver;

/**
 * Call a strategy by name in another language by name
 * 
 * @author Vlad Vergu <v.a.vergu add tudelft.nl>
 * 
 */
public class ForeignLangCallPrimitive extends AbstractPrimitive {

	public ForeignLangCallPrimitive() {
		super("SSL_EXT_foreigncall", 0, 2);
	}

	/**
	 * Example usage:
	 * 
	 * <code>
	 * foreign-call(|lang,strategy) = PRIM("SSL_EXT_buildercall");
	 * 
	 * foobar:
	 *  foreign-call(|"OtherLang", "strategy-name")
	 * 
	 * </code>
	 */
	@Override
	public boolean call(final IContext env, Strategy[] svars, IStrategoTerm[] tvars)
			throws InterpreterException {

		assert tvars.length == 2;
		assert tvars[0] instanceof IStrategoString;
		assert tvars[1] instanceof IStrategoString;
		try {
			final String oLangName = ((IStrategoString) tvars[0]).stringValue();
			final String strategyName = ((IStrategoString) tvars[1]).stringValue();
			final IStrategoTerm inputTerm = env.current();
			final EditorIOAgent agent = (EditorIOAgent) SSLLibrary.instance(env).getIOAgent();
			final IProject project = agent.getProject();

			final Language oLang = LanguageRegistry.findLanguage(oLangName);
			if (oLang == null)
				return false;
			final Descriptor oLangDescr = Environment.getDescriptor(oLang);
			assert oLangDescr != null;
			final StrategoObserver observer = oLangDescr.createService(StrategoObserver.class, null);
			final IStrategoTerm outputTerm = observer.invoke(strategyName, inputTerm, project
					.getLocation().toFile());
			env.setCurrent(outputTerm);
		} catch (ClassCastException cex) {
			Environment.logException(cex);
			return false;
		} catch (BadDescriptorException e) {
			Environment.logException(e);
			return false;
		}
		return true;
	}
}

@@ -1500,17 +1500,8 @@
 ng;%0A
-%09%09try %7B%0A%09
 %09%09fi
@@ -1559,33 +1559,32 @@
 .stringValue();%0A
-%09
 %09%09final String s
@@ -1637,24 +1637,58 @@
 ingValue();%0A
+%09%09boolean result = false;%0A%09%09try %7B%0A
 %09%09%09final ISt
@@ -1858,16 +1858,118 @@
 oject();
+%0A%09%09%09final String dir = ((EditorIOAgent) SSLLibrary.instance(env).getIOAgent())%0A%09%09%09%09%09.getProjectPath();
 %0A%0A%09%09%09fin
@@ -2214,16 +2214,22 @@
 angDescr
+%0A%09%09%09%09%09
 .createS
@@ -2273,149 +2273,230 @@
 %0A%09%09%09
-final IStrategoTerm outputTerm = observer.invoke(strategyName, inputTerm, project%0A%09%09%09%09%09.getLocation().toFile());%0A%09%09%09env.setCurrent(outputTerm
+observer.configureRuntime(project, dir);%0A%09%09%09observer.getRuntime().setCurrent(inputTerm);%0A%09%09%09result = observer.getRuntime().invoke(strategyName);%0A%09%09%09env.setCurrent(observer.getRuntime().current());%0A%09%09%09observer.uninitialize(
 );%0A%09
@@ -2509,17 +2509,15 @@
 ch (
-ClassCast
+Runtime
 Exce
@@ -2563,33 +2563,16 @@
 n(cex);%0A
-%09%09%09return false;%0A
 %09%09%7D catc
@@ -2636,29 +2636,81 @@
 n(e);%0A%09%09
-%09return false
+%7D catch (InterpreterException e) %7B%0A%09%09%09Environment.logException(e)
 ;%0A%09%09%7D%0A%09%09
@@ -2720,12 +2720,14 @@
 urn 
-true
+result
 ;%0A%09%7D

Call foreign strategy directly on the interpreter instead of on the observer