Skip to content

Commit 31eaf4e

Browse files
upgrade to scala 3 (#9)
1 parent 2e7cc37 commit 31eaf4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+2538
-1996
lines changed

.github/workflows/scala.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ jobs:
1313
uses: actions/setup-java@v1
1414
with:
1515
java-version: 11
16-
- name: format, test
17-
run: sbt scalafmtCheckAll test
16+
- name: Coursier Cache
17+
uses: coursier/cache-action@v5
18+
- name: test
19+
run: sbt test

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
target/
2-
/.idea/
32
/.bsp/
3+
/.dotty-ide-artifact
4+
/.dotty-ide.json
5+
/.idea/
6+
/.vscode/

build.sbt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
scalaVersion := "2.13.4"
1+
scalaVersion := "3.0.0-RC1"
22

33
name := "tapl-scala"
44

55
scalacOptions ++= Seq("-deprecation", "-feature")
66

7-
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
8-
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.2" % "test"
7+
libraryDependencies += ("org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2").withDottyCompat(scalaVersion.value)
8+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.5" % "test"

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.3")

src/main/scala/tapl/arith/core.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tapl.arith
33
// Small-step semantics as described by Pierce
44
object Evaluator {
55
import Util._
6+
import Term._
67

78
private def eval1(t: Term): Term =
89
t match {
@@ -47,6 +48,7 @@ object Evaluator {
4748

4849
// This is solution to the Exercise 3.5.17
4950
object BigStepEvaluator {
51+
import Term._
5052
import Util._
5153

5254
def eval(t: Term): Term =
@@ -91,6 +93,8 @@ object BigStepEvaluator {
9193
}
9294

9395
object Util {
96+
import Term._
97+
9498
def isNumericVal(t: Term): Boolean =
9599
t match {
96100
case TmZero => true

src/main/scala/tapl/arith/demo.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package tapl.arith
22

3+
import scala.language.implicitConversions
4+
35
object ArithDemo extends util.Demo[Unit, Command] {
46

57
import Evaluator._
6-
import util.Print._
8+
import util.Print._, util.Print.text2doc
79
import PrettyPrinter._
10+
import Command._
811

912
val width = 60
1013

@@ -17,9 +20,9 @@ object ArithDemo extends util.Demo[Unit, Command] {
1720
override def processCommand(ctx: Unit, cmd: Command): Unit =
1821
cmd match {
1922
case Eval(t1) =>
20-
val doc1 = g2(ptmATerm(true, t1) :: ";")
23+
val doc1 = g2(ptmATerm(true, t1) ::: ";")
2124
val t2 = eval(t1)
22-
val doc2 = g2(ptmATerm(true, t2) :: ";")
25+
val doc2 = g2(ptmATerm(true, t2) ::: ";")
2326

2427
println("====================")
2528
println(print(doc1, width))

src/main/scala/tapl/arith/parser.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import scala.util.parsing.combinator.ImplicitConversions
44
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
55

66
object ArithParsers extends StandardTokenParsers with ImplicitConversions {
7+
import Command._
8+
import Term._
9+
710
lexical.reserved ++= Seq("true", "false", "if", "then", "else", "iszero", "succ", "pred")
811
lexical.delimiters ++= Seq("(", ")", ";")
912

@@ -12,17 +15,17 @@ object ArithParsers extends StandardTokenParsers with ImplicitConversions {
1215
success(List())
1316

1417
private def command: Parser[Command] =
15-
term ^^ Eval
18+
term ^^ Eval.apply
1619

1720
private def term: Parser[Term] =
1821
appTerm |
19-
("if" ~> term) ~ ("then" ~> term) ~ ("else" ~> term) ^^ TmIf
22+
("if" ~> term) ~ ("then" ~> term) ~ ("else" ~> term) ^^ TmIf.apply
2023

2124
private def appTerm: Parser[Term] =
2225
aTerm |
23-
"succ" ~> aTerm ^^ TmSucc |
24-
"pred" ~> aTerm ^^ TmPred |
25-
"iszero" ~> aTerm ^^ TmIsZero
26+
"succ" ~> aTerm ^^ TmSucc.apply |
27+
"pred" ~> aTerm ^^ TmPred.apply |
28+
"iszero" ~> aTerm ^^ TmIsZero.apply
2629

2730
// Atomic terms are ones that never require extra parentheses
2831
private def aTerm: Parser[Term] =
Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
11
package tapl.arith
22

3-
sealed trait Term
4-
5-
case object TmTrue extends Term
6-
case object TmFalse extends Term
7-
case class TmIf(cond: Term, t1: Term, t2: Term) extends Term
8-
case object TmZero extends Term
9-
case class TmSucc(t: Term) extends Term
10-
case class TmPred(t: Term) extends Term
11-
case class TmIsZero(t: Term) extends Term
3+
enum Term {
4+
case TmTrue
5+
case TmFalse
6+
case TmIf(cond: Term, t1: Term, t2: Term)
7+
case TmZero
8+
case TmSucc(t: Term)
9+
case TmPred(t: Term)
10+
case TmIsZero(t: Term)
11+
}
1212

13-
sealed trait Command
14-
case class Eval(t: Term) extends Command
13+
enum Command {
14+
case Eval(t: Term)
15+
}
1516

1617
import util.Document
1718
import util.Document._
1819

1920
object PrettyPrinter {
20-
import util.Print._
21+
import scala.language.implicitConversions
22+
import util.Print._, util.Print.text2doc
23+
import Term._
2124

2225
def ptmTerm(outer: Boolean, t: Term): Document =
2326
t match {
24-
2527
case TmIf(t1, t2, t3) =>
2628
val ifB = g2("if" :/: ptmTerm(outer, t1))
2729
val thenB = g2("then" :/: ptmTerm(outer, t2))
2830
val elseB = g2("else" :/: ptmTerm(outer, t3))
2931
g0(ifB :/: thenB :/: elseB)
30-
case t => ptmAppTerm(outer, t)
31-
32+
case t =>
33+
ptmAppTerm(outer, t)
3234
}
3335

3436
def ptmAppTerm(outer: Boolean, t: Term): Document =
3537
t match {
3638
case TmPred(t1) =>
37-
"pred " :: ptmATerm(false, t1)
39+
"pred " ::: ptmATerm(false, t1)
3840
case TmIsZero(t1) =>
39-
"iszero " :: ptmATerm(false, t1)
41+
"iszero " ::: ptmATerm(false, t1)
4042
case t =>
4143
ptmATerm(outer, t)
4244
}
@@ -57,13 +59,13 @@ object PrettyPrinter {
5759
case TmSucc(s) =>
5860
pf(i + 1, s)
5961
case _ =>
60-
"(succ " :: ptmATerm(false, t1) :: ")"
62+
"(succ " ::: ptmATerm(false, t1) ::: ")"
6163
}
6264
pf(1, t1)
6365
case t =>
64-
"(" :: ptmTerm(outer, t) :: ")"
66+
"(" ::: ptmTerm(outer, t) ::: ")"
6567
}
6668

67-
def ptm(t: Term) = ptmTerm(true, t)
68-
69+
def ptm(t: Term) =
70+
ptmTerm(true, t)
6971
}

src/main/scala/tapl/bot/core.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package tapl.bot
22

33
object Util {
4+
import Term._
45

56
def isVal(ctx: Context, t: Term): Boolean =
67
t match {
@@ -12,6 +13,7 @@ object Util {
1213
object Evaluator {
1314
import Util._
1415
import Syntax._
16+
import Term._
1517

1618
private def eval1(ctx: Context, t: Term): Term =
1719
t match {
@@ -38,6 +40,9 @@ object Evaluator {
3840

3941
object Typer {
4042
import Syntax._
43+
import Binding._
44+
import Term._
45+
import Ty._
4146

4247
def subtype(tyS: Ty, tyT: Ty): Boolean =
4348
tyS == tyT ||

src/main/scala/tapl/bot/demo.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package tapl.bot
22

33
object BotDemo extends util.Demo[Context, Command] {
4+
import scala.language.implicitConversions
45
import Evaluator._
5-
import util.Print._
6+
import util.Print._, util.Print.text2doc
67
import PrettyPrinter._
78

89
val width = 60
@@ -15,13 +16,13 @@ object BotDemo extends util.Demo[Context, Command] {
1516

1617
def processCommand(ctx: Context, cmd: Command): Context =
1718
cmd match {
18-
case Eval(t1) =>
19+
case Command.Eval(t1) =>
1920
val ty1 = Typer.typeof(ctx, t1)
20-
val doc1 = g2(ptmATerm(true, ctx, t1) :: ":" :/: ptyTy(ctx, ty1) :: ";")
21+
val doc1 = g2(ptmATerm(true, ctx, t1) ::: ":" :/: ptyTy(ctx, ty1) ::: ";")
2122

2223
val t2 = eval(ctx, t1)
2324
val ty2 = Typer.typeof(ctx, t2)
24-
val doc2 = g2(ptmATerm(true, ctx, t2) :: ":" :/: ptyTy(ctx, ty2) :: ";")
25+
val doc2 = g2(ptmATerm(true, ctx, t2) ::: ":" :/: ptyTy(ctx, ty2) ::: ";")
2526

2627
println("====================")
2728
println(print(doc1, width))
@@ -31,8 +32,8 @@ object BotDemo extends util.Demo[Context, Command] {
3132

3233
ctx
3334

34-
case Bind(x, bind) =>
35-
val doc1 = x :: pBindingTy(ctx, bind) :: ";"
35+
case Command.Bind(x, bind) =>
36+
val doc1 = x ::: pBindingTy(ctx, bind) ::: ";"
3637
println("====================")
3738
println(print(doc1, width))
3839
ctx.addBinding(x, bind)

src/main/scala/tapl/bot/parser.scala

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import scala.util.parsing.combinator.PackratParsers
55
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
66

77
object BotParsers extends StandardTokenParsers with PackratParsers with ImplicitConversions {
8+
import Binding._
9+
import Command._
10+
import Term._
11+
import Ty._
12+
813
lexical.reserved ++= Seq(
914
"lambda",
1015
"Bool",
@@ -63,29 +68,29 @@ object BotParsers extends StandardTokenParsers with PackratParsers with Implicit
6368
lazy val topLevel: PackratParser[Res1[List[Command]]] =
6469
((command <~ ";") ~ topLevel) ^^ {
6570
case f ~ g =>
66-
ctx: Context =>
71+
(ctx: Context) =>
6772
val (cmd1, ctx1) = f(ctx)
6873
val (cmds, ctx2) = g(ctx1)
6974
(cmd1 :: cmds, ctx2)
70-
} | success { ctx: Context => (List(), ctx) }
75+
} | success { (ctx: Context) => (List(), ctx) }
7176

7277
lazy val command: PackratParser[Res1[Command]] =
73-
lcid ~ binder ^^ { case id ~ bind => ctx: Context => (Bind(id, bind(ctx)), ctx.addName(id)) } |
74-
term ^^ { t => ctx: Context =>
78+
lcid ~ binder ^^ { case id ~ bind => (ctx: Context) => (Bind(id, bind(ctx)), ctx.addName(id)) } |
79+
term ^^ { t => (ctx: Context) =>
7580
val t1 = t(ctx); (Eval(t1), ctx)
7681
}
7782

7883
lazy val binder: Parser[Context => Binding] =
79-
":" ~> typ ^^ { t => ctx: Context => VarBind(t(ctx)) }
84+
":" ~> typ ^^ { t => (ctx: Context) => VarBind(t(ctx)) }
8085

8186
lazy val typ: PackratParser[Res[Ty]] = arrowType
8287
lazy val aType: PackratParser[Res[Ty]] =
8388
"(" ~> typ <~ ")" |
84-
"Bot" ^^ { _ => ctx: Context => TyBot } |
85-
"Top" ^^ { _ => ctx: Context => TyTop }
89+
"Bot" ^^ { _ => (ctx: Context) => TyBot } |
90+
"Top" ^^ { _ => (ctx: Context) => TyTop }
8691

8792
lazy val fieldTypes: PackratParser[Res[List[(String, Ty)]]] =
88-
repsep(fieldType, ",") ^^ { fs => ctx: Context =>
93+
repsep(fieldType, ",") ^^ { fs => (ctx: Context) =>
8994
fs.zipWithIndex.map { case (ft, i) => ft(ctx, i + 1) }
9095
}
9196

@@ -94,25 +99,25 @@ object BotParsers extends StandardTokenParsers with PackratParsers with Implicit
9499
typ ^^ { ty => (ctx: Context, i: Int) => (i.toString, ty(ctx)) }
95100

96101
lazy val arrowType: PackratParser[Res[Ty]] =
97-
(aType <~ "->") ~ arrowType ^^ { case t1 ~ t2 => ctx: Context => TyArr(t1(ctx), t2(ctx)) } |
102+
(aType <~ "->") ~ arrowType ^^ { case t1 ~ t2 => (ctx: Context) => TyArr(t1(ctx), t2(ctx)) } |
98103
aType
99104

100105
// TERMS
101106
lazy val term: PackratParser[Res[Term]] =
102107
appTerm |
103108
("lambda" ~> lcid) ~ (":" ~> typ) ~ ("." ~> term) ^^ {
104-
case v ~ ty ~ t => ctx: Context => TmAbs(v, ty(ctx), t(ctx.addName(v)))
109+
case v ~ ty ~ t => (ctx: Context) => TmAbs(v, ty(ctx), t(ctx.addName(v)))
105110
} |
106111
("lambda" ~ "_") ~> (":" ~> typ) ~ ("." ~> term) ^^ {
107-
case ty ~ t => ctx: Context => TmAbs("_", ty(ctx), t(ctx.addName("_")))
112+
case ty ~ t => (ctx: Context) => TmAbs("_", ty(ctx), t(ctx.addName("_")))
108113
}
109114
lazy val appTerm: PackratParser[Res[Term]] =
110-
appTerm ~ aTerm ^^ { case t1 ~ t2 => ctx: Context => TmApp(t1(ctx), t2(ctx)) } |
115+
appTerm ~ aTerm ^^ { case t1 ~ t2 => (ctx: Context) => TmApp(t1(ctx), t2(ctx)) } |
111116
aTerm
112117

113118
lazy val aTerm: PackratParser[Res[Term]] =
114119
"(" ~> term <~ ")" |
115-
lcid ^^ { i => ctx: Context => TmVar(ctx.name2index(i), ctx.length) }
120+
lcid ^^ { i => (ctx: Context) => TmVar(ctx.name2index(i), ctx.length) }
116121

117122
lazy val phraseTopLevel: PackratParser[Res1[List[Command]]] = phrase(topLevel)
118123

0 commit comments

Comments
 (0)