Skip to content

Commit 5eab66a

Browse files
author
Oron Port
committed
Prevent accidental Java wait() method calls in DFHDL
1 parent c2f1673 commit 5eab66a

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

core/src/main/scala/dfhdl/core/Wait.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ object Wait:
1515
dfc.tags
1616
).addMember
1717
object Ops:
18+
inline def __java_waitErr(): Unit =
19+
compiletime.error(
20+
"Did you mean to call DFHDL's `wait`? If so, use `<time>.wait` instead (e.g., `5.ns.wait`).\nDid you mean to call Java's `wait`? if so, use `this.wait` instead."
21+
)
22+
inline def __java_waitErr(arg: Long): Unit = __java_waitErr()
23+
inline def __java_waitErr(arg: Long, arg2: Int): Unit = __java_waitErr()
24+
1825
extension (lhs: DFConstOf[Duration]) def wait(using DFC): Unit = trydf { Wait(lhs) }
1926
def waitWhile(cond: DFValOf[DFBool])(using DFC): Unit =
2027
trydf {

plugin/src/main/scala/plugin/PreTyperPhase.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import annotation.tailrec
2828
* - change infix operator precedence of terms: `a := b match {...}` to be `a := (b match {...})`
2929
* and `a <> b match {...}` to be `a <> (b match {...})`
3030
* - change process{} to process.forever{}
31+
* - change wait(...) to __java_waitErr(...)
3132
* - workaround for https://github.com/scala/scala3/issues/20053
3233
*/
3334
class PreTyperPhase(setting: Setting) extends PluginPhase:
@@ -83,12 +84,19 @@ class PreTyperPhase(setting: Setting) extends PluginPhase:
8384
case Apply(Ident(process), List(ofTree)) if process.toString == "process" =>
8485
Some(Apply(Select(Ident(process), "forever".toTermName), List(ofTree)))
8586
case _ => None
87+
object WaitChange:
88+
def unapply(tree: Tree)(using Context): Option[Tree] =
89+
tree match
90+
case Apply(Ident(wait), args) if wait.toString == "wait" =>
91+
Some(Apply(Ident("__java_waitErr".toTermName), args))
92+
case _ => None
8693
override def transformBlock(blk: Block)(using Context): Block =
8794
super.transformBlock(blk) match
8895
// a connection/assignment could be in return expression position of a Unit-typed block
8996
case Block(stats, InfixOpChange(expr)) => Block(stats, expr)
9097
case Block(stats, MatchAssignOpChange(expr)) => Block(stats, expr)
9198
case Block(stats, ProcessChange(expr)) => Block(stats, expr)
99+
case Block(stats, WaitChange(expr)) => Block(stats, expr)
92100
case blk => blk
93101
override def transformStats(trees: List[Tree], exprOwner: Symbol)(using Context): List[Tree] =
94102
super.transformStats(trees, exprOwner).map:
@@ -97,7 +105,9 @@ class PreTyperPhase(setting: Setting) extends PluginPhase:
97105
case MatchAssignOpChange(tree) => tree
98106
// change process{} to process.forever{}
99107
case ProcessChange(tree) => tree
100-
case tree => tree
108+
// change wait() to __java_waitErr()
109+
case WaitChange(tree) => tree
110+
case tree => tree
101111
override def transform(tree: Tree)(using Context): Tree =
102112
super.transform(tree) match
103113
// a connection could be in return position of a DFHDL Unit definition (if no block is used)

0 commit comments

Comments
 (0)