Skip to content

Commit

Permalink
Support addToHostClassPath in Espresso mode
Browse files Browse the repository at this point in the history
  • Loading branch information
JaroslavTulach committed Sep 16, 2023
1 parent 9be90fb commit f3705ea
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ static AddToClassPathNode build() {
@CompilerDirectives.TruffleBoundary
@Specialization
Object doExecute(Object path, @Cached ExpectStringNode expectStringNode) {
EnsoContext context = EnsoContext.get(this);
context
.getEnvironment()
.addToHostClassPath(context.getTruffleFile(new File(expectStringNode.execute(path))));
return context.getBuiltins().nothing();
var ctx = EnsoContext.get(this);
var file = ctx.getTruffleFile(new File(expectStringNode.execute(path)));
ctx.addToHostClassPath(file);
return ctx.getBuiltins().nothing();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.TruffleLanguage.Env;
import com.oracle.truffle.api.TruffleLogger;
import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
Expand Down Expand Up @@ -383,6 +384,27 @@ public Optional<Module> findModuleByExpressionId(UUID expressionId) {
.findFirst();
}

/**
* Modifies the classpath to use to lookup {@code polyglot java} imports.
* @param file the file to register
*/
@TruffleBoundary
public void addToHostClassPath(TruffleFile file) {
if (findGuestJava() == null) {
environment.addToHostClassPath(file);
} else {
try {
var path = new File(file.toUri()).getAbsoluteFile();
if (!path.exists()) {
throw new IllegalStateException("File not found " + path);
}
InteropLibrary.getUncached().invokeMember(findGuestJava(), "addPath", path.getPath());
} catch (InteropException ex) {
throw new IllegalStateException(ex);
}
}
}

/**
* Tries to lookup a Java class (host symbol in Truffle terminology) by its fully qualified name.
* This method also tries to lookup inner classes. More specifically, if the provided name
Expand All @@ -401,24 +423,29 @@ public Object lookupJavaClass(String className) {
List<String> nestedClassPart =
i < items.size() - 1 ? items.subList(i + 1, items.size()) : List.of();
try {
Object hostSymbol;
if (findGuestJava() == null) {
hostSymbol = environment.lookupHostSymbol(pkgName + "." + curClassName);
} else {
hostSymbol = InteropLibrary.getUncached().readMember(findGuestJava(), pkgName + "." + curClassName);
}
var hostSymbol = lookupHostSymbol(pkgName, curClassName);
if (nestedClassPart.isEmpty()) {
return hostSymbol;
} else {
return getNestedClass(hostSymbol, nestedClassPart);
var fullInnerClassName = curClassName + "$" + String.join("$", nestedClassPart);
return lookupHostSymbol(pkgName, fullInnerClassName);
}
} catch (RuntimeException | UnsupportedMessageException | UnknownIdentifierException ex) {
} catch (RuntimeException | InteropException ex) {
logger.log(Level.WARNING, null, ex);
}
}
return null;
}

private Object lookupHostSymbol(String pkgName, String curClassName)
throws UnknownIdentifierException, UnsupportedMessageException {
if (findGuestJava() == null) {
return environment.lookupHostSymbol(pkgName + "." + curClassName);
} else {
return InteropLibrary.getUncached().readMember(findGuestJava(), pkgName + "." + curClassName);
}
}

private Object guestJava = this;

@TruffleBoundary
Expand All @@ -428,10 +455,14 @@ private Object findGuestJava() throws IllegalStateException {
}
guestJava = null;
var envJava = System.getenv("ENSO_JAVA");
if (envJava == null) {
return guestJava;
}
if ("espresso".equals(envJava)) {
var src = Source.newBuilder("java", "<Bindings>", "getbindings.java").build();
try {
guestJava = environment.parsePublic(src).call();
logger.log(Level.SEVERE, "Using experimental Espresso support!");
} catch (Exception ex) {
if (ex.getMessage().contains("No language for id java found.")) {
logger.log(Level.SEVERE, "Environment variable ENSO_JAVA=" + envJava + ", but " + ex.getMessage());
Expand All @@ -443,6 +474,8 @@ private Object findGuestJava() throws IllegalStateException {
throw ise;
}
}
} else {
throw new IllegalStateException("Unsupported value of ENSO_JAVA environment variable: " + envJava);
}
return guestJava;
}
Expand Down Expand Up @@ -641,30 +674,6 @@ public NotificationHandler getNotificationHandler() {
return notificationHandler;
}

private Object getNestedClass(Object hostClass, List<String> nestedClassName) {
Object nestedClass = hostClass;
var interop = InteropLibrary.getUncached();
for (String name : nestedClassName) {
if (interop.isMemberReadable(nestedClass, name)) {
Object member;
try {
member = interop.readMember(nestedClass, name);
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
throw new IllegalStateException(e);
}
assert member != null;
if (interop.isMetaObject(member)) {
nestedClass = member;
} else {
return null;
}
} else {
return null;
}
}
return nestedClass;
}

private <T> T getOption(OptionKey<T> key) {
var options = getEnvironment().getOptions();
var safely = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ private class DefaultPackageRepository(
isLibrary: Boolean
): Unit = {
val extensions = pkg.listPolyglotExtensions("java")
extensions.foreach(context.getEnvironment.addToHostClassPath)
extensions.foreach(context.addToHostClassPath)

val (regularModules, syntheticModulesMetadata) = pkg
.listSources()
Expand Down

0 comments on commit f3705ea

Please sign in to comment.