Implement Interop Library for Unresolved Symbols (#952)

This commit is contained in:
Marcin Kostrzewa 2020-06-30 11:33:31 +02:00 committed by GitHub
parent e9b676834b
commit 510d9e4a2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 5 deletions

View File

@ -1,11 +1,20 @@
package org.enso.interpreter.runtime.callable;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.*;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import org.enso.interpreter.Constants;
import org.enso.interpreter.node.callable.MethodResolverNode;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.scope.ModuleScope;
/** Simple runtime value representing a yet-unresolved by-name symbol. */
@ExportLibrary(InteropLibrary.class)
public class UnresolvedSymbol implements TruffleObject {
private final String name;
private final ModuleScope scope;
@ -17,7 +26,7 @@ public class UnresolvedSymbol implements TruffleObject {
* @param scope the scope in which this symbol was created
*/
private UnresolvedSymbol(String name, ModuleScope scope) {
this.name = name.intern();
this.name = name;
this.scope = scope;
}
@ -68,4 +77,31 @@ public class UnresolvedSymbol implements TruffleObject {
public static UnresolvedSymbol build(String name, ModuleScope scope) {
return new UnresolvedSymbol(name, scope);
}
/**
* Marks this object as executable through the interop library.
*
* @return always true
*/
@ExportMessage
public boolean isExecutable() {
return true;
}
/** Implements the logic of executing {@link UnresolvedSymbol} through the interop library. */
@ExportMessage
@ImportStatic(Constants.CacheSizes.class)
public static class Execute {
@Specialization
static Object doDispatch(
UnresolvedSymbol symbol,
Object[] arguments,
@Cached MethodResolverNode methodResolverNode,
@CachedLibrary(limit = "BUILTIN_INTEROP_DISPATCH") InteropLibrary library)
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
if (arguments.length == 0) throw ArityException.create(1, 0);
Function function = methodResolverNode.execute(symbol, arguments[0]);
return library.execute(function, arguments);
}
}
}

View File

@ -1,12 +1,12 @@
package org.enso.interpreter.test.semantic
import org.enso.interpreter.test.{InterpreterTest, InterpreterContext}
import org.enso.interpreter.test.{InterpreterContext, InterpreterTest}
class InteropTest extends InterpreterTest {
override def subject: String = "Interop Library"
override def specify(
implicit interpreterContext: InterpreterContext
override def specify(implicit
interpreterContext: InterpreterContext
): Unit = {
"support tail recursive functions" in {
val code =
@ -53,5 +53,26 @@ class InteropTest extends InterpreterTest {
val fun = eval(code)
fun.call(1, 2) shouldEqual 2
}
"work with unresolved symbols" in {
val code =
"""
|Number.add x = x + this
|Text.add x = this + x
|
|main = add
|""".stripMargin
val symbol = eval(code)
symbol.call(1, 2) shouldEqual 3
symbol.call(3, 4) shouldEqual 7
symbol.execute("Hello", " World") shouldEqual "Hello World"
}
"work with unresolved symbols from builtin scope" in {
val code = "main = to_text"
val symbol = eval(code)
symbol.call(1) shouldEqual "1"
symbol.execute("Foo") shouldEqual "Foo"
}
}
}