Eliminate compile time dependency on runtime-language-epb (#7611)

This commit is contained in:
Jaroslav Tulach 2023-08-21 05:31:39 +02:00 committed by GitHub
parent f3f2f06bd9
commit e224eb350a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 72 additions and 74 deletions

View File

@ -1230,6 +1230,7 @@ lazy val `runtime-language-epb` =
truffleDslSuppressWarnsSetting,
instrumentationSettings
)
.dependsOn(`polyglot-api`)
/** Runs gu (GraalVM updater) command with given `args`.
* For example `runGu(Seq("install", "js"))`.
@ -1404,7 +1405,6 @@ lazy val runtime = (project in file("engine/runtime"))
Benchmark / parallelExecution := false
)
.dependsOn(`common-polyglot-core-utils`)
.dependsOn(`runtime-language-epb`)
.dependsOn(`edition-updater`)
.dependsOn(`interpreter-dsl`)
.dependsOn(`library-manager`)
@ -1532,6 +1532,7 @@ lazy val `runtime-with-instruments` =
.dependsOn(`runtime-instrument-id-execution`)
.dependsOn(`runtime-instrument-repl-debugger`)
.dependsOn(`runtime-instrument-runtime-server`)
.dependsOn(`runtime-language-epb`)
/* runtime-with-polyglot
* ~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,47 @@
package org.enso.polyglot;
import com.oracle.truffle.api.source.Source;
import java.util.Arrays;
/** Lists all the languages supported in polyglot eval. */
public enum ForeignLanguage {
JS("js", "js"),
PY("python", "python"),
R("R", "r");
public static final String ID = "epb";
private final String truffleId;
private final String syntacticTag;
ForeignLanguage(String truffleId, String syntacticTag) {
this.truffleId = truffleId;
this.syntacticTag = syntacticTag;
}
/** @return a Truffle language ID associated with this language */
public String getTruffleId() {
return truffleId;
}
/**
* Transforms an Enso-side syntactic language tag into a recognized language object.
*
* @param tag the tag to parse
* @return a corresponding language value, or null if the language is not recognized
*/
public static ForeignLanguage getBySyntacticTag(String tag) {
return Arrays.stream(values()).filter(l -> l.syntacticTag.equals(tag)).findFirst().orElse(null);
}
/**
* Builds a new source instance that can later be parsed by this class.
*
* @param foreignSource the foreign source to evaluate
* @param name the name of the source
* @return a source instance, parsable by the EPB language
*/
public Source buildSource(String foreignSource, String name) {
return Source.newBuilder(ID, this + "#" + foreignSource, name).build();
}
}

View File

