Skip to content

Commit 642050c

Browse files
committed
Walkaround cyclic dependencies by reorganization of files
1 parent 7d3aa24 commit 642050c

File tree

3 files changed

+191
-234
lines changed

3 files changed

+191
-234
lines changed

scalactic-macro/src/main/scala/org/scalactic/BooleanMacro.scala renamed to scalactic/src/main/scala/org/scalactic/BooleanMacro.scala

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,3 +857,182 @@ package org.scalactic
857857
// ownerRepair.repairOwners(expandedCode)
858858
// }
859859
// }
860+
861+
import scala.quoted._
862+
import scala.tasty._
863+
864+
object BooleanMacro {
865+
def parse(condition: Expr[Boolean], prettifier: Expr[Prettifier])(implicit refl: Reflection): Expr[Bool] = {
866+
import refl._
867+
import quoted.Toolbox.Default._
868+
869+
def exprStr: String = condition.show
870+
def defaultCase = '(Bool.simpleMacroBool(~condition, ~exprStr.toExpr, ~prettifier))
871+
872+
// AssertionsSpec.this.convertToEqualizer[scala.Int](a).===(5)(scalactic.Equality.default[scala.Int])
873+
object TripleEqual {
874+
def isEqualizer(tp: Type): Boolean = true // tp <:< typeOf[TripleEqualsSupport#Equalizer[_]]
875+
876+
def unapply(tree: Term): Option[(Term, Term, String, Term, Option[Term])] = tree match {
877+
case Term.Apply(Term.Select(Term.Apply(fun, lhs :: Nil), op), rhs :: Nil) if isEqualizer(fun.tpe) =>
878+
Some((fun, lhs, op, rhs, None))
879+
case Term.Apply(Term.Apply(Term.Select(Term.Apply(fun, lhs :: Nil), op), rhs :: Nil), equality :: Nil) if isEqualizer(fun.tpe) =>
880+
Some((fun, lhs, op, rhs, Some(equality)))
881+
case _ => None
882+
}
883+
}
884+
885+
condition.unseal.underlyingArgument match {
886+
case Term.Apply(Term.Select(lhs, op), rhs :: Nil) =>
887+
op match {
888+
case "==" =>
889+
val left = lhs.seal[Any]
890+
val right = rhs.seal[Any]
891+
'{
892+
val _left = ~left
893+
val _right = ~right
894+
val _result = _left == _right
895+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
896+
}
897+
case "!=" =>
898+
val left = lhs.seal[Any]
899+
val right = rhs.seal[Any]
900+
'{
901+
val _left = ~left
902+
val _right = ~right
903+
val _result = _left != _right
904+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
905+
}
906+
case ">" =>
907+
// blocked by tasty constructors
908+
// https://github.com/lampepfl/dotty/issues/5567
909+
val left = lhs.seal[Int]
910+
val right = rhs.seal[Int]
911+
'{
912+
val _left = ~left
913+
val _right = ~right
914+
val _result = _left > _right
915+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
916+
}
917+
case "<" =>
918+
// blocked by tasty constructors
919+
// https://github.com/lampepfl/dotty/issues/5567
920+
val left = lhs.seal[Int]
921+
val right = rhs.seal[Int]
922+
'{
923+
val _left = ~left
924+
val _right = ~right
925+
val _result = _left < _right
926+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
927+
}
928+
case ">=" =>
929+
// blocked by tasty constructors
930+
// https://github.com/lampepfl/dotty/issues/5567
931+
val left = lhs.seal[Int]
932+
val right = rhs.seal[Int]
933+
'{
934+
val _left = ~left
935+
val _right = ~right
936+
val _result = _left >= _right
937+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
938+
}
939+
case "<=" =>
940+
// blocked by tasty constructors
941+
// https://github.com/lampepfl/dotty/issues/5567
942+
val left = lhs.seal[Int]
943+
val right = rhs.seal[Int]
944+
'{
945+
val _left = ~left
946+
val _right = ~right
947+
val _result = _left <= _right
948+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
949+
}
950+
case "eq" =>
951+
val left = lhs.seal[AnyRef]
952+
val right = rhs.seal[AnyRef]
953+
'{
954+
val _left = ~left
955+
val _right = ~right
956+
val _result = _left `eq` _right
957+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
958+
}
959+
case "ne" =>
960+
val left = lhs.seal[AnyRef]
961+
val right = rhs.seal[AnyRef]
962+
'{
963+
val _left = ~left
964+
val _right = ~right
965+
val _result = _left `ne` _right
966+
Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
967+
}
968+
case "||" =>
969+
val left = parse(lhs.seal[Boolean], prettifier)
970+
val right = parse(rhs.seal[Boolean], prettifier)
971+
'(~left || ~right)
972+
case "|" =>
973+
val left = parse(lhs.seal[Boolean], prettifier)
974+
val right = parse(rhs.seal[Boolean], prettifier)
975+
'(~left | ~right)
976+
case "&&" =>
977+
val left = parse(lhs.seal[Boolean], prettifier)
978+
val right = parse(rhs.seal[Boolean], prettifier)
979+
'(~left && ~right)
980+
case "&" =>
981+
val left = parse(lhs.seal[Boolean], prettifier)
982+
val right = parse(rhs.seal[Boolean], prettifier)
983+
'(~left & ~right)
984+
case _ =>
985+
defaultCase
986+
}
987+
// case TripleEqual(fn, lhs, op, rhs, Some(eq)) =>
988+
// val fun = fn.seal[Any => TripleEqualsSupport#Equalizer[_]]
989+
// val left = lhs.seal[Any]
990+
// val right = rhs.seal[Any]
991+
// val equality = eq.seal[Equality[Any]]
992+
// op match {
993+
// case "===" =>
994+
// '{
995+
// val _left = ~left
996+
// val _right = ~right
997+
// val _result = (~fun)(_left).===(_right)(~equality)
998+
// Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
999+
// }
1000+
// case "!==" =>
1001+
// '{
1002+
// val _left = ~left
1003+
// val _right = ~right
1004+
// val _result = (~fun)(_left).!==(_right)(~equality)
1005+
// Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
1006+
// }
1007+
// }
1008+
// case TripleEqual(fn, lhs, op, rhs, None) =>
1009+
// val fun = fn.seal[Any => TripleEqualsSupport#Equalizer[_]]
1010+
// val left = lhs.seal[Any]
1011+
// val right = rhs.seal[Any]
1012+
1013+
// op match {
1014+
// case "===" =>
1015+
// '{
1016+
// val _left = ~left
1017+
// val _right = ~right
1018+
// val _result = (~fun)(_left) === _right
1019+
// Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
1020+
// }
1021+
// case "!==" =>
1022+
// '{
1023+
// val _left = ~left
1024+
// val _right = ~right
1025+
// val _result = (~fun)(_left) !== _right
1026+
// Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
1027+
// }
1028+
// }
1029+
case Term.Select(left, "unary_!") =>
1030+
val receiver = parse(left.seal[Boolean], prettifier)
1031+
'{ !(~receiver) }
1032+
case Term.Literal(_) =>
1033+
'(Bool.simpleMacroBool(~condition, "", ~prettifier))
1034+
case _ =>
1035+
defaultCase
1036+
}
1037+
}
1038+
}

