-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Description
In implementing ScalaTest macros, I find two tree constructors are useful:
def selectApply(receiver: Term, name: Name, args: List[Term]): Term
def let(expr: Term)(body: Ident => Term): TermThe constructor selectApply should do overloading resolution internally, but no other adapation (like inserting apply nor implicits). The constructor let allows creating bindings friendly.
The current implementation of assert is as follows:
case Term.Apply(Term.Select(lhs, op), rhs :: Nil) =>
op match {
case "==" =>
val left = lhs.seal[Any]
val right = rhs.seal[Any]
'{
val _left = ~left
val _right = ~right
val _result = _left == _right
val _bool = Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
Assertions.assertionsHelper.macroAssert(_bool, ~clue, ~pos)
}
case ">" =>
// blocked by tasty constructors
// https://github.com/lampepfl/dotty/pull/5438
val left = lhs.seal[Int]
val right = rhs.seal[Int]
'{
val _left = ~left
val _right = ~right
val _result = _left > _right
val _bool = Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
Assertions.assertionsHelper.macroAssert(_bool, ~clue, ~pos)
}With the two constructors, the implementation can be made more generic & simpler:
case Term.Apply(Term.Select(lhs, op), rhs :: Nil) =>
val res =
let(lhs) { left =>
let(rhs) { right =>
let(selectApply(left, op, right)) { result =>
val l = left.seal[Any]
val r = right.seal[Any]
val b = result.seal[Boolean]
'{
val _bool = Bool.binaryMacroBool(~l, ~op.toExpr, ~r, ~b, ~prettifier)
Assertions.assertionsHelper.macroAssert(_bool, ~clue, ~pos)
}
}
}
res.seal[Assertion]