Add method call info for infix operators (#7090)

close #6374

In order to provide the method pointer information, the `IrToTruffle` pass sets the module name and the type name of the builtin node.
This commit is contained in:
Dmitry Bushev 2023-06-27 14:11:12 +01:00 committed by GitHub
parent 4e5cb9cca6
commit 22259e696d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 417 additions and 75 deletions

View File

@ -842,6 +842,7 @@
- [Add special handling for static method calls on Any][7033]
- [Improve parallel execution of commands and jobs in Language Server][7042]
- [Added retries when executing GraalVM updater][7079]
- [Add method call info for infix operators][7090]
[3227]: https://github.com/enso-org/enso/pull/3227
[3248]: https://github.com/enso-org/enso/pull/3248
@ -963,6 +964,7 @@
[7033]: https://github.com/enso-org/enso/pull/7033
[7042]: https://github.com/enso-org/enso/pull/7042
[7079]: https://github.com/enso-org/enso/pull/7079
[7090]: https://github.com/enso-org/enso/pull/7090
# Enso 2.0.0-alpha.18 (2021-10-12)

View File

@ -331,7 +331,7 @@ type File
## PRIVATE
Internal method to join two path segments together.
resolve : File
resolve self = @Builtin_Method "File.resolve"
resolve self subpath = @Builtin_Method "File.resolve"
## PRIVATE
Convert the file descriptor to a JS_Object.

View File

@ -9,10 +9,10 @@ import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
import org.enso.interpreter.instrument.profiling.ProfilingInfo;
import org.enso.interpreter.node.EnsoRootNode;
import org.enso.interpreter.node.MethodRootNode;
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode;
import org.enso.interpreter.node.expression.atom.QualifiedAccessorNode;
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.Type;
@ -212,6 +212,7 @@ public interface IdExecutionService {
*/
public FunctionCallInfo(FunctionCallInstrumentationNode.FunctionCall call) {
RootNode rootNode = call.getFunction().getCallTarget().getRootNode();
switch (rootNode) {
case MethodRootNode methodNode -> {
moduleName = methodNode.getModuleScope().getModule().getName();
@ -224,12 +225,12 @@ public interface IdExecutionService {
typeName = atomConstructor.getType().getQualifiedName();
functionName = atomConstructor.getName();
}
case EnsoRootNode ensoRootNode -> {
moduleName = ensoRootNode.getModuleScope().getModule().getName();
typeName = null;
functionName = rootNode.getName();
case BuiltinRootNode builtinRootNode -> {
moduleName = builtinRootNode.getModuleName();
typeName = builtinRootNode.getTypeName();
functionName = QualifiedName.fromString(builtinRootNode.getName()).item();
}
case default -> {
default -> {
moduleName = null;
typeName = null;
functionName = rootNode.getName();

View File

@ -271,9 +271,9 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
// appropriately invalidate all dependent expressions.
if (!isPanic) {
cache.offer(nodeId, result);
cache.putCall(nodeId, call);
}
cache.putType(nodeId, resultType);
cache.putCall(nodeId, call);
passExpressionValueToCallback(expressionValue);
if (isPanic) {

View File

@ -411,13 +411,13 @@ class BuiltinTypesTest
val requestId = UUID.randomUUID()
val metadata = new Metadata
val idMain = metadata.addItem(43, 18)
val idMain = metadata.addItem(48, 25)
val code =
"""import Standard.Base.Data.Time.Date
|
|main =
| Date.new 2000
| Date.new_builtin 2000 1 1
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)

View File

@ -514,6 +514,13 @@ class RuntimeErrorsTest
TestMessages.error(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(xId))
),
TestMessages.error(
@ -682,6 +689,13 @@ class RuntimeErrorsTest
TestMessages.error(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(xId))
),
TestMessages.update(contextId, yId, ConstantsGen.INTEGER),
@ -747,6 +761,13 @@ class RuntimeErrorsTest
TestMessages.error(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(xId))
),
TestMessages.error(
@ -902,6 +923,13 @@ class RuntimeErrorsTest
TestMessages.error(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(xId))
),
TestMessages.error(
@ -1039,7 +1067,7 @@ class RuntimeErrorsTest
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val xId = metadata.addItem(60, 19)
val xId = metadata.addItem(60, 19, "aa")
val yId = metadata.addItem(88, 5)
val mainResId = metadata.addItem(98, 12)
@ -1090,10 +1118,18 @@ class RuntimeErrorsTest
TestMessages.panic(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Panic",
"Standard.Base.Panic.Panic",
"throw"
)
),
Api.ExpressionUpdate.Payload.Panic(
"MyError",
Seq(xId)
)
),
Some("Standard.Base.Panic.Panic")
),
TestMessages.panic(
contextId,
@ -1318,10 +1354,18 @@ class RuntimeErrorsTest
TestMessages.panic(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Panic",
"Standard.Base.Panic.Panic",
"throw"
)
),
Api.ExpressionUpdate.Payload.Panic(
"MyError1",
Seq(xId)
)
),
Some("Standard.Base.Panic.Panic")
),
TestMessages.panic(
contextId,
@ -1364,12 +1408,18 @@ class RuntimeErrorsTest
TestMessages.panic(
contextId,
xId,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Panic",
"Standard.Base.Panic.Panic",
"throw"
)
),
Api.ExpressionUpdate.Payload.Panic(
"MyError2",
Seq(xId)
),
builtin = false,
typeChanged = false
Some("Standard.Base.Panic.Panic")
),
TestMessages.panic(
contextId,
@ -1388,8 +1438,7 @@ class RuntimeErrorsTest
"MyError2",
Seq(xId)
),
builtin = false,
typeChanged = false
builtin = false
),
context.executionComplete(contextId)
)

View File

@ -1692,6 +1692,187 @@ class RuntimeServerTest
)
}
it should "send method pointer updates of a builtin method" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val id_x = metadata.addItem(46, 17, "aa")
val code =
"""from Standard.Base import all
|
|main =
| x = "hello" + "world"
| x
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// open file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, moduleName, "main"),
None,
Vector()
)
)
)
)
context.receiveNIgnoreStdLib(4) should contain theSameElementsAs Seq(
Api.Response(Api.BackgroundJobsStartedNotification()),
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.update(
contextId,
id_x,
ConstantsGen.TEXT,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Data.Text",
"Standard.Base.Data.Text.Text",
"+"
)
)
),
context.executionComplete(contextId)
)
}
it should "send method pointer updates of a builtin method called as static" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val id_x = metadata.addItem(52, 25, "aa")
val id_y = metadata.addItem(86, 16, "ab")
val code =
"""import Standard.Base.Data.Time.Date
|
|main =
| x = Date.new_builtin 1970 1 1
| y = Date.Date.year x
| y
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// open file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, moduleName, "main"),
None,
Vector()
)
)
)
)
context.receiveNIgnoreStdLib(5) should contain theSameElementsAs Seq(
Api.Response(Api.BackgroundJobsStartedNotification()),
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.update(contextId, id_x, ConstantsGen.DATE),
TestMessages.update(
contextId,
id_y,
ConstantsGen.INTEGER_BUILTIN,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Data.Time.Date",
"Standard.Base.Data.Time.Date.Date",
"year"
)
)
),
context.executionComplete(contextId)
)
}
it should "not send method pointer updates of a builtin method defined as static" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val id_x = metadata.addItem(52, 25, "aa")
val code =
"""import Standard.Base.Data.Time.Date
|
|main =
| x = Date.new_builtin 2022 1 1
| x
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// open file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, moduleName, "main"),
None,
Vector()
)
)
)
)
context.receiveNIgnoreStdLib(4) should contain theSameElementsAs Seq(
Api.Response(Api.BackgroundJobsStartedNotification()),
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.update(contextId, id_x, "Standard.Base.Data.Time.Date.Date"),
context.executionComplete(contextId)
)
}
it should "send updates from last line" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
@ -2108,7 +2289,12 @@ class RuntimeServerTest
context.receiveN(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PopContextResponse(contextId)),
TestMessages
.update(contextId, mainRes, ConstantsGen.NOTHING, typeChanged = false),
.update(
contextId,
mainRes,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages.update(
contextId,
mainFoo,
@ -2231,8 +2417,12 @@ class RuntimeServerTest
fromCache = false,
typeChanged = false
),
TestMessages
.update(contextId, mainRes, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
mainRes,
ConstantsGen.NOTHING,
typeChanged = false
),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual List("6")
@ -2489,8 +2679,12 @@ class RuntimeServerTest
ConstantsGen.INTEGER,
Api.MethodCall(Api.MethodPointer(moduleName, ConstantsGen.NUMBER, "x"))
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -2522,8 +2716,12 @@ class RuntimeServerTest
fromCache = false,
typeChanged = false
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -2555,8 +2753,12 @@ class RuntimeServerTest
fromCache = false,
typeChanged = true
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -2588,8 +2790,12 @@ class RuntimeServerTest
fromCache = false,
typeChanged = true
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -2619,8 +2825,12 @@ class RuntimeServerTest
ConstantsGen.TEXT,
Api.MethodCall(Api.MethodPointer(moduleName, moduleName, "hie"))
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -2652,8 +2862,12 @@ class RuntimeServerTest
fromCache = false,
typeChanged = true
),
TestMessages
.update(contextId, idMainP, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idMainP,
ConstantsGen.NOTHING,
typeChanged = false
),
TestMessages
.update(contextId, idMain, ConstantsGen.NOTHING, typeChanged = false),
context.executionComplete(contextId)
@ -3500,8 +3714,12 @@ class RuntimeServerTest
) should contain theSameElementsAs Seq(
TestMessages
.update(contextId, idText, ConstantsGen.TEXT, typeChanged = false),
TestMessages
.update(contextId, idRes, ConstantsGen.NOTHING, typeChanged = false),
TestMessages.update(
contextId,
idRes,
ConstantsGen.NOTHING,
typeChanged = false
),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual List(prompt2)

View File

@ -2047,6 +2047,13 @@ class RuntimeVisualizationsTest
TestMessages.error(
contextId,
idMain,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(idMain))
),
context.executionComplete(contextId)
@ -2138,7 +2145,15 @@ class RuntimeVisualizationsTest
TestMessages.panic(
contextId,
idMain,
Api.ExpressionUpdate.Payload.Panic("42 (Integer)", Seq(idMain))
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Panic",
"Standard.Base.Panic.Panic",
"throw"
)
),
Api.ExpressionUpdate.Payload.Panic("42 (Integer)", Seq(idMain)),
Some("Standard.Base.Panic.Panic")
),
context.executionComplete(contextId)
)
@ -2167,9 +2182,15 @@ class RuntimeVisualizationsTest
TestMessages.panic(
contextId,
idMain,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Panic",
"Standard.Base.Panic.Panic",
"throw"
)
),
Api.ExpressionUpdate.Payload.Panic("42 (Integer)", Seq(idMain)),
builtin = false,
typeChanged = false
builtin = false
),
Api.Response(
Api.VisualizationEvaluationFailed(
@ -2253,6 +2274,13 @@ class RuntimeVisualizationsTest
TestMessages.error(
contextId,
idMain,
Api.MethodCall(
Api.MethodPointer(
"Standard.Base.Error",
"Standard.Base.Error.Error",
"throw"
)
),
Api.ExpressionUpdate.Payload.DataflowError(Seq(idMain))
),
context.executionComplete(contextId)

View File

@ -4,6 +4,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.RootNode;
import org.enso.interpreter.EnsoLanguage;
import org.enso.pkg.QualifiedName;
/** Root node for use by all the builtin functions. */
@NodeInfo(shortName = "BuiltinRoot", description = "Root node for builtin functions.")
@ -12,6 +13,29 @@ public abstract class BuiltinRootNode extends RootNode {
super(language);
}
protected QualifiedName moduleName = null;
protected QualifiedName typeName = null;
/** Get the module name where the builtin is defined. */
public QualifiedName getModuleName() {
return moduleName;
}
/** Set the module name where the builtin is defined. */
public void setModuleName(QualifiedName moduleName) {
this.moduleName = moduleName;
}
/** Get the type name of the builtin. */
public QualifiedName getTypeName() {
return typeName;
}
/** Set the type name of the builtin. */
public void setTypeName(QualifiedName typeName) {
this.typeName = typeName;
}
/**
* Executes this node's logic, returning a pair of return value and the new state.
*

View File

@ -116,9 +116,9 @@ public final class ModuleScope implements TruffleObject {
public void registerMethod(Type type, String method, Function function) {
Map<String, Function> methodMap = ensureMethodMapFor(type);
if (methodMap.containsKey(method)) {
// Builtin types will have double definition because of
// BuiltinMethod and that's OK
if (methodMap.containsKey(method) && !type.isBuiltin()) {
throw new RedefinedMethodException(type.getName(), method);
} else {
methodMap.put(method, function);

View File

@ -48,6 +48,7 @@ import org.enso.interpreter.node.expression.atom.{
ConstantNode,
QualifiedAccessorNode
}
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode
import org.enso.interpreter.node.expression.constant._
import org.enso.interpreter.node.expression.foreign.ForeignMethodCallNode
import org.enso.interpreter.node.expression.literal.LiteralNode
@ -83,6 +84,7 @@ import org.enso.interpreter.runtime.scope.{
import org.enso.interpreter.{Constants, EnsoLanguage}
import java.math.BigInteger
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
@ -441,15 +443,23 @@ class IrToTruffle(
else Left(l)
}
.map(fOpt =>
// Register builtin iff it has not been automatically registered at an early stage
// of builtins initialization or if it is a static wrapper.
fOpt
.filter(m => !m.isAutoRegister() || staticWrapper)
.map { m =>
if (staticWrapper) {
// Static wrappers differ in the number of arguments by 1.
// Therefore we cannot simply get the registered function.
// BuiltinRootNode.execute will infer the right order of arguments.
fOpt.map { m =>
if (m.isAutoRegister) {
val irFunctionArgumentsCount = fn.arguments.length
val builtinArgumentsCount =
m.getFunction.getSchema.getArgumentsCount
if (irFunctionArgumentsCount != builtinArgumentsCount) {
val irFunctionArguments =
fn.arguments.map(_.name.name).mkString(",")
val builtinArguments =
m.getFunction.getSchema.getArgumentInfos
.map(_.getName)
.mkString(",")
throw new CompilerError(
s"Wrong number of arguments provided in the definition of builtin function ${cons.getName}.${methodDef.methodName.name}. " +
s"[$irFunctionArguments] vs [$builtinArguments]"
)
}
val bodyBuilder =
new expressionProcessor.BuildFunctionBody(
fn.arguments,
@ -457,6 +467,11 @@ class IrToTruffle(
effectContext,
true
)
val builtinRootNode =
m.getFunction.getCallTarget.getRootNode
.asInstanceOf[BuiltinRootNode]
builtinRootNode.setModuleName(moduleScope.getModule.getName)
builtinRootNode.setTypeName(cons.getQualifiedName)
new RuntimeFunction(
m.getFunction.getCallTarget,
null,
@ -1750,7 +1765,7 @@ class IrToTruffle(
* @param binding whether the function is right inside a binding
* @return a truffle node representing the described function
*/
def processFunctionBody(
private def processFunctionBody(
arguments: List[IR.DefinitionArgument],
body: IR.Expression,
location: Option[IdentifiedLocation],

View File

@ -70,7 +70,7 @@ class InstrumentTestContext {
n: Int,
timeoutSeconds: Long = 60
): List[Api.Response] = {
receiveNWithFilter(n, (_ => true), timeoutSeconds)
receiveNWithFilter(n, _ => true, timeoutSeconds)
}
private def receiveNWithFilter(

View File

@ -15,7 +15,7 @@ class DateTest extends InterpreterTest {
|import Standard.Base.Data.Time.Date
|
|main =
| IO.println (Date.new 2022 04 01)
| IO.println (Date.new_builtin 2022 04 01)
|""".stripMargin
eval(code)
consumeOut shouldEqual List("2022-04-01")
@ -60,7 +60,7 @@ class DateTest extends InterpreterTest {
|import Standard.Base.Data.Time.Date
|
|main =
| ensodate = Date.new 2022 4 1
| ensodate = Date.new_builtin 2022 4 1
| ensoyear = ensodate.year
| ensomonth = ensodate.month
| ensoday = ensodate.day

View File

@ -478,9 +478,14 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
+ arg.getPosition()
+ "Idx] }, \"Unsupported argument for "
+ varName
+ " expected a "
+ " expected a '"
+ builtinName
+ "\");");
+ "' but got a '\""
+ " + arguments[arg" + arg.getPosition() + "Idx]"
+ " + \"' [\""
+ " + arguments[arg" + arg.getPosition() + "Idx].getClass()"
+ " + \"]\""
+ ");");
out.println(" throw new PanicException(error, bodyNode);");
out.println(" }");
}

View File

@ -1,6 +1,4 @@
polyglot java import java.time.LocalDate
new year (month = 1) (day = 1) = (LocalDate.of year month day) . internal_local_date
new_builtin year month day = @Builtin_Method "Date.new_builtin"
@Builtin_Type
type Date

View File

@ -21,6 +21,8 @@ meta value =
is_unresolved_symbol value = @Builtin_Method "Meta.is_unresolved_symbol"
get_unresolved_symbol_name symbol = @Builtin_Method "Meta.get_unresolved_symbol_name"
get_unresolved_symbol_scope symbol = @Builtin_Method "Meta.get_unresolved_symbol_scope"
get_atom_constructor atom = @Builtin_Method "Meta.get_atom_constructor"
get_constructor_name atom_constructor = @Builtin_Method "Meta.get_constructor_name"
@Builtin_Type
type Project_Description

View File

@ -9,7 +9,7 @@ type Polyglot
has_source_location value = @Builtin_Method "Polyglot.has_source_location"
get_source_location value = @Builtin_Method "Polyglot.get_source_location"
is_language_installed language_name = @Builtin_Method "Polyglot.is_language_installed"
get_executable_name = @Builtin_Method "Polyglot.get_executable_name"
get_executable_name value = @Builtin_Method "Polyglot.get_executable_name"
type Java
lookup_class name = @Builtin_Method "Java.lookup_class"