Skip to content

Commit 1266af7

Browse files
committed
update for Scala 3.2.0
1 parent f55e01b commit 1266af7

File tree

9 files changed

+134
-36
lines changed

9 files changed

+134
-36
lines changed

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
ThisBuild / version := "0.1.0-SNAPSHOT"
1+
ThisBuild / version := "1.0.0"
22

3-
ThisBuild / scalaVersion := "3.1.3"
3+
ThisBuild / scalaVersion := "3.2.0"
44

55
lazy val root = (project in file("."))
66
.settings(

project/metals.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
// This file enables sbt-bloop to create bloop config files.
44

5-
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.0-18-003e6c7b")
5+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.3")
66

project/project/metals.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
// This file enables sbt-bloop to create bloop config files.
44

5-
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.0-18-003e6c7b")
5+
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.5.3")
66

src/main/scala/actor/Actor.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import java.util.concurrent.LinkedTransferQueue
44
import join_patterns.Matcher
55

66
abstract class Actor[M, T] extends Runnable {
7-
protected val q = LinkedTransferQueue[M]
8-
val ref = ActorRef(q)
7+
protected val q: LinkedTransferQueue[M] = LinkedTransferQueue[M]
8+
val ref: ActorRef[M] = ActorRef(q)
99
protected val matcher: Matcher[M, T]
1010
}
1111

1212
abstract class DynamicActor[M, T] extends Runnable {
13-
protected val q = LinkedTransferQueue[M]
14-
val ref = ActorRef(q)
13+
protected val q: LinkedTransferQueue[M] = LinkedTransferQueue[M]
14+
val ref: ActorRef[M] = ActorRef(q)
1515
protected var matcher: Matcher[M, T]
1616
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package actor
22

33
import java.util.concurrent.LinkedTransferQueue
4+
import scala.annotation.targetName
45

56
class ActorRef[-M](q: LinkedTransferQueue[M]) {
6-
def send(m: M) = q.put(m)
7-
def !(m: M) = send(m)
7+
def send(m: M): Unit = q.put(m)
8+
9+
def !(m: M): Unit = send(m)
810
}

src/main/scala/join_patterns/Macro.scala

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
package join_patterns
22

3-
import java.util.concurrent.{LinkedTransferQueue => Queue}
4-
5-
import scala.quoted.{Expr, Type, Quotes, Varargs}
3+
import java.util.concurrent.LinkedTransferQueue as Queue
4+
import scala.quoted.{Expr, Quotes, Type, Varargs}
65
import scala.collection.mutable.ListBuffer
7-
import scala.collection.mutable.{Map => mutMap}
6+
import scala.collection.mutable.Map as mutMap
7+
import scala.language.postfixOps
88

99
case class JoinPattern[M, T](
10-
val extract: List[M] => (List[M], Map[String, Any]),
11-
val guard: Map[String, Any] => Boolean,
12-
val rhs: Map[String, Any] => T,
13-
val size: Int
10+
extract: List[M] => (List[M], Map[String, Any]),
11+
guard: Map[String, Any] => Boolean,
12+
rhs: Map[String, Any] => T,
13+
size: Int
1414
)
1515

1616
class Matcher[M, T](val patterns: List[JoinPattern[M, T]]) {
1717
// Messages extracted from the queue are saved here to survive across apply() calls
18-
private var messages = ListBuffer[M]()
18+
private val messages = ListBuffer[M]()
1919

2020
def apply(q: Queue[M]): T =
2121
import collection.convert.ImplicitConversions._
@@ -25,12 +25,12 @@ class Matcher[M, T](val patterns: List[JoinPattern[M, T]]) {
2525
while (result.isEmpty)
2626
for
2727
pattern <- patterns
28-
if !result.isDefined
28+
if result.isEmpty
2929
do
3030
if messages.size >= pattern.size then
3131
val (matchedMessages, substs) = pattern.extract(messages.toList)
3232

33-
if !matchedMessages.isEmpty && pattern.guard(substs) then
33+
if matchedMessages.nonEmpty && pattern.guard(substs) then
3434
result = Some(pattern.rhs(substs))
3535
messages.subtractAll(matchedMessages)
3636

@@ -59,7 +59,7 @@ private def extractInner(using quotes: Quotes)(
5959
case typed @ Typed(Wildcard(), TypeIdent(_)) => ("_", typed.tpt.tpe.dealias.simplified)
6060
// add support for Wildcard !!! : (_)
6161
// add support for Bind(String, WildCard) : (name: _)
62-
case default =>
62+
case _ =>
6363
errorTree("Unsupported bottom-level pattern", t)
6464
("", TypeRepr.of[Nothing])
6565

@@ -103,9 +103,9 @@ private def generateExtractor(using
103103
Lambda(
104104
owner = Symbol.spliceOwner,
105105
tpe = MethodType(List(""))(_ => List(outerType), _ => TypeRepr.of[Map[String, Any]]),
106-
rhsFn = (sym: Symbol, params: List[Tree]) =>
106+
rhsFn = (_: Symbol, params: List[Tree]) =>
107107
val p0 = params.head.asInstanceOf[Ident]
108-
val isMemberName: (Symbol => Boolean) =
108+
val isMemberName: Symbol => Boolean =
109109
(p: Symbol) => p.name.head == '_' && p.name.tail.toIntOption.isDefined
110110
val memberSymbols: List[Symbol] = outerType.typeSymbol.methodMembers
111111
.filter(isMemberName(_))
@@ -137,13 +137,13 @@ private def generateGuard(using quotes: Quotes)(
137137
override def transformTerm(term: Term)(owner: Symbol): Term = super.transformTerm(term)(owner)
138138
}
139139

140-
var _rhsFn = (sym: Symbol, params: List[Tree]) =>
141-
_transform.transformTerm(('{ true }).asExprOf[Boolean].asTerm.changeOwner(sym))(sym)
140+
var _rhsFn = (sym: Symbol, _: List[Tree]) =>
141+
_transform.transformTerm('{ true }.asExprOf[Boolean].asTerm.changeOwner(sym))(sym)
142142

143143
guard match
144144
case Some(apply: Apply) =>
145145
if inners.isEmpty then
146-
_rhsFn = (sym: Symbol, params: List[Tree]) =>
146+
_rhsFn = (sym: Symbol, _: List[Tree]) =>
147147
_transform.transformTerm(apply.changeOwner(sym))(sym)
148148
else
149149
_rhsFn = (sym: Symbol, params: List[Tree]) =>
@@ -152,7 +152,7 @@ private def generateGuard(using quotes: Quotes)(
152152
val transform = new TreeMap {
153153
override def transformTerm(term: Term)(owner: Symbol): Term = term match
154154
case Ident(n) if inners.exists(_._1 == n) =>
155-
val inner = '{ ${ p0.asExprOf[Map[String, Any]] }(${ Expr(n) }) }
155+
val inner = '{ (${ p0.asExprOf[Map[String, Any]] })(${ Expr(n) }) }
156156

157157
inners.find(_._1 == n).get._2.asType match
158158
case '[innerType] => ('{ ${ inner }.asInstanceOf[innerType] }).asTerm
@@ -195,7 +195,7 @@ private def generateRhs[T](using
195195
val transform = new TreeMap {
196196
override def transformTerm(term: Term)(owner: Symbol): Term = term match
197197
case Ident(n) if inners.exists(_._1 == n) =>
198-
val inner = '{ ${ p0.asExprOf[Map[String, Any]] }(${ Expr(n) }) }
198+
val inner = '{ (${ p0.asExprOf[Map[String, Any]] })(${ Expr(n) }) }
199199

200200
inners.find(_._1 == n).get._2.asType match
201201
case '[innerType] => ('{ ${ inner }.asInstanceOf[innerType] }).asTerm
@@ -243,7 +243,7 @@ private def generate[M, T](using quotes: Quotes, tm: Type[M], tt: Type[T])(
243243
m.find(_.isInstanceOf[ot]) match
244244
case None => (List(), Map())
245245
case Some(message) =>
246-
(List(message), ${ extractor }(message.asInstanceOf[ot]))
246+
(List(message), $extractor(message.asInstanceOf[ot]))
247247
}
248248
(List(outer), inners)
249249
// (A, B, C ...)
@@ -319,7 +319,7 @@ private def getCases[M, T](
319319

320320
expr.asTerm match
321321
case Inlined(_, _, Block(_, Block(stmts, _))) =>
322-
stmts(0) match
322+
stmts.head match
323323
case DefDef(_, _, _, Some(Block(_, Match(_, cases)))) =>
324324
val code = cases.map { generate[M, T](_) }
325325
/*

src/main/scala/join_patterns/main.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ case class F(b: Int, a: String) extends Msg
1212
case class G(b: Int, a: String, c: Int, d: Boolean) extends Msg
1313

1414
object PatternOrdering extends Ordering[JoinPattern[Msg, Int]] {
15-
def compare(a: JoinPattern[Msg, Int], b: JoinPattern[Msg, Int]) = a.size.compare(b.size)
15+
def compare(a: JoinPattern[Msg, Int], b: JoinPattern[Msg, Int]): Int = a.size.compare(b.size)
1616
}
1717

1818
@main
1919
def main(): Unit =
20-
val i: Int = 0;
20+
val i: Int = 0
2121
val m = 0
2222
val isZero: Int => Boolean = (n: Int) => n == 0
2323
val q = LinkedTransferQueue[Msg]
2424

25-
var f = receive { (y: Msg) =>
25+
val f = receive { (y: Msg) =>
2626
y match
2727
case A() => 5
2828
/*
@@ -53,4 +53,4 @@ def main(): Unit =
5353
q.add(F(2, "t"))
5454
*/
5555
val ret1 = f(q)
56-
println(f"After receiving A, f returned: ${ret1}")
56+
println(f"After receiving A, f returned: $ret1")

src/main/scala/join_patterns/util.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def showExpr[T](expr: Expr[T])(using Quotes): Expr[String] =
1313
val code: String = expr.show
1414
Expr(code)
1515

16-
def _println[T](x: Expr[T])(using Quotes) = {
16+
def _println[T](x: Expr[T])(using Quotes): Unit = {
1717
import quotes.reflect.*
1818

1919
val tree: Tree = x.asTerm

src/test/scala/scenario/Demo.scala

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package test.scenario.demo
2+
3+
import java.util.Date
4+
import java.time.Duration
5+
import org.scalatest.funsuite.AnyFunSuite
6+
7+
import join_patterns.receive
8+
import test.classes.Msg
9+
import test.benchmark.Benchmarkable
10+
import actor.Actor
11+
12+
case class Motion(status: Boolean, room: String) extends Msg
13+
case class Light(status: Boolean, room: String) extends Msg
14+
case class Contact(open: Boolean, room: String) extends Msg
15+
16+
class DemoSmartHouse extends Actor[Msg, Unit] {
17+
private var lastMotionInBathroom = Date(0L)
18+
private var lastNotification = Date(0L)
19+
private val between: (Date, Date) => Duration = (a, b) =>
20+
Duration.between(a.toInstant, b.toInstant).abs
21+
22+
def turnOff(rooms: Seq[String], mStatus: Boolean, lStatus: Boolean, window: Duration) =
23+
rooms.forall(_ == "bathroom") && !mStatus && lStatus && between(
24+
lastMotionInBathroom,
25+
Date()
26+
).compareTo(window) > 0
27+
28+
def occupiedHome(
29+
statuses: Seq[Boolean],
30+
mRoom0: String,
31+
mRoom1: String,
32+
cRoom: String
33+
): Boolean =
34+
statuses.forall(
35+
_ == true
36+
) && mRoom0 == "front_door" && cRoom == "front_door" && mRoom1 == "entrance_hall"
37+
38+
protected val matcher = receive { (y: Msg) =>
39+
y match
40+
// E2. Turn off the lights in a room after two minutes without detecting any movement.
41+
case (
42+
Motion(mStatus: Boolean, mRoom: String),
43+
Light(lStatus: Boolean, lRoom: String)
44+
) if turnOff(List(mRoom, lRoom), mStatus, lStatus, Duration.ofMinutes(2)) =>
45+
lastMotionInBathroom = Date()
46+
println("turn_off_light()")
47+
// E5. Detect home arrival based on a particular sequence of messages, and activate the corresponding scene.
48+
case (
49+
Motion(mStatus0: Boolean, mRoom0: String),
50+
Contact(cStatus: Boolean, cRoom: String),
51+
Motion(mStatus1: Boolean, mRoom1: String)
52+
)
53+
if occupiedHome(
54+
List(mStatus0, mStatus1, cStatus),
55+
mRoom0,
56+
mRoom1,
57+
cRoom
58+
) =>
59+
lastNotification = Date()
60+
println("activate_home_scene(l, i, t)")
61+
62+
}
63+
64+
def run(): Unit =
65+
matcher(q)
66+
Thread.`yield`()
67+
}
68+
69+
class SmartHouseTest extends AnyFunSuite {
70+
test("E2. Turn off the lights in a room after two minutes without detecting any movement.") {
71+
val house = DemoSmartHouse()
72+
val houseThread = Thread(house)
73+
74+
houseThread.start
75+
76+
house.ref.send(Motion(false, "bathroom"))
77+
house.ref.send(Light(true, "bathroom"))
78+
79+
houseThread.join
80+
}
81+
82+
test(
83+
"E5. Detect home arrival based on a particular sequence of messages, and activate the corresponding scene."
84+
) {
85+
val house = DemoSmartHouse()
86+
val houseThread = Thread(house)
87+
88+
houseThread.start
89+
90+
house.ref.send(Motion(true, "front_door"))
91+
house.ref.send(Contact(true, "front_door"))
92+
house.ref.send(Motion(true, "entrance_hall"))
93+
94+
houseThread.join
95+
}
96+
}

0 commit comments

Comments
 (0)