From 3aa00b19107b6383bf059f8c6108e5af641790f3 Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Fri, 19 Jun 2020 18:28:53 +0200 Subject: [PATCH 1/3] Add summonAll and constValueTuple --- library/src/scala/compiletime/package.scala | 23 +++++++++++++++++++++ tests/run/constValueTuple.check | 1 + tests/run/constValueTuple.scala | 4 ++++ tests/run/summonAll.check | 1 + tests/run/summonAll.scala | 7 +++++++ 5 files changed, 36 insertions(+) create mode 100644 tests/run/constValueTuple.check create mode 100644 tests/run/constValueTuple.scala create mode 100644 tests/run/summonAll.check create mode 100644 tests/run/summonAll.scala diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index dbc60f3b9298..3761c3b83606 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -42,6 +42,15 @@ package object compiletime { inline def constValue[T]: T = ??? + inline def constValueTuple[T <: Tuple]: T = + val res = + inline erasedValue[T] match + case _: EmptyTuple => EmptyTuple + case _: (t *: ts) => constValue[t] *: constValueTuple[ts] + end match + res.asInstanceOf[T] + end constValueTuple + /** Summons first given matching one of the listed cases. E.g. in * * given B { ... } @@ -68,6 +77,20 @@ package object compiletime { case t: T => t } + /** Given a tuple T, summons each of its member types and returns them in + * a List. + * + * @tparam T the tuple containing the types of the values to be summoned + * @return the given values typed as elements of the tuple + */ + inline def summonAll[T <: Tuple]: T = + val res = + inline erasedValue[T] match + case _: EmptyTuple => EmptyTuple + case _: (t *: ts) => summonInline[t] *: summonAll[ts] + end match + res.asInstanceOf[T] + end summonAll /** Succesor of a natural number where zero is the type 0 and successors are reduced as if the definition was * diff --git a/tests/run/constValueTuple.check b/tests/run/constValueTuple.check new file mode 100644 index 000000000000..264d259343f4 --- /dev/null +++ b/tests/run/constValueTuple.check @@ -0,0 +1 @@ +(foo,bar,10,2.5) diff --git a/tests/run/constValueTuple.scala b/tests/run/constValueTuple.scala new file mode 100644 index 000000000000..ab9467adb714 --- /dev/null +++ b/tests/run/constValueTuple.scala @@ -0,0 +1,4 @@ +import compiletime.constValueTuple + +@main def Test = + println(constValueTuple["foo" *: "bar" *: 10 *: 2.5 *: EmptyTuple]) diff --git a/tests/run/summonAll.check b/tests/run/summonAll.check new file mode 100644 index 000000000000..c4bbadaa6ae8 --- /dev/null +++ b/tests/run/summonAll.check @@ -0,0 +1 @@ +(10,foo,1.2) diff --git a/tests/run/summonAll.scala b/tests/run/summonAll.scala new file mode 100644 index 000000000000..b4638d7e6ee6 --- /dev/null +++ b/tests/run/summonAll.scala @@ -0,0 +1,7 @@ +import compiletime.summonAll + +@main def Test = + given as Int = 10 + given as String = "foo" + given as Double = 1.2 + println(summonAll[Int *: String *: Double *: EmptyTuple]) From 28d553f586eab26c5266fcc29b4b03b0a4653e97 Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Wed, 24 Jun 2020 11:55:10 +0200 Subject: [PATCH 2/3] Add Widen type to the Tuple --- library/src/scala/Tuple.scala | 12 ++++++++++++ library/src/scala/compiletime/package.scala | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/library/src/scala/Tuple.scala b/library/src/scala/Tuple.scala index 78b2196217aa..a17e73c509be 100644 --- a/library/src/scala/Tuple.scala +++ b/library/src/scala/Tuple.scala @@ -143,6 +143,18 @@ object Tuple { } } + /** + * Use this type to widen a self-type to a tuple. E.g. + * ``` + * val x: (1, 3) = (1, 3) + * val y: Widen[x.type] = x + * ``` + */ + type Widen[Tup <: Tuple] <: Tuple = Tup match { + case EmptyTuple => EmptyTuple + case h *: t => h *: t + } + /** Given two tuples, `A1 *: ... *: An * At` and `B1 *: ... *: Bn *: Bt` * where at least one of `At` or `Bt` is `EmptyTuple` or `Tuple`, * returns the tuple type `(A1, B1) *: ... *: (An, Bn) *: Ct` diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index 3761c3b83606..5ae12e3d89d6 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -42,13 +42,13 @@ package object compiletime { inline def constValue[T]: T = ??? - inline def constValueTuple[T <: Tuple]: T = + inline def constValueTuple[T <: Tuple]: Tuple.Widen[T]= val res = inline erasedValue[T] match case _: EmptyTuple => EmptyTuple case _: (t *: ts) => constValue[t] *: constValueTuple[ts] end match - res.asInstanceOf[T] + res.asInstanceOf[Tuple.Widen[T]] end constValueTuple /** Summons first given matching one of the listed cases. E.g. in @@ -83,13 +83,13 @@ package object compiletime { * @tparam T the tuple containing the types of the values to be summoned * @return the given values typed as elements of the tuple */ - inline def summonAll[T <: Tuple]: T = + inline def summonAll[T <: Tuple]: Tuple.Widen[T] = val res = inline erasedValue[T] match case _: EmptyTuple => EmptyTuple case _: (t *: ts) => summonInline[t] *: summonAll[ts] end match - res.asInstanceOf[T] + res.asInstanceOf[Tuple.Widen[T]] end summonAll /** Succesor of a natural number where zero is the type 0 and successors are reduced as if the definition was From bf38180da70c85dde930424499f907e7eeec14bc Mon Sep 17 00:00:00 2001 From: Anatolii Kmetiuk Date: Thu, 25 Jun 2020 12:11:57 +0200 Subject: [PATCH 3/3] Fill in the missing docs for `compiletime` package members Typo fix Co-authored-by: Nicolas Stucki --- library/src/scala/compiletime/package.scala | 22 ++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index 5ae12e3d89d6..39cd810d30ac 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -4,6 +4,16 @@ import scala.quoted._ package object compiletime { + /** Use this method when you have a type, do not have a value for it but want to + * pattern match on it. For example, given a type `Tup <: Tuple`, one can + * pattern-match on it as follows: + * ``` + * erasedValue[Tup] match { + * case _: EmptyTuple => ... + * case _: h *: t => ... + * } + * ``` + */ erased def erasedValue[T]: T = ??? /** The error method is used to produce user-defined compile errors during inline expansion. @@ -38,10 +48,20 @@ package object compiletime { transparent inline def (inline self: StringContext) code (inline args: Any*): String = ${ dotty.internal.CompileTimeMacros.codeExpr('self, 'args) } + /** Same as `constValue` but returns a `None` if a constant value + * cannot be constructed from the provided type. Otherwise returns + * that value wrapped in `Some`. + */ inline def constValueOpt[T]: Option[T] = ??? + /** Given a constant, singleton type `T`, convert it to a value + * of the same singleton type. For example: `assert(constValue[1] == 1)`. + */ inline def constValue[T]: T = ??? + /** Given a tuple type `(X1, ..., Xn)`, returns a tuple value + * `(constValue[X1], ..., constValue[Xn])`. + */ inline def constValueTuple[T <: Tuple]: Tuple.Widen[T]= val res = inline erasedValue[T] match @@ -78,7 +98,7 @@ package object compiletime { } /** Given a tuple T, summons each of its member types and returns them in - * a List. + * a Tuple. * * @tparam T the tuple containing the types of the values to be summoned * @return the given values typed as elements of the tuple