@ -5,6 +5,7 @@ import com.oracle.truffle.api.TruffleLanguage;
import java.util.function.Consumer;
import org.enso.interpreter.epb.node.ContextRewrapNode;
import org.enso.interpreter.epb.node.ForeignEvalNode;
import org.enso.polyglot.ForeignLanguage;
/**
* An internal language that serves as a bridge between Enso and other supported languages.
@ -29,7 +30,7 @@ import org.enso.interpreter.epb.node.ForeignEvalNode;
* provide context-switching facilities.
*/
@TruffleLanguage.Registration(
id = EpbLanguage.ID,
id = ForeignLanguage.ID,
name = "Enso Polyglot Bridge",
characterMimeTypes = {EpbLanguage.MIME},
internal = true,
@ -37,7 +38,6 @@ import org.enso.interpreter.epb.node.ForeignEvalNode;
contextPolicy = TruffleLanguage.ContextPolicy.SHARED,
services = Consumer.class)
public class EpbLanguage extends TruffleLanguage<EpbContext> {
public static final String ID = "epb";
public static final String MIME = "application/epb";
@Override

View File

@ -1,45 +1,10 @@
package org.enso.interpreter.epb;
import com.oracle.truffle.api.source.Source;
import java.util.Arrays;
import org.enso.polyglot.ForeignLanguage;
/** A class containing helpers for creating and parsing EPB code */
public class EpbParser {
private static final String separator = "#";
/** Lists all the languages supported in polyglot eval. */
public enum ForeignLanguage {
JS("js", "js"),
PY("python", "python"),
R("R", "r");
private final String truffleId;
private final String syntacticTag;
ForeignLanguage(String truffleId, String syntacticTag) {
this.truffleId = truffleId;
this.syntacticTag = syntacticTag;
}
/** @return a Truffle language ID associated with this language */
public String getTruffleId() {
return truffleId;
}
/**
* Transforms an Enso-side syntactic language tag into a recognized language object.
*
* @param tag the tag to parse
* @return a corresponding language value, or null if the language is not recognized
*/
public static ForeignLanguage getBySyntacticTag(String tag) {
return Arrays.stream(values())
.filter(l -> l.syntacticTag.equals(tag))
.findFirst()
.orElse(null);
}
}
/** A parsing result. */
public static class Result {
private final ForeignLanguage language;
@ -69,19 +34,7 @@ public class EpbParser {
*/
public static Result parse(Source source) {
String src = source.getCharacters().toString();
String[] langAndCode = src.split(separator, 2);
String[] langAndCode = src.split("#", 2);
return new Result(ForeignLanguage.valueOf(langAndCode[0]), langAndCode[1]);
}
/**
* Builds a new source instance that can later be parsed by this class.
*
* @param language the foreign language to use
* @param foreignSource the foreign source to evaluate
* @param name the name of the source
* @return a source instance, parsable by the EPB language
*/
public static Source buildSource(ForeignLanguage language, String foreignSource, String name) {
return Source.newBuilder(EpbLanguage.ID, language + separator + foreignSource, name).build();
}
}

View File

@ -17,7 +17,6 @@ import org.enso.interpreter.epb.EpbLanguage;
import org.enso.interpreter.epb.EpbParser;
import org.enso.interpreter.epb.runtime.ForeignParsingException;
import org.enso.interpreter.epb.runtime.GuardedTruffleContext;
import org.graalvm.polyglot.Context;
public class ForeignEvalNode extends RootNode {
private final EpbParser.Result code;
@ -72,7 +71,8 @@ public class ForeignEvalNode extends RootNode {
CompilerDirectives.transferToInterpreterAndInvalidate();
var foreignLang = code.getLanguage();
String truffleLangId = foreignLang.getTruffleId();
var installedLanguages = Context.getCurrent().getEngine().getLanguages();
var context = EpbContext.get(this);
var installedLanguages = context.getEnv().getInternalLanguages();
if (!installedLanguages.containsKey(truffleLangId)) {
this.parseException =
new ForeignParsingException(truffleLangId, installedLanguages.keySet(), this);

View File

@ -13,7 +13,7 @@ public class ForeignMethodInvokeTest extends TestBase {
@BeforeClass
public static void prepareCtx() {
ctx = createDefaultContext();
ctx = defaultContextBuilder("enso").build();
}
@AfterClass
@ -27,10 +27,10 @@ public class ForeignMethodInvokeTest extends TestBase {
// should fail with a Polyglot_Error, rather than crashing whole engine.
String source = """
from Standard.Base import all
foreign python py_array = \"\"\"
return [1,2,3]
main =
Panic.recover Any py_array
""".trim();

View File

@ -15,7 +15,6 @@ import org.enso.distribution.DistributionManager;
import org.enso.distribution.Environment;
import org.enso.distribution.locking.LockManager;
import org.enso.distribution.locking.ThreadSafeFileLockManager;
import org.enso.interpreter.epb.EpbLanguage;
import org.enso.interpreter.instrument.NotificationHandler;
import org.enso.interpreter.instrument.NotificationHandler.Forwarder;
import org.enso.interpreter.instrument.NotificationHandler.TextMode$;
@ -31,6 +30,7 @@ import org.enso.interpreter.runtime.tag.Patchable;
import org.enso.interpreter.util.FileDetector;
import org.enso.lockmanager.client.ConnectedLockManager;
import org.enso.logger.masking.MaskingFactory;
import org.enso.polyglot.ForeignLanguage;
import org.enso.polyglot.LanguageInfo;
import org.enso.polyglot.RuntimeOptions;
import org.enso.syntax2.Line;
@ -69,7 +69,7 @@ import com.oracle.truffle.api.nodes.RootNode;
defaultMimeType = LanguageInfo.MIME_TYPE,
characterMimeTypes = {LanguageInfo.MIME_TYPE},
contextPolicy = TruffleLanguage.ContextPolicy.EXCLUSIVE,
dependentLanguages = {EpbLanguage.ID},
dependentLanguages = {ForeignLanguage.ID},
fileTypeDetectors = FileDetector.class,
services= { Timer.class, NotificationHandler.Forwarder.class, LockManager.class }
)
@ -159,7 +159,7 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
var env = context.getEnvironment();
var preinit = env.getOptions().get(RuntimeOptions.PREINITIALIZE_KEY);
if (preinit != null && preinit.length() > 0) {
var epb = env.getInternalLanguages().get(EpbLanguage.ID);
var epb = env.getInternalLanguages().get(ForeignLanguage.ID);
var run = env.lookup(epb, Consumer.class);
run.accept(preinit);
}

View File

@ -7,8 +7,7 @@ import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.epb.node.CoercePrimitiveNode;
import org.enso.interpreter.node.expression.foreign.CoerceNothing;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.error.PanicException;
@ -22,13 +21,12 @@ public class ReadArrayElementNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private @Child CoercePrimitiveNode coercion = CoercePrimitiveNode.build();
private @Child CoerceNothing nothingCoercion = CoerceNothing.build();
private @Child HostValueToEnsoNode toEnso = HostValueToEnsoNode.build();
private final BranchProfile err = BranchProfile.create();
Object execute(Object array, long index) {
try {
return nothingCoercion.execute(coercion.execute(library.readArrayElement(array, index)));
return toEnso.execute(library.readArrayElement(array, index));
} catch (UnsupportedMessageException e) {
err.enter();
Builtins builtins = EnsoContext.get(this).getBuiltins();

View File

@ -31,7 +31,7 @@ import org.enso.compiler.pass.resolve.{
TypeNames,
TypeSignatures
}
import org.enso.interpreter.epb.EpbParser
import org.enso.polyglot.ForeignLanguage
import org.enso.interpreter.node.callable.argument.ReadArgumentNode
import org.enso.interpreter.node.callable.function.{
BlockNode,
@ -1684,7 +1684,7 @@ class IrToTruffle(
val bodyExpr = body match {
case IR.Foreign.Definition(lang, code, _, _, _) =>
buildForeignBody(
EpbParser.ForeignLanguage.getBySyntacticTag(lang),
ForeignLanguage.getBySyntacticTag(lang),
code,
arguments.map(_.name.name),
argSlotIdxs
@ -1746,12 +1746,12 @@ class IrToTruffle(
}
private def buildForeignBody(
language: EpbParser.ForeignLanguage,
language: ForeignLanguage,
code: String,
argumentNames: List[String],
argumentSlotIdxs: List[Int]
): RuntimeExpression = {
val src = EpbParser.buildSource(language, code, scopeName)
val src = language.buildSource(code, scopeName)
val foreignCt = context.getEnvironment
.parseInternal(src, argumentNames: _*)
val argumentReaders = argumentSlotIdxs

View File

@ -12,8 +12,7 @@ import org.enso.compiler.pass.analyse.{
}
import org.enso.compiler.pass.lint.UnusedBindings
import org.enso.compiler.pass.optimise.LambdaConsolidate
import org.enso.interpreter.epb.EpbParser
import org.enso.interpreter.epb.EpbParser.ForeignLanguage
import org.enso.polyglot.ForeignLanguage
import scala.annotation.{tailrec}
@ -299,7 +298,7 @@ case object GenerateMethodBodies extends IRPass {
@tailrec
private def findForeignDefinition(
body: IR.Expression,
lang: Option[EpbParser.ForeignLanguage]
lang: Option[ForeignLanguage]
): Option[IR.Foreign.Definition] = {
body match {
case foreignDef: IR.Foreign.Definition =>

View File

@ -39,8 +39,8 @@ public abstract class TestBase {
return context;
}
protected static Context.Builder defaultContextBuilder() {
return Context.newBuilder()
protected static Context.Builder defaultContextBuilder(String... languages) {
return Context.newBuilder(languages)
.allowExperimentalOptions(true)
.allowIO(IOAccess.ALL)
.allowAllAccess(true)