diff --git a/src/main/scala/inox/ast/DSL.scala b/src/main/scala/inox/ast/DSL.scala index d0f2ebcc20969fc2bdd7b809a3d0608b1961b50a..e3de5c914276ef2e43f6cc9e25cc054399949a08 100644 --- a/src/main/scala/inox/ast/DSL.scala +++ b/src/main/scala/inox/ast/DSL.scala @@ -20,7 +20,7 @@ trait DSL { case SafeSimplify => e2 } - implicit class ExprDSL(e: Expr)(implicit simpLvl: SimplificationLevel) { + implicit class ExprOps(e: Expr)(implicit simpLvl: SimplificationLevel) { private def binOp( e1: (Expr, Expr) => Expr, @@ -86,8 +86,6 @@ trait DSL { def asInstOf(tp: ClassType) = unOp(AsInstanceOf(_, tp), symbols.asInstOf(_, tp)) } - private def tpl(es: Expr*) = Tuple(es.toSeq) - // Literals def L(i: Int): Expr = IntLiteral(i) def L(b: BigInt): Expr = IntegerLiteral(b) @@ -96,9 +94,7 @@ trait DSL { def L(): Expr = UnitLiteral() def L(n: BigInt, d: BigInt) = FractionLiteral(n, d) def L(s: String): Expr = StringLiteral(s) - def L(e1: Expr, e2: Expr): Expr = tpl(e1, e2) - def L(e1: Expr, e2: Expr, e3: Expr): Expr = tpl(e1, e2, e3) - def L(e1: Expr, e2: Expr, e3: Expr, e4: Expr): Expr = tpl(e1, e2, e3, e4) + def L(e1: Expr, e2: Expr, es: Expr*): Expr = Tuple(e1 :: e2 :: es.toList) def L(s: Set[Expr]) = { require(s.nonEmpty) FiniteSet(s.toSeq, leastUpperBound(s.toSeq map (_.getType)).get) @@ -167,80 +163,105 @@ trait DSL { def assertion(e: Expr) = new BlockSuspension(Assert(e, None, _)) def assertion(e: Expr, msg: String) = new BlockSuspension(Assert(e, Some(msg), _)) + // Pattern-matching implicit class PatternMatch(scrut: Expr) { def matchOn(cases: MatchCase* ) = { MatchExpr(scrut, cases.toList) } } - implicit class PatternSuspension(pat: Pattern) { + //Patterns + + // This introduces the rhs of a case given a pattern + implicit class PatternOps(pat: Pattern) { + + val guard: Option[Expr] = None - def ~> (rhs: => Expr) = { + def ==>(rhs: => Expr) = { val Seq() = pat.binders - MatchCase(pat, None, rhs) + MatchCase(pat, guard, rhs) } - def ~> (rhs: Expr => Expr) = { + def ==>(rhs: Expr => Expr) = { val Seq(b1) = pat.binders - MatchCase(pat, None, rhs(b1.toVariable)) + MatchCase(pat, guard, rhs(b1.toVariable)) } - def ~> (rhs: (Expr, Expr) => Expr) = { + def ==>(rhs: (Expr, Expr) => Expr) = { val Seq(b1, b2) = pat.binders - MatchCase(pat, None, rhs(b1.toVariable, b2.toVariable)) + MatchCase(pat, guard, rhs(b1.toVariable, b2.toVariable)) } - def ~> (rhs: (Expr, Expr, Expr) => Expr) = { + def ==>(rhs: (Expr, Expr, Expr) => Expr) = { val Seq(b1, b2, b3) = pat.binders - MatchCase(pat, None, rhs(b1.toVariable, b2.toVariable, b3.toVariable)) + MatchCase(pat, guard, rhs(b1.toVariable, b2.toVariable, b3.toVariable)) } - def ~> (rhs: (Expr, Expr, Expr, Expr) => Expr) = { + def ==>(rhs: (Expr, Expr, Expr, Expr) => Expr) = { val Seq(b1, b2, b3, b4) = pat.binders - MatchCase(pat, None, + MatchCase(pat, guard, rhs(b1.toVariable, b2.toVariable, b3.toVariable, b4.toVariable)) } + + def ~|~(g: Expr) = new PatternOpsWithGuard(pat, g) + } + + class PatternOpsWithGuard(pat: Pattern, g: Expr) extends PatternOps(pat) { + override val guard = Some(g) + override def ~|~(g: Expr) = sys.error("Redefining guard!") } private def l2p[T](l: Literal[T]) = LiteralPattern(None, l) + // Literal patterns def P(i: Int) = l2p(IntLiteral(i)) def P(b: BigInt) = l2p(IntegerLiteral(b)) def P(b: Boolean) = l2p(BooleanLiteral(b)) def P(c: Char) = l2p(CharLiteral(c)) def P() = l2p(UnitLiteral()) - def P(ps: Pattern*) = TuplePattern(None, ps.toSeq) + // Binder-only patterns + def P(vd: ValDef) = WildcardPattern(Some(vd)) + class CaseClassToPattern(ct: ClassType) { + def apply(ps: Pattern*) = CaseClassPattern(None, ct, ps.toSeq) + } + // case class patterns + def P(ct: ClassType) = new CaseClassToPattern(ct) + // Tuple patterns + def P(p1:Pattern, p2: Pattern, ps: Pattern*) = TuplePattern(None, p1 :: p2 :: ps.toList) + // Wildcard pattern def __ = WildcardPattern(None) - + // Attach binder to pattern implicit class BinderToPattern(b: ValDef) { def @@ (p: Pattern) = p.withBinder(b) } - implicit class CaseClassToPattern(ct: ClassType) { - def pat(ps: Pattern*) = CaseClassPattern(None, ct, ps.toSeq) - } - + // Instance-of patterns implicit class TypeToInstanceOfPattern(ct: ClassType) { - def :: (vd: Option[ValDef]) = InstanceOfPattern(vd, ct) def :: (vd: ValDef) = InstanceOfPattern(Some(vd), ct) + def :: (wp: WildcardPattern) = { + if (wp.binder.nonEmpty) sys.error("Instance of pattern with named wildcardpattern?") + else InstanceOfPattern(None, ct) + } // TODO Kinda dodgy... } - // TODO: Remove this at some point private def test(e1: Expr, e2: Expr, ct: ClassType)(implicit simpl: SimplificationLevel) = { prec(e1) in - let("i" :: Untyped, e1) { i => - if_ (\("j" :: Untyped)(j => e1(j))) { - e1 + e2 + i + L(42) - } else_ { - assertion(L(true), "Weird things") in - ct(e1, e2) matchOn ( - ct.pat( - ("i" :: Untyped) :: ct, P(42), - P(P(__), ( "j" :: Untyped) @@ P(42)) - ) ~> { - (i, j) => e1 - }, - __ ~> e2 - ) - } + let("i" :: Untyped, e1) { i => + if_ (\("j" :: Untyped)(j => e1(j))) { + e1 + e2 + i + L(42) + } else_ { + assertion(L(true), "Weird things") in + ct(e1, e2) matchOn ( + P(ct)( + ("i" :: Untyped) :: ct, + P(42), + __ :: ct, + P("k" :: Untyped), + P(__, ( "j" :: Untyped) @@ P(42)) + ) ==> { + (i, j, k) => e1 + }, + __ ~|~ e1 ==> e2 + ) } + } } ensures e2 }