From 9c812f71582ca5524b2cf7684d8cfcce429b388a Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Mon, 16 Dec 2024 23:46:48 +0100 Subject: [PATCH] ex2 typechecks --- build.sbt | 2 ++ .../GenerativeFluentAssertionsDSLSyntax.scala | 15 +++++++++++++++ .../ch/usi/si/msde/edsl/lecture10/Main.scala | 18 ++++++++++-------- .../edsl/lecture10/ShouldBeTypeProvider.scala | 2 +- .../lecture10/ShouldHaveTypeProvider.scala | 14 ++++++++++++-- 5 files changed, 40 insertions(+), 11 deletions(-) diff --git a/build.sbt b/build.sbt index c832fca..e69e0a3 100644 --- a/build.sbt +++ b/build.sbt @@ -9,3 +9,5 @@ lazy val root = project scalaVersion := scala3Version, libraryDependencies += "org.typelevel" %% "squants" % "1.8.3", ) + +scalacOptions ++= Seq("-explain", "-explain-types") \ No newline at end of file diff --git a/src/main/scala/ch/usi/si/msde/edsl/lecture10/GenerativeFluentAssertionsDSLSyntax.scala b/src/main/scala/ch/usi/si/msde/edsl/lecture10/GenerativeFluentAssertionsDSLSyntax.scala index 6cbfcaa..83786ae 100644 --- a/src/main/scala/ch/usi/si/msde/edsl/lecture10/GenerativeFluentAssertionsDSLSyntax.scala +++ b/src/main/scala/ch/usi/si/msde/edsl/lecture10/GenerativeFluentAssertionsDSLSyntax.scala @@ -12,6 +12,21 @@ class DynamicShouldBeProperty extends AssertionProperty with Dynamic: def applyDynamic(fieldName: String)(foo: Any*) = ??? end DynamicShouldBeProperty +object satisfying: + def `===`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.eq(something, toWhat) + def `!==`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.ne(something, toWhat) + def `<`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.lt(something, toWhat) + def `>`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.gt(something, toWhat) + def `<=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.lteq(something, toWhat) + def `>=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean = + something => ord.gteq(something, toWhat) +end satisfying + class BePropertyTypeProvider[T](val subject: T) extends Selectable: def selectDynamic(fieldName: String): AssertionProperty = ??? def applyDynamic(fieldName: String)(foo: Any*): AssertionProperty = ??? diff --git a/src/main/scala/ch/usi/si/msde/edsl/lecture10/Main.scala b/src/main/scala/ch/usi/si/msde/edsl/lecture10/Main.scala index dfb343d..d429dac 100644 --- a/src/main/scala/ch/usi/si/msde/edsl/lecture10/Main.scala +++ b/src/main/scala/ch/usi/si/msde/edsl/lecture10/Main.scala @@ -40,6 +40,8 @@ case class Box(label: String, weight: Mass, price: Money) // assert(List(1,2,3).nonEmpty) List(1, 2, 3) should be.nonEmpty + (person should have) age ((x: Int) => x == 10) + // New syntax for `be` with type provider // either adult is a method with a dummy Unit parameter person should be_ adult() @@ -47,13 +49,13 @@ case class Box(label: String, weight: Mass, price: Money) (person should be_).adult /* should have assertions */ - // assert(List(1).head == 1, ...) - List(1) should have head 1 - // assert(box.weight == 30.kg, ...) - box should have weight 30.kg - // assert(person.age == 0x29, ...) - person should have age 0x29 - List(2, 3) should have tail List(3) - 3.i + 1 should have re 1.0 +// // assert(List(1).head == 1, ...) +// List(1) should have head 1 +// // assert(box.weight == 30.kg, ...) +// box should have weight 30.kg +// // assert(person.age == 0x29, ...) +// person should have age 0x29 +// List(2, 3) should have tail List(3) +// 3.i + 1 should have re 1.0 end assertionsExample diff --git a/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldBeTypeProvider.scala b/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldBeTypeProvider.scala index dab5632..9b679c9 100644 --- a/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldBeTypeProvider.scala +++ b/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldBeTypeProvider.scala @@ -53,7 +53,7 @@ object ShouldBeTypeProvider: members ) - println(refinedType) +// println(refinedType) // This is the way to extract a (reflection) type to a // type that can be used in some quoted code. diff --git a/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldHaveTypeProvider.scala b/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldHaveTypeProvider.scala index cddb4c7..d2f7adf 100644 --- a/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldHaveTypeProvider.scala +++ b/src/main/scala/ch/usi/si/msde/edsl/lecture10/ShouldHaveTypeProvider.scala @@ -25,6 +25,14 @@ object ShouldHaveTypeProvider: // The type of the field, or the return type of the method. val fieldTypeRepr = subjectTypeRepr.memberType(symbol).widen + // hack to get the equivalent of `TypeRepr.of[Function1[?, ?]]` (i.e. an arity-1 function type constructor). + // Getting it as is returns an applied type with useless bounds (Nothing to Any), and the returned TypeRepr, + // if re-applied to some `I` input type and `O` output type would be incompatible with `TypeRepr.of[I => O]` for + // some reason + val function1TypeConstructor = AppliedType.unapply(TypeRepr.of[? => ?].asInstanceOf[AppliedType])._1 + + val appliedType = AppliedType(function1TypeConstructor, List(fieldTypeRepr, TypeRepr.of[Boolean])) + // Generates the "type" of the method to be generated for the refinement. // The first parameter is the list of arguments, the second is a function returning // the type of arguments, and the third one is a function returning the return type @@ -33,9 +41,9 @@ object ShouldHaveTypeProvider: // _ => List(fieldTypeRepr) returns a list with the type of arg; // _ => TypeRepr.of[AssertionProperty] returns the (reflection) type of the method. val methodType = MethodType(List("arg"))( - _ => List(fieldTypeRepr), + _ => List(appliedType), _ => TypeRepr.of[AssertionProperty] - ) + ).widen // returns the refinement of currentTypeRepr - // symbol.name is the name of the method, // methodType is its type. @@ -71,6 +79,8 @@ object ShouldHaveTypeProvider: fields ++ arityZeroMethods ) + println(refinedType.show) + // This is the way to extract a (reflection) type to a // type that can be used in some quoted code. // it's the equivalent of .asExpr for expressions,