scalactic/src/main/scala/org/scalactic/Requirements.scala

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ trait Requirements {
145145
* @throws IllegalArgumentException if the condition is <code>false</code>.
146146
*/
147147
inline def require(condition: Boolean)(implicit prettifier: Prettifier): Unit =
148-
~RequirementsMacro.require('(condition), '(prettifier))
148+
~RequirementsMacro.require('(condition), '(prettifier), '(""))
149149

150150
/**
151151
* Require that a boolean condition about an argument passed to a method, function, or constructor,
@@ -162,7 +162,10 @@ trait Requirements {
162162
* @throws IllegalArgumentException if the condition is <code>false</code>.
163163
* @throws NullPointerException if <code>message</code> is <code>null</code>.
164164
*/
165-
def require(condition: Boolean, clue: Any)(implicit prettifier: Prettifier): Unit = () //RequirementsMacro.requireWithClue
165+
inline def require(condition: Boolean, clue: Any)(implicit prettifier: Prettifier): Unit = ()
166+
// blocked by tasty constructors
167+
// https://github.com/lampepfl/dotty/issues/5567
168+
// ~RequirementsMacro.require('(condition), '(prettifier), '(clue))
166169

167170
/**
168171
* Require that a boolean condition is true about the state of an object on which a method has been invoked.
@@ -179,7 +182,7 @@ trait Requirements {
179182
* @param condition the boolean condition to check as requirement
180183
* @throws IllegalStateException if the condition is <code>false</code>.
181184
*/
182-
def requireState(condition: Boolean)(implicit prettifier: Prettifier): Unit = ??? //RequirementsMacro.requireState
185+
def requireState(condition: Boolean)(implicit prettifier: Prettifier): Unit = () // RequirementsMacro.requireState
183186

184187
/**
185188
* Require that a boolean condition about the state of an object on which a method has been
@@ -228,65 +231,14 @@ object RequirementsMacro {
228231
* @param condition original condition expression
229232
* @return transformed expression that performs the requirement check and throw <code>IllegalArgumentException</code> with rich error message if requirement failed
230233
*/
231-
def require(condition: Expr[Boolean], prettifier: Expr[Prettifier])(implicit tasty: Reflection): Expr[Unit] = {
232-
import tasty._
233-
234-
val tree = condition.unseal
235-
def exprStr: String = tree.show
234+
def require(condition: Expr[Boolean], prettifier: Expr[Prettifier], clue: Expr[Any])(implicit refl: Reflection): Expr[Unit] = {
235+
import refl._
236+
import quoted.Toolbox.Default._
236237

237-
tree match {
238-
case Term.Apply(Term.Select(lhs, op), rhs :: Nil) =>
239-
val left = lhs.seal[Any]
240-
val right = rhs.seal[Any]
241-
op match {
242-
case "==" =>
243-
'{
244-
val _left = ~left
245-
val _right = ~right
246-
val _result = _left == _right
247-
val _bool = Bool.binaryMacroBool(_left, ~op.toExpr, _right, _result, ~prettifier)
248-
Requirements.requirementsHelper.macroRequire(_bool, None)
249-
}
250-
case "!=" =>
251-
'(Requirements.requirementsHelper.macroRequire(Bool.simpleMacroBool(~condition, ~exprStr.toExpr, ~prettifier), None))
252-
}
253-
case Term.Select(left, "unary_!") =>
254-
'(Requirements.requirementsHelper.macroRequire(Bool.simpleMacroBool(~condition, ~exprStr.toExpr, ~prettifier), None))
255-
case _ =>
256-
'(Requirements.requirementsHelper.macroRequire(Bool.simpleMacroBool(~condition, ~exprStr.toExpr, ~prettifier), None))
257-
}
238+
val bool = BooleanMacro.parse(condition, prettifier)
239+
'{ Requirements.requirementsHelper.macroRequire(~bool, ~clue) }
258240
}
259241

260-
// /**
261-
// * Provides requirement implementation for <code>Requirements.require(booleanExpr: Boolean, clue: Any)</code>, with rich error message.
262-
// *
263-
// * @param context macro context
264-
// * @param condition original condition expression
265-
// * @param clue original clue expression
266-
// * @return transformed expression that performs the requirement check and throw <code>IllegalArgumentException</code> with rich error message (clue included) if requirement failed
267-
// */
268-
// def requireWithClue(context: Context)(condition: context.Expr[Boolean], clue: context.Expr[Any])(prettifier: context.Expr[Prettifier]): context.Expr[Unit] = {
269-
// import context.universe._
270-
// new BooleanMacro[context.type](context).genMacro(
271-
// Select(
272-
// Select(
273-
// Select(
274-
// Select(
275-
// Ident(newTermName("_root_")),
276-
// newTermName("org")
277-
// ),
278-
// newTermName("scalactic")
279-
// ),
280-
// newTermName("Requirements")
281-
// ),
282-
// newTermName("requirementsHelper")
283-
// ),
284-
// condition,
285-
// "macroRequire",
286-
// clue,
287-
// prettifier)
288-
// }
289-
290242
// /**
291243
// * Provides requirement implementation for <code>Requirements.requireState(booleanExpr: Boolean)</code>, with rich error message.
292244
// *

0 commit comments

Comments
 (0)