Skip to content

Commit 2da8a22

Browse files
authored
Spanned holes: threading positions through holes (#1085)
Every hole is now internally associated with a span which is printed when the hole is encountered: ```sh $ for BACKEND in chez-callcc llvm js; do effekt hole.effekt --backend $BACKEND; done ``` ```log # Chez Exception: hole.effekt:8:15: not implemented yet [error] Process exited with non-zero exit code 255. # LLVM PANIC: hole.effekt:8:15: not implemented yet [error] Process exited with non-zero exit code 1. # JS .../out/hole.js:208 else throw e ^ hole.effekt:8:15: not implemented yet (Use `node --trace-uncaught ...` to show where the exception was thrown) Node.js v22.16.0 [error] Process exited with non-zero exit code 1. ```
1 parent f6a7196 commit 2da8a22

31 files changed

+55
-48
lines changed

effekt/jvm/src/test/scala/effekt/core/PatternMatchingTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class PatternMatchingTests extends CoreTests {
4747
}
4848

4949
test("Sanity check: compiling empty list of clauses") {
50-
assertEquals(compile(Nil), core.Hole())
50+
assertEquals(compile(Nil), core.Hole(effekt.source.Span.missing))
5151
}
5252

5353
test("Simple guard") {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class CoreParsers(names: Names) extends EffektLexers {
298298
}
299299
| (`if` ~> `(` ~/> pure <~ `)`) ~ stmt ~ (`else` ~> stmt) ^^ Stmt.If.apply
300300
| `region` ~> blockLit ^^ Stmt.Region.apply
301-
| `<>` ^^^ Hole()
301+
| `<>` ^^^ Hole(effekt.source.Span.missing)
302302
| (pure <~ `match`) ~/ (`{` ~> many(clause) <~ `}`) ~ (`else` ~> stmt).? ^^ Stmt.Match.apply
303303
)
304304

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ object PatternMatchingCompiler {
8686
*/
8787
def compile(clauses: List[Clause]): core.Stmt = {
8888
// This shouldn't be reachable anymore since we specialize matching on void before calling compile
89-
if (clauses.isEmpty) return core.Hole()
89+
if (clauses.isEmpty) return core.Hole(effekt.source.Span.missing)
9090

9191
// (0) normalize clauses
9292
val normalized @ (headClause :: remainingClauses) = clauses.map(normalize) : @unchecked

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ object PolymorphismBoxing extends Phase[CoreTransformed, CoreTransformed] {
269269
val boxedResult = transformArg(originalResult)
270270
coerce(Stmt.Region(BlockLit(tparams, cparams, vparams, bparams, coerce(body, boxedResult))), originalResult)
271271
}
272-
case Stmt.Hole() => Stmt.Hole()
272+
case Stmt.Hole(span) => Stmt.Hole(span)
273273
}
274274

275275
def transform(expr: Expr)(using Context, DeclarationContext): Bind[Expr] = expr match {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ object PrettyPrinter extends ParenPrettyPrinter {
235235
val d = default.map { body => space <> "else" <+> braces(nest(line <> toDocStmts(body))) }.getOrElse { emptyDoc }
236236
toDoc(sc) <+> "match" <+> cs <> d
237237

238-
case Hole() =>
239-
"<>"
238+
case Hole(span) =>
239+
"<>" <+> s"// @ ${span.range.from.format}"
240240
}
241241

242242
def toDoc(tpe: core.BlockType): Doc = tpe match {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class Recursive(
8383
case Stmt.Shift(prompt, body) => process(prompt); process(body)
8484
case Stmt.Resume(k, body) => process(k); process(body)
8585
case Stmt.Region(body) => process(body)
86-
case Stmt.Hole() => ()
86+
case Stmt.Hole(span) => ()
8787
}
8888

8989
def process(e: Expr): Unit = e match {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
470470
Context.bind(Region(BlockLit(Nil, List(region.capture), Nil, List(cap), transform(body))))
471471

472472
case source.Hole(id, stmts, span) =>
473-
Context.bind(core.Hole())
473+
Context.bind(core.Hole(span))
474474

475475
case a @ source.Assign(id, expr, _) =>
476476
val sym = a.definition

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ enum Stmt extends Tree {
303303
case Resume(k: BlockVar, body: Stmt)
304304

305305
// Others
306-
case Hole()
306+
case Hole(span: effekt.source.Span)
307307

308308
val tpe: ValueType = Type.inferType(this)
309309
val capt: Captures = Type.inferCapt(this)
@@ -637,7 +637,7 @@ object Variables {
637637
case Stmt.Reset(body) => free(body)
638638
case Stmt.Shift(prompt, body) => free(prompt) ++ free(body)
639639
case Stmt.Resume(k, body) => free(k) ++ free(body)
640-
case Stmt.Hole() => Variables.empty
640+
case Stmt.Hole(span) => Variables.empty
641641
}
642642

643643
def bound(t: ValueParam): Variables = Variables.value(t.id, t.tpe)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ object Type {
225225
}
226226
case Stmt.Region(body) => body.returnType
227227

228-
case Stmt.Hole() => TBottom
228+
case Stmt.Hole(span) => TBottom
229229
}
230230

231231
def inferCapt(stmt: Stmt): Captures = stmt match {
@@ -245,7 +245,7 @@ object Type {
245245
case Stmt.Shift(prompt, body) => prompt.capt ++ body.capt
246246
case Stmt.Resume(k, body) => k.capt ++ body.capt
247247
case Stmt.Region(body) => body.capt
248-
case Stmt.Hole() => Set.empty
248+
case Stmt.Hole(span) => Set.empty
249249
}
250250

251251
def inferType(expr: Expr): ValueType = expr match {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ object BindSubexpressions {
8686
case Stmt.Reset(body) => Stmt.Reset(transform(body))
8787
case Stmt.Shift(prompt, body) => Stmt.Shift(transform(prompt), transform(body))
8888
case Stmt.Resume(k, body) => Stmt.Resume(transform(k), transform(body))
89-
case Stmt.Hole() => Stmt.Hole()
89+
case Stmt.Hole(span) => Stmt.Hole(span)
9090
}
9191

9292
def transform(b: Block)(using Env): Bind[Block] = b match {

0 commit comments

Comments
 (0)