mirror of
https://github.com/enso-org/enso.git
synced 2024-10-04 16:48:21 +03:00
Enable conversion methods (#3177)
This commit is contained in:
parent
7239643046
commit
6a426c477a
@ -162,6 +162,10 @@ class IrToTruffle(
|
||||
val methodDefs = module.bindings.collect {
|
||||
case method: IR.Module.Scope.Definition.Method.Explicit => method
|
||||
}
|
||||
val conversionDefs = module.bindings.collect {
|
||||
case conversion: IR.Module.Scope.Definition.Method.Conversion =>
|
||||
conversion
|
||||
}
|
||||
|
||||
// Register the imports in scope
|
||||
imports.foreach {
|
||||
@ -287,7 +291,80 @@ class IrToTruffle(
|
||||
}
|
||||
moduleScope.registerMethod(cons, methodDef.methodName.name, function)
|
||||
}
|
||||
})
|
||||
|
||||
// Register the conversion definitions in scope
|
||||
conversionDefs.foreach(methodDef => {
|
||||
val scopeInfo = methodDef
|
||||
.unsafeGetMetadata(
|
||||
AliasAnalysis,
|
||||
s"Missing scope information for conversion " +
|
||||
s"`${methodDef.typeName.name}.${methodDef.methodName.name}`."
|
||||
)
|
||||
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
||||
val dataflowInfo = methodDef.unsafeGetMetadata(
|
||||
DataflowAnalysis,
|
||||
"Method definition missing dataflow information."
|
||||
)
|
||||
|
||||
val consOpt =
|
||||
methodDef.methodReference.typePointer
|
||||
.getMetadata(MethodDefinitions)
|
||||
.map { res =>
|
||||
res.target match {
|
||||
case BindingsMap.ResolvedModule(module) =>
|
||||
module.unsafeAsModule().getScope.getAssociatedType
|
||||
case BindingsMap.ResolvedConstructor(definitionModule, cons) =>
|
||||
definitionModule
|
||||
.unsafeAsModule()
|
||||
.getScope
|
||||
.getConstructors
|
||||
.get(cons.name)
|
||||
case BindingsMap.ResolvedPolyglotSymbol(_, _) =>
|
||||
throw new CompilerError(
|
||||
"Impossible polyglot symbol, should be caught by MethodDefinitions pass."
|
||||
)
|
||||
case _: BindingsMap.ResolvedMethod =>
|
||||
throw new CompilerError(
|
||||
"Impossible here, should be caught by MethodDefinitions pass."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
consOpt.foreach { cons =>
|
||||
val expressionProcessor = new ExpressionProcessor(
|
||||
cons.getName ++ Constants.SCOPE_SEPARATOR ++ methodDef.methodName.name,
|
||||
scopeInfo.graph,
|
||||
scopeInfo.graph.rootScope,
|
||||
dataflowInfo
|
||||
)
|
||||
|
||||
val function = methodDef.body match {
|
||||
case fn: IR.Function =>
|
||||
val (body, arguments) =
|
||||
expressionProcessor.buildFunctionBody(fn.arguments, fn.body)
|
||||
val rootNode = MethodRootNode.build(
|
||||
language,
|
||||
expressionProcessor.scope,
|
||||
moduleScope,
|
||||
body,
|
||||
makeSection(methodDef.location),
|
||||
cons,
|
||||
methodDef.methodName.name
|
||||
)
|
||||
val callTarget = Truffle.getRuntime.createCallTarget(rootNode)
|
||||
new RuntimeFunction(
|
||||
callTarget,
|
||||
null,
|
||||
new FunctionSchema(arguments: _*)
|
||||
)
|
||||
case _ =>
|
||||
throw new CompilerError(
|
||||
"Conversion bodies must be functions at the point of codegen."
|
||||
)
|
||||
}
|
||||
moduleScope.registerMethod(cons, methodDef.methodName.name, function)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -215,6 +215,64 @@ class RuntimeInstrumentTest
|
||||
)
|
||||
}
|
||||
|
||||
it should "instrument conversion methods" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
val moduleName = "Enso_Test.Test.Main"
|
||||
val fooTypeName = s"$moduleName.Foo"
|
||||
|
||||
val metadata = new Metadata
|
||||
val mainBody = metadata.addItem(52, 12)
|
||||
|
||||
val code =
|
||||
"""type Foo
|
||||
|type Bar
|
||||
|
|
||||
|Foo.from (_ : Bar) = Foo
|
||||
|
|
||||
|main = Foo.from Bar
|
||||
|""".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 the new 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, "Enso_Test.Test.Main", "main"),
|
||||
None,
|
||||
Vector()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
context.receive(3) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
TestMessages.update(
|
||||
contextId,
|
||||
mainBody,
|
||||
fooTypeName,
|
||||
Api.MethodPointer(moduleName, fooTypeName, "from")
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
}
|
||||
|
||||
it should "instrument expressions" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
|
Loading…
Reference in New Issue
Block a user