Skip to content

Commit 32abb70

Browse files
Keep information about extern data types (#1296)
We were throwing away information about extern data types when transforming to core. This info is relevant for some Core -> Core phases (like Monomorphization #1024), so we know whether a type is Extern instead of guessing.
1 parent 74652cd commit 32abb70

10 files changed

Lines changed: 45 additions & 13 deletions

File tree

effekt/shared/src/main/scala/effekt/core/DeclarationContext.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class DeclarationContext(
2222
case d: Extern.Def => (d.id.name.name, d.vparams.map(_.tpe)) -> d
2323
}.toMap
2424

25+
lazy val externDatas: Map[Id, Extern.Data] = externs.collect {
26+
case d: Extern.Data => d.id -> d
27+
}.toMap
28+
2529
// Maps to speed-up lookup. Assumes that, if we ever lookup a Constructor/Field/Interface/...,
2630
// we will eventually lookup most of them (and caches all in a respective map).
2731

@@ -77,6 +81,8 @@ class DeclarationContext(
7781
def findExternDef(id: Id): Option[Extern.Def] = externDefs.get(id)
7882
def findExternDef(name: String, params: List[ValueType]): Option[Extern.Def] = externDefsName.get((name, params))
7983

84+
def findExternData(id: Id): Option[Extern.Data] = externDatas.get(id)
85+
8086
def getDeclaration(id: Id)(using context: ErrorReporter): Declaration = findDeclaration(id).getOrElse {
8187
context.panic(s"No declaration found for ${id}.")
8288
}
@@ -116,6 +122,9 @@ class DeclarationContext(
116122
def getExternDef(id: Id)(using context: ErrorReporter): Extern.Def = findExternDef(id).getOrElse{
117123
context.panic(s"No extern definition found for ${id}")
118124
}
125+
def getExternData(id: Id)(using context: ErrorReporter): Extern.Data = findExternData(id).getOrElse{
126+
context.panic(s"No extern data found for ${id}")
127+
}
119128

120129
extension(field: Field) {
121130
def constructor(using context: ErrorReporter): Constructor = getConstructor(field)

effekt/shared/src/main/scala/effekt/core/PrettyPrinter.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ class PrettyPrinter(printDetails: Boolean, printInternalIds: Boolean = true) ext
8282
case ExternBody.Unsupported(err) => ???
8383
})
8484
case Extern.Include(ff, contents) => "extern" <+> toDoc(ff) <+> stringLiteral(contents)
85+
case Extern.Data(id, tps) => "extern type" <+> toDoc(id) <> typeParamsDoc(tps)
8586
}
8687

8788
def toDoc(ff: FeatureFlag): Doc = ff match {

effekt/shared/src/main/scala/effekt/core/TestRenamer.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ class TestRenamer(names: Names = Names(Map.empty), prefix: String = "$", preserv
201201
case Extern.Include(featureFlag, contents) => {
202202
Extern.Include(featureFlag, contents)
203203
}
204+
case Extern.Data(id, tparams) => {
205+
withBindings(tparams) {
206+
Extern.Data(rewrite(id), tparams map rewrite)
207+
}
208+
}
204209
}
205210

206211
override def rewrite(c: Constructor) = c match {
@@ -283,6 +288,7 @@ class TestRenamer(names: Names = Names(Map.empty), prefix: String = "$", preserv
283288
} ++ definitions.map(_.id) ++ externs.flatMap {
284289
case Extern.Def(id, _, _, _, _, _, _, _) => Some(id)
285290
case Extern.Include(_, _) => None
291+
case Extern.Data(id, _) => Some(id)
286292
}
287293
}
288294
}

effekt/shared/src/main/scala/effekt/core/Transformer.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
121121
case d @ source.NamespaceDef(name, defs, doc, span) =>
122122
defs.flatMap(transformToplevel)
123123

124+
case e @ source.ExternType(id, _, _, _) =>
125+
val sym@ExternType(name, tps, _) = e.symbol
126+
List(Extern.Data(sym, tps))
127+
124128
// For now we forget about all of the following definitions in core:
125129
case d: source.Def.Extern => Nil
126130
case d: source.Def.Alias => Nil

effekt/shared/src/main/scala/effekt/core/Tree.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ case class Property(id: Id, tpe: BlockType) extends Tree
132132
* FFI external definitions
133133
*/
134134
enum Extern extends Tree {
135+
case Data(id: Id, tparams: List[Id])
135136
case Def(id: Id, tparams: List[Id], cparams: List[Id], vparams: List[ValueParam], bparams: List[BlockParam], ret: ValueType, annotatedCapture: Captures, body: ExternBody)
136137
case Include(featureFlag: FeatureFlag, contents: String)
137138
}
@@ -692,6 +693,7 @@ object Tree {
692693
Extern.Def(rewrite(id), tparams.map(rewrite), cparams.map(rewrite), vparams.map(rewrite), bparams.map(rewrite),
693694
rewrite(ret), rewrite(annotatedCapture), rewrite(body).run())
694695
case Extern.Include(featureFlag, contents) => e
696+
case Extern.Data(id, tparams) => Extern.Data(rewrite(id), tparams.map(rewrite))
695697
}
696698

697699
def rewrite(d: Declaration): Declaration = d match {

effekt/shared/src/main/scala/effekt/core/Type.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ object Type {
378378
wellformed(free)
379379

380380
case Extern.Include(featureFlag, contents) => ()
381+
case Extern.Data(id, tparams) => ()
381382
}
382383
}
383384

effekt/shared/src/main/scala/effekt/core/optimizer/Deadcode.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class Deadcode(reachable: Map[Id, Usage])
5050
// We need to keep "show", "showBuiltin" & "infixConcat" for generating show definitions (see #1123)
5151
case e: Extern.Def if used(e.id) || List("show", "showBuiltin", "infixConcat").contains(e.id.name.name) => e
5252
case e: Extern.Include => e
53+
// We currently do not have usage information on extern types, so we have to keep all of them
54+
case e: Extern.Data => e
5355
},
5456
// drop unreachable definitions
5557
definitions.collect { case d if used(d.id) => rewrite(d) },

effekt/shared/src/main/scala/effekt/cps/Transformer.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object Transformer {
2323
def transform(module: core.ModuleDecl): ModuleDecl = module match {
2424
case core.ModuleDecl(path, includes, declarations, externs, definitions, exports) =>
2525
given TransformationContext(Map.empty, Map.empty)
26-
ModuleDecl(path, includes, declarations, externs.map(transform), definitions.map(transformToplevel), exports)
26+
ModuleDecl(path, includes, declarations, externs.flatMap(transform), definitions.map(transformToplevel), exports)
2727
}
2828

2929
def transformToplevel(definition: core.Toplevel)(using TransformationContext): ToplevelDefinition = definition match {
@@ -34,10 +34,11 @@ object Transformer {
3434
ToplevelDefinition.Val(id, ks, k, transform(stmt, ks, Continuation.Dynamic(k)))
3535
}
3636

37-
def transform(extern: core.Extern)(using TransformationContext): Extern = extern match {
37+
def transform(extern: core.Extern)(using TransformationContext): Option[Extern] = extern match {
3838
case core.Extern.Def(id, tparams, cparams, vparams, bparams, ret, annotatedCapture, body) =>
39-
Extern.Def(id, vparams.map(_.id), bparams.map(_.id), annotatedCapture.contains(symbols.builtins.AsyncCapability.capture), transform(body))
40-
case core.Extern.Include(featureFlag, contents) => Extern.Include(featureFlag, contents)
39+
Some(Extern.Def(id, vparams.map(_.id), bparams.map(_.id), annotatedCapture.contains(symbols.builtins.AsyncCapability.capture), transform(body)))
40+
case core.Extern.Include(featureFlag, contents) => Some(Extern.Include(featureFlag, contents))
41+
case core.Extern.Data(id, tparams) => None
4142
}
4243

4344
def transform(externBody: core.ExternBody)(using TransformationContext): ExternBody = externBody match {

effekt/shared/src/main/scala/effekt/generator/chez/Transformer.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ trait Transformer {
6666

6767
def toChez(module: ModuleDecl)(using ErrorReporter): List[chez.Def] = {
6868
val decls = module.declarations.flatMap(toChez)
69-
val externs = module.externs.map(toChez)
69+
val externs = module.externs.flatMap(toChez)
7070
// TODO FIXME, once there is a let _ = ... in there, we are doomed!
7171
val defns = module.definitions.map(toChez)
7272
decls ++ externs ++ defns
@@ -123,20 +123,23 @@ trait Transformer {
123123
generateConstructor(id, operations.map(op => op.id))
124124
}
125125

126-
def toChez(decl: core.Extern)(using ErrorReporter): chez.Def = decl match {
126+
def toChez(decl: core.Extern)(using ErrorReporter): Option[chez.Def] = decl match {
127127
case Extern.Def(id, tpe, cps, vps, bps, ret, capt, body) =>
128128
val tBody = body match {
129129
case ExternBody.StringExternBody(featureFlag, contents) => toChez(contents)
130130
case u: ExternBody.Unsupported =>
131131
u.report
132132
chez.Builtin("unreachable")
133133
}
134-
chez.Constant(nameDef(id),
134+
Some(chez.Constant(nameDef(id),
135135
chez.Lambda(vps.map { p => nameDef(p.id) } ++ bps.map { p => nameDef(p.id) },
136-
tBody))
136+
tBody)))
137137

138138
case Extern.Include(ff, contents) =>
139-
RawDef(contents)
139+
Some(RawDef(contents))
140+
141+
case Extern.Data(id, tparams) =>
142+
None
140143
}
141144

142145
def toChez(t: Template[core.Expr]): chez.Expr =

effekt/shared/src/main/scala/effekt/machine/Transformer.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ object Transformer {
3131
given DC: DeclarationContext = core.DeclarationContext(mod.declarations, mod.externs)
3232

3333
// collect all information
34-
val declarations = mod.externs.map(transform)
34+
val declarations = mod.externs.flatMap(transform)
3535
val definitions = mod.definitions
3636
val mainEntry = Label(mainName, Nil)
3737

@@ -54,7 +54,7 @@ object Transformer {
5454
Program(declarations, toplevelDefinitions ++ localDefinitions, mainEntry)
5555
}
5656

57-
def transform(extern: core.Extern)(using BlocksParamsContext, ErrorReporter): Declaration = extern match {
57+
def transform(extern: core.Extern)(using BlocksParamsContext, ErrorReporter): Option[Declaration] = extern match {
5858
case core.Extern.Def(name, tps, cparams, vparams, bparams, ret, capture, body) =>
5959
// TODO delete, and/or enforce at call site (ImpureApp)
6060
if bparams.nonEmpty then ErrorReporter.abort("Foreign functions currently cannot take block arguments.")
@@ -65,10 +65,13 @@ object Transformer {
6565
val transformedRet = transformUnboxed(ret)
6666
val isExternAsync = capture.contains(symbols.builtins.AsyncCapability.capture)
6767
noteDefinition(name, transformedParams, Nil, isExternAsync)
68-
Extern(transform(name), transformedParams, transformedRet, isExternAsync, transform(body))
68+
Some(Extern(transform(name), transformedParams, transformedRet, isExternAsync, transform(body)))
6969

7070
case core.Extern.Include(ff, contents) =>
71-
Include(ff, contents)
71+
Some(Include(ff, contents))
72+
73+
case core.Extern.Data(id, tparams) =>
74+
None
7275
}
7376

7477
def transform(body: core.ExternBody)(using ErrorReporter): machine.ExternBody = body match {

0 commit comments

Comments
 (0)