Skip to content

Commit 7c3d951

Browse files
Rip out kiama positions (#1097)
Completing the span transition, this PR rips out the remnants of the previously used positioning system from kiama. It also fills in all missing spans in the parser. After this PR, there are no more calls to `Span.missing` in the parser.
1 parent 5b81a6e commit 7c3d951

23 files changed

+238
-280
lines changed

effekt/js/src/main/scala/effekt/LanguageServer.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import effekt.util.{PlainMessaging, getOrElseAborting}
66
import effekt.util.messages.{BufferedMessaging, EffektError, EffektMessaging, FatalPhaseError}
77
import effekt.util.paths.*
88
import effekt.generator.js.JavaScriptWeb
9-
import kiama.util.{Messaging, Position, Positions, Severities, Source, StringSource}
9+
import kiama.util.{Messaging, Position, Severities, Source, StringSource}
1010

1111
import scala.scalajs.js
1212
import scala.scalajs.js.JSConverters.*
@@ -58,12 +58,9 @@ object lsp {
5858
* A language server to be run in a webworker
5959
*/
6060
class LanguageServer extends Intelligence {
61-
62-
val positions: Positions = new Positions
63-
6461
object config extends EffektConfig
6562

66-
implicit object context extends Context(positions) with VirtualModuleDB {
63+
implicit object context extends Context with VirtualModuleDB {
6764
object messaging extends PlainMessaging
6865
}
6966

effekt/jvm/src/main/scala/effekt/Driver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ trait Driver extends kiama.util.Compiler[EffektConfig, EffektError] { outer =>
2525
// Compiler context
2626
// ================
2727
// We always only have one global instance of the compiler
28-
object context extends Context(positions) with IOModuleDB { val messaging = outer.messaging }
28+
object context extends Context with IOModuleDB { val messaging = outer.messaging }
2929

3030
override def createConfig(args: Seq[String]) =
3131
new EffektConfig(args)

effekt/jvm/src/main/scala/effekt/Repl.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
5555
*/
5656
override def parse(source: Source): ParseResult[Tree] = {
5757
val tokens = effekt.lexer.Lexer.lex(source)
58-
val parser = new Parser(context.positions, tokens, source)
58+
val parser = new Parser(tokens, source)
5959
parser.parseRepl(Input(source, 0))
6060
}
6161

effekt/jvm/src/main/scala/effekt/Server.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ class Server(config: EffektConfig, compileOnChange: Boolean=false) extends Langu
289289
decl <- getSourceTreeFor(sym)
290290
kind <- getSymbolKind(sym)
291291
detail <- getInfoOf(sym)(using context)
292-
declRange = convertRange(positions.getStart(decl), positions.getFinish(decl))
293-
idRange = convertRange(positions.getStart(id), positions.getFinish(id))
292+
declRange = convertRange(decl.span.range)
293+
idRange = convertRange(id.span.range)
294294
} yield new DocumentSymbol(sym.name.name, kind, declRange, idRange, detail.header)
295295

296296
val result = Collections.seqToJavaList(
@@ -332,7 +332,7 @@ class Server(config: EffektConfig, compileOnChange: Boolean=false) extends Langu
332332
fromLSPPosition(params.getPosition, source)
333333
};
334334
definition <- getDefinitionAt(position)(using context);
335-
location = locationOfNode(positions, definition)
335+
location = rangeToLocation(definition.span.range)
336336
} yield location
337337

338338
val result = location.map(l => messages.Either.forLeft[util.List[_ <: Location], util.List[_ <: LocationLink]](Collections.seqToJavaList(List(l))))
@@ -358,7 +358,7 @@ class Server(config: EffektConfig, compileOnChange: Boolean=false) extends Langu
358358
// getContext may be null!
359359
includeDeclaration = Option(params.getContext).exists(_.isIncludeDeclaration)
360360
allRefs = if (includeDeclaration) tree :: refs else refs
361-
locations = allRefs.map(ref => locationOfNode(positions, ref))
361+
locations = allRefs.map(ref => rangeToLocation(ref.span.range))
362362
} yield locations
363363

364364
CompletableFuture.completedFuture(Collections.seqToJavaList(locations.getOrElse(Seq[Location]())))
@@ -479,12 +479,12 @@ class Server(config: EffektConfig, compileOnChange: Boolean=false) extends Langu
479479
if holeTpe == contentTpe
480480
res <- stmt match {
481481
case source.Return(exp, _) => for {
482-
text <- positions.textOf(exp)
482+
text <- exp.span.text
483483
} yield EffektCodeAction("Close hole", hole.span, text)
484484

485485
// <{ ${s1 ; s2; ...} }>
486486
case _ => for {
487-
text <- positions.textOf(stmt)
487+
text <- stmt.span.text
488488
} yield EffektCodeAction("Close hole", hole.span, s"locally { ${text} }")
489489
}
490490
} yield res

effekt/jvm/src/test/scala/effekt/ConstraintTests.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package effekt
22
package typer
33
package constraints
44

5-
import effekt.context.Context
65
import effekt.source.NoSource
76
import effekt.symbols.*
87
import effekt.util.messages.{DebugMessaging, ErrorReporter, FatalPhaseError}
9-
import kiama.util.Positions
108
import effekt.core.TestContext
119

1210
import scala.language.implicitConversions
@@ -15,7 +13,7 @@ abstract class ConstraintTests extends munit.FunSuite {
1513

1614
object messages extends DebugMessaging
1715

18-
given ErrorReporter with { var focus = NoSource; val messaging = messages; val positions = new Positions }
16+
given ErrorReporter with { var focus = NoSource; val messaging = messages }
1917

2018
lazy val scope = { val s = new TestContext; s.enterScope(); s }
2119

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

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package effekt
22

33
import effekt.lexer.TokenKind.*
4-
import effekt.lexer.{Lexer, Token, TokenKind}
4+
import effekt.lexer.{Token, TokenKind}
55
import effekt.source.*
66
import effekt.source.Origin.Synthesized
7-
import kiama.util.{Positions, Source, StringSource}
7+
import kiama.util.{Source, StringSource}
88
import munit.Location
99

1010
// DSL for creating code snippets with span annotations
@@ -69,16 +69,16 @@ object SpanSyntax {
6969

7070
class ParserTests extends munit.FunSuite {
7171

72-
def parser(input: String, positions: Positions)(using munit.Location): Parser = {
72+
def parser(input: String)(using munit.Location): Parser = {
7373
val source = StringSource(input, "")
7474
val tokens = effekt.lexer.Lexer.lex(source)
7575
// TODO catch LexerError exception?
76-
new Parser(positions, tokens, source)
76+
new Parser(tokens, source)
7777
}
7878

79-
def parse[R](input: String, f: Parser => R, positions: Positions = new Positions())(using munit.Location): R =
79+
def parse[R](input: String, f: Parser => R)(using munit.Location): R =
8080
try {
81-
val p = parser(input, positions)
81+
val p = parser(input)
8282
val result = f(p)
8383
assert(p.peek(TokenKind.EOF), s"Did not consume everything: ${p.peek}")
8484
result
@@ -87,64 +87,64 @@ class ParserTests extends munit.FunSuite {
8787
fail(s"Unexpected parse error (token index ${pos}): ${msg}")
8888
}
8989

90-
def parseExpr(input: String, positions: Positions = new Positions())(using munit.Location): Term =
90+
def parseExpr(input: String)(using munit.Location): Term =
9191
parse(input, _.expr())
9292

93-
def parseStmt(input: String, positions: Positions = new Positions())(using munit.Location): Stmt =
93+
def parseStmt(input: String)(using munit.Location): Stmt =
9494
parse(input, _.stmt())
9595

96-
def parseStmts(input: String, positions: Positions = new Positions())(using munit.Location): Stmt =
96+
def parseStmts(input: String)(using munit.Location): Stmt =
9797
parse(input, _.stmts(inBraces = true))
9898

99-
def parseMatchPattern(input: String, positions: Positions = new Positions())(using munit.Location): MatchPattern =
99+
def parseMatchPattern(input: String)(using munit.Location): MatchPattern =
100100
parse(input, _.matchPattern())
101101

102-
def parseMatchClause(input: String, positions: Positions = new Positions())(using munit.Location): MatchClause =
102+
def parseMatchClause(input: String)(using munit.Location): MatchClause =
103103
parse(input, _.matchClause())
104104

105-
def parseValueTypeAnnotation(input: String, positions: Positions = new Positions())(using munit.Location): ValueType =
105+
def parseValueTypeAnnotation(input: String)(using munit.Location): ValueType =
106106
parse(input, _.valueTypeAnnotation())
107107

108-
def parseReturnAnnotation(input: String, positions: Positions = new Positions())(using munit.Location): Effectful =
108+
def parseReturnAnnotation(input: String)(using munit.Location): Effectful =
109109
parse(input, _.returnAnnotation())
110110

111-
def parseValueType(input: String, positions: Positions = new Positions())(using munit.Location): ValueType =
111+
def parseValueType(input: String)(using munit.Location): ValueType =
112112
parse(input, _.valueType())
113113

114-
def parseBlockType(input: String, positions: Positions = new Positions())(using munit.Location): BlockType =
114+
def parseBlockType(input: String)(using munit.Location): BlockType =
115115
parse(input, _.blockType())
116116

117-
def parseOpClause(input: String, positions: Positions = new Positions())(using munit.Location): OpClause =
117+
def parseOpClause(input: String)(using munit.Location): OpClause =
118118
parse(input, _.opClause())
119119

120-
def parseImplementation(input: String, positions: Positions = new Positions())(using munit.Location): Implementation =
120+
def parseImplementation(input: String)(using munit.Location): Implementation =
121121
parse(input, _.implementation())
122122

123-
def parseTry(input: String, positions: Positions = new Positions())(using munit.Location): Term =
123+
def parseTry(input: String)(using munit.Location): Term =
124124
parse(input, _.tryExpr())
125125

126-
def parseParams(input: String, positions: Positions = new Positions())(using munit.Location): (Many[Id], Many[ValueParam], Many[BlockParam]) =
126+
def parseParams(input: String)(using munit.Location): (Many[Id], Many[ValueParam], Many[BlockParam]) =
127127
parse(input, _.params())
128128

129-
def parseLambdaParams(input: String, positions: Positions = new Positions())(using munit.Location): (List[Id], List[ValueParam], List[BlockParam]) =
129+
def parseLambdaParams(input: String)(using munit.Location): (List[Id], List[ValueParam], List[BlockParam]) =
130130
parse(input, _.lambdaParams())
131131

132-
def parseDefinition(input: String, positions: Positions = new Positions())(using munit.Location): Def =
132+
def parseDefinition(input: String)(using munit.Location): Def =
133133
parse(input, _.definition())
134134

135-
def parseDefinitions(input: String, positions: Positions = new Positions())(using munit.Location): List[Def] =
135+
def parseDefinitions(input: String)(using munit.Location): List[Def] =
136136
parse(input, _.definitions())
137137

138-
def parseToplevel(input: String, positions: Positions = new Positions())(using munit.Location): Def =
138+
def parseToplevel(input: String)(using munit.Location): Def =
139139
parse(input, _.toplevel())
140140

141-
def parseProgram(input: String, positions: Positions = new Positions())(using munit.Location): ModuleDecl =
141+
def parseProgram(input: String)(using munit.Location): ModuleDecl =
142142
parse(input, _.program())
143143

144-
def parseExternDef(input: String, positions: Positions = new Positions())(using munit.Location): Def =
144+
def parseExternDef(input: String)(using munit.Location): Def =
145145
parse(input, _.externDef())
146146

147-
def parseInfo(input: String, positions: Positions = new Positions())(using munit.Location): Info =
147+
def parseInfo(input: String)(using munit.Location): Info =
148148
parse(input, _.info(parseCaptures = true))
149149

150150
// Custom asserts
@@ -251,7 +251,7 @@ class ParserTests extends munit.FunSuite {
251251
test("Peeking") {
252252
implicit def toToken(t: TokenKind): Token = Token(0, 0, t)
253253
def peek(tokens: Seq[Token], offset: Int): Token =
254-
new Parser(new Positions, tokens, StringSource("", "test")).peek(offset)
254+
new Parser(tokens, StringSource("", "test")).peek(offset)
255255

256256
val tokens = List[Token](`(`, Space, Newline, `)`, Space, `=>`, EOF)
257257
assertEquals(peek(tokens, 0).kind, `(`)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package effekt.core
22

33
import effekt.context.{Context, ModuleDB}
4-
import kiama.util.Positions
54
import kiama.util.Source
65
import effekt.util.messages.DebugMessaging
76
import scala.collection.immutable.Map
@@ -45,7 +44,7 @@ trait TestModuleDB extends ModuleDB { self: Context =>
4544
override def findSource(modulePath: String): Option[Source] = sources.get(modulePath)
4645
}
4746

48-
class TestContext extends Context(new Positions) with TestModuleDB {
47+
class TestContext extends Context with TestModuleDB {
4948

5049
object messaging extends DebugMessaging
5150
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ class VMTests extends munit.FunSuite {
99
import effekt.context.{ Context, IOModuleDB }
1010
import effekt.util.PlainMessaging
1111
import effekt.generator.vm.VM
12-
import kiama.util.{ Positions, StringSource, FileSource }
12+
import kiama.util.{StringSource, FileSource }
1313

1414

15-
val positions = new Positions
1615
object plainMessaging extends PlainMessaging
17-
object context extends Context(positions) with IOModuleDB {
16+
object context extends Context with IOModuleDB {
1817
val messaging = plainMessaging
1918
object frontend extends generator.vm.VM
2019
override lazy val compiler = frontend.asInstanceOf

effekt/shared/src/main/scala/effekt/Compiler.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import effekt.source.{AnnotateCaptures, ExplicitCapabilities, ModuleDecl, Resolv
88
import effekt.symbols.Module
99
import effekt.typer.{BoxUnboxInference, Typer, Wellformedness}
1010
import effekt.util.messages.{CompilerPanic, FatalPhaseError}
11-
import effekt.util.{SourceTask, Task, VirtualSource, paths}
11+
import effekt.util.paths
1212
import kiama.output.PrettyPrinterTypes.Document
13-
import kiama.util.{Positions, Source}
13+
import kiama.util.Source
1414

1515
import scala.language.postfixOps
1616

@@ -313,7 +313,6 @@ trait Compiler[Executable] {
313313

314314
// Helpers
315315
// -------
316-
import effekt.util.paths.file
317316

318317
/**
319318
* Path relative to the output folder

effekt/shared/src/main/scala/effekt/Intelligence.scala

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package effekt
22

33
import effekt.context.{Annotations, Context}
4-
import effekt.source.{FunDef, Include, Maybe, ModuleDecl, Span, Tree, Doc}
4+
import effekt.source.Origin.Missing
5+
import effekt.source.{Doc, FunDef, Include, Maybe, ModuleDecl, Span, Tree}
56
import effekt.symbols.{CaptureSet, Hole}
67
import kiama.util.{Position, Source}
78
import effekt.symbols.scopes.Scope
89
import effekt.source.sourceOf
10+
import effekt.source.Spans
911

1012
trait Intelligence {
1113

@@ -49,15 +51,14 @@ trait Intelligence {
4951
.replace("\\n", "\n")
5052

5153
private def sortByPosition(trees: Vector[Tree])(using C: Context): Vector[Tree] =
52-
val pos = C.positions
5354
trees.sortWith {
5455
(t1, t2) =>
55-
val p1s = pos.getStart(t1).get
56-
val p2s = pos.getStart(t2).get
56+
val p1s = t1.span.from
57+
val p2s = t2.span.from
5758

5859
if (p2s == p1s) {
59-
val p1e = pos.getFinish(t1).get
60-
val p2e = pos.getFinish(t2).get
60+
val p1e = t1.span.to
61+
val p2e = t1.span.to
6162
p1e < p2e
6263
} else {
6364
p2s < p1s
@@ -68,15 +69,15 @@ trait Intelligence {
6869
decl <- C.compiler.getAST(position.source)
6970
tree = new EffektTree(decl)
7071
allTrees = tree.nodes.collect { case t: Tree => t }
71-
trees = C.positions.findNodesContaining(allTrees, position)
72+
trees = Spans.findNodesContaining(allTrees, position)
7273
nodes = sortByPosition(trees)
7374
} yield nodes
7475

7576
def getTreesInRange(range: kiama.util.Range)(using C: Context): Option[Vector[Tree]] = for {
7677
decl <- C.compiler.getAST(range.from.source)
7778
tree = new EffektTree(decl)
7879
allTrees = tree.nodes.collect { case t: Tree => t }
79-
trees = C.positions.findNodesInRange(allTrees, range)
80+
trees = Spans.findNodesInRange(allTrees, range)
8081
nodes = sortByPosition(trees)
8182
} yield nodes
8283

@@ -253,16 +254,14 @@ trait Intelligence {
253254
val src = range.from.source
254255
allCaptures(src).filter {
255256
// keep only captures in the current range
256-
case (t, c) => C.positions.getStart(t) match
257-
case Some(p) => p.between(range.from, range.to)
258-
case None => false
257+
case (t, c) => t.span.origin != Missing && t.span.range.from.between(range.from, range.to)
259258
}.collect {
260259
case (t: source.FunDef, c) => for {
261-
pos <- C.positions.getStart(t)
262-
} yield CaptureInfo(t.ret.span.range.from, c)
260+
pos <- if t.span.origin != Missing then Some(t.ret.span.range.from) else None
261+
} yield CaptureInfo(pos, c)
263262
case (t: source.DefDef, c) => for {
264-
pos <- C.positions.getStart(t)
265-
} yield CaptureInfo(t.annot.span.range.from, c)
263+
pos <- if t.span.origin != Missing then Some(t.annot.span.range.from) else None
264+
} yield CaptureInfo(pos, c)
266265
case (source.Box(Maybe(None, span), block, _), _) if C.inferredCaptureOption(block).isDefined => for {
267266
capt <- C.inferredCaptureOption(block)
268267
} yield CaptureInfo(span.range.from, capt)

0 commit comments

Comments
 (0)