Skip to content

Commit 5b81a6e

Browse files
authored
Do not flatten namespaces (#1074)
Flattening namespaces is annoying for documentation generation because information gets lost and somehow needs to get reconstructed (for example with scope annotations). Now we do not flatten namespaces anymore. One case is still missing but interestingly we also get a segfault in LLVM, no idea why. Additionally, we also deprecate namespace definitions nested in function definitions. Closes #1037.
1 parent a2534b9 commit 5b81a6e

File tree

9 files changed

+30
-60
lines changed

9 files changed

+30
-60
lines changed

effekt/jvm/src/test/scala/effekt/ParserTests.scala

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -934,22 +934,22 @@ class ParserTests extends munit.FunSuite {
934934
|val y = 5
935935
|""".stripMargin)
936936

937-
val nested = parseDefinitions(
937+
val nested = parseToplevel(
938938
"""namespace list {
939939
| val x = 4
940940
| val y = 5
941941
|}
942942
|""".stripMargin)
943943

944-
val semi = parseDefinitions(
944+
val semi = parseToplevel(
945945
"""namespace list;
946946
|val x = 4
947947
|val y = 5
948948
|""".stripMargin)
949949

950950
assertEqualModuloSpans(nested, semi)
951951

952-
val nested2 = parseDefinitions(
952+
val nested2 = parseProgram(
953953
"""namespace list {
954954
| namespace internal {
955955
|
@@ -959,32 +959,15 @@ class ParserTests extends munit.FunSuite {
959959
|}
960960
|""".stripMargin)
961961

962-
val semi2 = parseDefinitions(
963-
"""namespace list;
964-
|namespace internal;
965-
|
966-
|val x = 4
967-
|val y = 5
968-
|""".stripMargin)
969-
970-
val semiInsertion = parseDefinitions(
962+
val semi2 = parseProgram(
971963
"""namespace list
972964
|namespace internal
973965
|
974966
|val x = 4
975-
|val y = 5
967+
|val y = 5;
976968
|""".stripMargin)
977969

978-
assertEqualModuloSpans(nested2, semi2)
979-
assertEqualModuloSpans(nested2, semiInsertion)
980-
981-
parseDefinitions(
982-
"""val x = {
983-
| namespace foo;
984-
| val y = 4;
985-
| foo::y
986-
|}
987-
|""".stripMargin)
970+
(nested2.defs zip semi2.defs).foreach(assertEqualModuloSpans)
988971
}
989972

990973
test("Definitions") {
@@ -1238,24 +1221,6 @@ class ParserTests extends munit.FunSuite {
12381221
assertEquals(varDef.span, span)
12391222
}
12401223

1241-
test("Namespace definition parses with correct span") {
1242-
val (source, span) =
1243-
raw"""namespace Foo {
1244-
|↑
1245-
|}
1246-
|↑""".sourceAndSpan
1247-
1248-
val definition = parseDefinition(source.content)
1249-
1250-
val nsDef = definition match {
1251-
case nd@NamespaceDef(id, defs, doc, span) => nd
1252-
case other =>
1253-
throw new IllegalArgumentException(s"Expected NamespaceDef but got ${other.getClass.getSimpleName}")
1254-
}
1255-
1256-
assertEquals(nsDef.span, span)
1257-
}
1258-
12591224
test("Interface definition parses with correct span") {
12601225
val (source, span) =
12611226
raw"""interface IBar {}

effekt/shared/src/main/scala/effekt/Parser.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
459459
}
460460

461461
def isDefinition: Boolean = peek.kind match {
462-
case `val` | `def` | `type` | `effect` | `namespace` => true
462+
case `val` | `def` | `type` | `effect` => true
463463
case `interface` | `type` | `record` =>
464464
val kw = peek.kind
465465
fail(s"Only supported on the toplevel: ${kw.toString} declaration.")
@@ -473,7 +473,6 @@ class Parser(positions: Positions, tokens: Seq[Token], source: Source) {
473473
case `def` => defDef(info)
474474
case `type` => typeOrAliasDef(info)
475475
case `effect` => effectDef(info)
476-
case `namespace` => namespaceDef(info)
477476
case _ => fail("Expected definition")
478477
}
479478

effekt/shared/src/main/scala/effekt/Typer.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,9 @@ object Typer extends Phase[NameResolved, Typechecked] {
767767
Context.bind(field, tpe, CaptureSet())
768768
}
769769

770+
case d @ source.NamespaceDef(name, defs, doc, span) =>
771+
defs.map(precheckDef)
772+
770773
case d: source.TypeDef => wellformed(d.symbol.tpe)
771774
case d: source.EffectDef => wellformed(d.symbol.effs)
772775

@@ -929,6 +932,11 @@ object Typer extends Phase[NameResolved, Typechecked] {
929932
Result((), Pure)
930933
}
931934

935+
case d @ source.NamespaceDef(name, defs, doc, span) =>
936+
defs.map(synthDef).reduceLeft {
937+
case (Result(_, effs), Result(_, acc)) => Result((), effs ++ acc)
938+
}
939+
932940
// all other definitions have already been prechecked
933941
case d =>
934942
Result((), Pure)

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,12 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
125125
case e @ source.ExternInclude(ff, path, contents, _, doc, span) =>
126126
List(Extern.Include(ff, contents.get))
127127

128+
case d @ source.NamespaceDef(name, defs, doc, span) =>
129+
defs.flatMap(transformToplevel)
130+
128131
// For now we forget about all of the following definitions in core:
129132
case d: source.Def.Extern => Nil
130133
case d: source.Def.Alias => Nil
131-
132-
case d: source.Def.NamespaceDef => Context.panic("Should have been removed by BoxUnboxInference")
133134
}
134135

135136
/**
@@ -201,11 +202,10 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
201202

202203
case d: source.Def.Extern => Context.panic("Only allowed on the toplevel")
203204
case d: source.Def.Declaration => Context.panic("Only allowed on the toplevel")
205+
case d: source.Def.NamespaceDef => Context.panic("Only allowed on the toplevel")
204206

205207
// For now we forget about all of the following definitions in core:
206208
case d: source.Def.Alias => transform(rest)
207-
208-
case d: source.Def.NamespaceDef => Context.panic("Should have been removed by BoxUnboxInference")
209209
}
210210
}
211211

effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] {
2020

2121
def rewrite(e: ModuleDecl)(using C: Context): ModuleDecl = visit(e) {
2222
case ModuleDecl(path, imports, defs, doc, span) =>
23-
ModuleDecl(path, imports, defs.flatMap(flattenNamespaces), doc, span)
23+
ModuleDecl(path, imports, defs.map(rewrite), doc, span)
2424
}
2525

2626
/**
@@ -125,11 +125,6 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] {
125125
}
126126
}
127127

128-
def flattenNamespaces(t: Def)(using C: Context): List[Def] = t match {
129-
case Def.NamespaceDef(name, defs, doc, span) => defs.flatMap(flattenNamespaces)
130-
case d => List(rewrite(d))
131-
}
132-
133128
def rewrite(t: Def)(using C: Context): Def = visit(t) {
134129

135130
case FunDef(id, tparams, vparams, bparams, ret, body, doc, span) =>
@@ -156,6 +151,9 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] {
156151
}
157152
DefDef(id, annot, block, doc, span)
158153

154+
case NamespaceDef(name, defs, doc, span) =>
155+
NamespaceDef(name, defs.map(rewrite), doc, span)
156+
159157
case d: InterfaceDef => d
160158
case d: DataDef => d
161159
case d: RecordDef => d
@@ -167,13 +165,11 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] {
167165
case d: ExternResource => d
168166
case d: ExternInterface => d
169167
case d: ExternInclude => d
170-
171-
case d: NamespaceDef => Context.panic("Should have been removed by flattenNamespaces")
172168
}
173169

174170
def rewrite(t: Stmt)(using C: Context): Stmt = visit(t) {
175171
case DefStmt(d, rest, span) =>
176-
flattenNamespaces(d).foldRight(rewrite(rest)) { case (d, rest) => DefStmt(d, rest, span) }
172+
DefStmt(rewrite(d), rewrite(rest), span)
177173

178174
case ExprStmt(e, rest, span) =>
179175
ExprStmt(rewriteAsExpr(e), rewrite(rest), span)

examples/neg/namer/functions.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[error] examples/neg/namer/functions.effekt:3:3: Expected statements but got keyword namespace
2+
namespace nested {
3+
^^^^^^^^^

examples/pos/namer/functions.effekt renamed to examples/neg/namer/functions.effekt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ def somefunction() = {
1111
def main() = somefunction() match {
1212
case list::Cons(msg, _) => println(msg)
1313
case _ => ()
14-
}
14+
}

examples/pos/bidirectional/typeparametric.effekt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern interface Cap[U, V]
33
extern pure def cap[U, V](): Cap[U, V] at {} =
44
js "42"
55
chez "42"
6-
llvm "ret %Pos undef"
6+
llvm "ret %Pos zeroinitializer"
77

88
interface Foo[S] {
99
def op[A]() {f: Cap[S, A]}: Cap[S, A] at {f} / { Exception[S] }
@@ -21,4 +21,4 @@ def main() = {
2121
resume { {g: Cap[Int, B]} => do raise(42, "") }
2222
}
2323
}
24-
}
24+
}

examples/pos/namer/functions.check

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)