Skip to content

Commit c53c05c

Browse files
timsueberkruebb-studiosJakubSchwenkbeck
authored
Add initial spans to source tree (#957)
This PR starts the effort on adding spans to the source syntax tree. It is just the first of several steps of this transition. --------- Co-authored-by: Jonathan Brachthäuser <[email protected]> Co-authored-by: Jakub Schwenkbeck <[email protected]>
1 parent 5289380 commit c53c05c

20 files changed

+863
-328
lines changed

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
108108
}
109109
output.emitln("")
110110

111-
runFrontend(StringSource(""), module.make(UnitLit()), config) { cu =>
111+
runFrontend(StringSource(""), module.make(StringSource(""), UnitLit()), config) { cu =>
112112
module.definitions.foreach {
113113
case u: Def =>
114114
outputCode(DeclPrinter(context.symbolOf(u)), config)
@@ -122,7 +122,7 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
122122
def typecheck(source: Source, config: EffektConfig): Unit =
123123
parse(source) match {
124124
case Success(e: Term, _) =>
125-
runFrontend(source, module.make(e), config) { mod =>
125+
runFrontend(source, module.make(source, e), config) { mod =>
126126
// TODO this is a bit ad-hoc
127127
val mainSym = mod.exports.terms("main").head
128128
val mainTpe = context.functionTypeOf(mainSym)
@@ -184,7 +184,7 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
184184
*/
185185
def process(source: Source, tree: Tree, config: EffektConfig): Unit = tree match {
186186
case e: Term =>
187-
runCompiler(source, module.makeEval(e), config)
187+
runCompiler(source, module.makeEval(source, e), config)
188188

189189
case i: Include =>
190190
val extendedIncludes = module + i
@@ -217,7 +217,7 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
217217

218218
case d: Def =>
219219
val extendedDefs = module + d
220-
val decl = extendedDefs.make(UnitLit())
220+
val decl = extendedDefs.make(source, UnitLit())
221221

222222
runFrontend(source, decl, config) { cu =>
223223
module = extendedDefs
@@ -309,17 +309,20 @@ class Repl(driver: Driver) extends REPL[Tree, EffektConfig, EffektError] {
309309
/**
310310
* Create a module declaration using the given expression as body of main
311311
*/
312-
def make(expr: Term): ModuleDecl = {
312+
def make(source: Source, expr: Term): ModuleDecl = {
313313

314314
val body = Return(expr)
315-
315+
val fakeSpan = Span(source, 0, 0, origin = Origin.Synthesized)
316+
val fullSpan = Span(source, 0, source.content.length, origin = Origin.Synthesized)
316317
ModuleDecl("interactive", includes,
317-
definitions :+ FunDef(IdDef("main"), Nil, Nil, Nil, None,
318-
body))
318+
definitions :+ FunDef(IdDef("main", fakeSpan), Many.empty(fakeSpan), Many.empty(fakeSpan), Many.empty(fakeSpan), Maybe.None(fakeSpan),
319+
body, fullSpan), fullSpan)
319320
}
320321

321-
def makeEval(expr: Term): ModuleDecl =
322-
make(Call(IdTarget(IdRef(List(), "println")), Nil, List(expr), Nil))
322+
def makeEval(source: Source, expr: Term): ModuleDecl = {
323+
val fakeSpan = Span(source, 0, 0, origin = Origin.Synthesized)
324+
make(source, Call(IdTarget(IdRef(List(), "println", fakeSpan)), Nil, List(expr), Nil))
325+
}
323326
}
324327
lazy val emptyModule = ReplModule(Nil, Nil)
325328
}

effekt/jvm/src/test/scala/effekt/LSPTests.scala

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -723,17 +723,15 @@ class LSPTests extends FunSuite {
723723
test("When showIR=source, server should provide source AST") {
724724
withClientAndServer { (client, server) =>
725725
val source =
726-
raw"""
727-
|def main() = { println("Hello, world!") }
728-
|"""
729-
val textDoc = new TextDocumentItem("file://path/to/test.effekt", "effekt", 0, source.stripMargin)
726+
raw"""def main() = <>""".textDocument
727+
val textDoc = new TextDocumentItem("file://path/to/test.effekt", "effekt", 0, source.getText)
730728
val initializeParams = new InitializeParams()
731729
val initializationOptions = """{"showIR": "source"}"""
732730
initializeParams.setInitializationOptions(JsonParser.parseString(initializationOptions))
733731
server.initialize(initializeParams).get()
734732

735733
val didOpenParams = new DidOpenTextDocumentParams()
736-
didOpenParams.setTextDocument(helloWorld)
734+
didOpenParams.setTextDocument(source)
737735
server.getTextDocumentService().didOpen(didOpenParams)
738736

739737
val expectedIRContents =
@@ -742,28 +740,36 @@ class LSPTests extends FunSuite {
742740
| Nil,
743741
| List(
744742
| FunDef(
745-
| IdDef(main),
746-
| Nil,
747-
| Nil,
748-
| Nil,
749-
| None(),
750-
| BlockStmt(
751-
| Return(
752-
| Call(
753-
| IdTarget(IdRef(Nil, println)),
754-
| Nil,
755-
| List(Literal(Hello, world!, ValueTypeApp(String_whatever, Nil))),
756-
| Nil
757-
| )
758-
| )
759-
| )
743+
| IdDef(
744+
| main,
745+
| Span(StringSource(def main() = <>, file://test.effekt), 4, 8, Real())
746+
| ),
747+
| Many(
748+
| Nil,
749+
| Span(StringSource(def main() = <>, file://test.effekt), 8, 8, Real())
750+
| ),
751+
| Many(
752+
| Nil,
753+
| Span(StringSource(def main() = <>, file://test.effekt), 8, 10, Real())
754+
| ),
755+
| Many(
756+
| Nil,
757+
| Span(StringSource(def main() = <>, file://test.effekt), 10, 10, Real())
758+
| ),
759+
| Maybe(
760+
| None(),
761+
| Span(StringSource(def main() = <>, file://test.effekt), 10, 10, Real())
762+
| ),
763+
| Return(Hole(Return(Literal((), ValueTypeApp(Unit_whatever, Nil))))),
764+
| Span(StringSource(def main() = <>, file://test.effekt), 0, 15, Real())
760765
| )
761-
| )
766+
| ),
767+
| Span(StringSource(def main() = <>, file://test.effekt), 0, 15, Real())
762768
|)""".stripMargin
763769

764770
val receivedIRContent = client.receivedIR()
765771
assertEquals(receivedIRContent.length, 1)
766-
val fixedReceivedIR = receivedIRContent.head.content.replaceAll("String_\\d+", "String_whatever")
772+
val fixedReceivedIR = receivedIRContent.head.content.replaceAll("Unit_\\d+", "Unit_whatever")
767773
assertEquals(fixedReceivedIR, expectedIRContents)
768774
}
769775
}

0 commit comments

Comments
 (0)