-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Companion object-based Contains derivation (fix #143)
- Loading branch information
1 parent
8cdbd60
commit 4190cc0
Showing
11 changed files
with
148 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,4 @@ node_modules/ | |
.bsp | ||
*.db | ||
.jvmopts | ||
**/.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
...s/core/src/main/scala/glass/package.scala → ...core/src/main/scala-2/glass/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package glass | ||
|
||
/** a collection of classic monomorphic optics based on http://hackage.haskell.org/package/lens and | ||
* http://julien-truffaut.github.io/Monocle/ using names readable for user unfamiliar with then capable for using as | ||
* implicit evidences in effect transmogrification | ||
*/ | ||
|
||
type Same[A, B] = PSame[A, A, B, B] | ||
type Equivalent[A, B] = PEquivalent[A, A, B, B] | ||
type Subset[A, B] = PSubset[A, A, B, B] | ||
type Contains[A, B] = PContains[A, A, B, B] | ||
type Property[A, B] = PProperty[A, A, B, B] | ||
type Repeated[A, B] = PRepeated[A, A, B, B] | ||
type Items[A, B] = PItems[A, A, B, B] | ||
type Reduced[A, B] = PReduced[A, A, B, B] | ||
type Downcast[A, B] = PDowncast[A, A, B, B] | ||
type Upcast[A, B] = PUpcast[A, A, B, B] | ||
type Extract[A, B] = PExtract[A, A, B, B] | ||
type Folded[A, B] = PFolded[A, A, B, B] | ||
type Update[A, B] = PUpdate[A, A, B, B] | ||
type Zipping[A, B] = PZipping[A, A, B, B] | ||
|
||
/** label provider for instance discrimination like Contains[A, B] with Label["first"] | ||
*/ | ||
type Label[label] = Any { | ||
type Label = label | ||
} |
10 changes: 10 additions & 0 deletions
10
modules/macro/src/main/scala-3/glass/macros/DeriveContains.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package glass.macros | ||
|
||
import glass.macros.internal.{CompanionClass, ContainsFor} | ||
|
||
trait DeriveContains: | ||
given conversion(using | ||
cc: CompanionClass[this.type], | ||
contains: ContainsFor[cc.Type] | ||
): Conversion[this.type, contains.Out] = | ||
_ => contains.contains |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
modules/macro/src/main/scala-3/glass/macros/internal/ContainsSelector.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package glass.macros.internal | ||
|
||
import glass.* | ||
|
||
private[macros] class ContainsSelector[A](lenses: Map[String, PContains[A, A, ?, ?]]) extends Selectable: | ||
inline def selectDynamic(name: String): PContains[A, A, ?, ?] = | ||
lenses(name) |
89 changes: 89 additions & 0 deletions
89
modules/macro/src/main/scala-3/glass/macros/internal/impl.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package glass.macros.internal | ||
|
||
import glass.* | ||
import quotidian.* | ||
import quotidian.syntax.* | ||
import quoted.* | ||
|
||
private[macros] object ContainsMacro: | ||
def mkContainsImpl[A: Type, B: Type](expr: Expr[A => B])(using Quotes): Expr[PContains[A, A, B, B]] = | ||
import quotes.reflect.* | ||
expr.asTerm.underlyingArgument match | ||
case Lambda(_, select @ Select(a, b)) => | ||
val productMirror = MacroMirror.summonProduct[A] | ||
|
||
val elem = productMirror | ||
.elemForSymbol(select.symbol) | ||
.getOrElse( | ||
report.errorAndAbort(s"Invalid selector ${select.show}, must be a field of ${productMirror.monoType.show}") | ||
) | ||
.asElemOf[B] | ||
|
||
'{ | ||
new PContains[A, A, B, B]: | ||
def extract(a: A) = ${ elem.get('a) } | ||
def set(a: A, b: B) = ${ elem.set('a, 'b) } | ||
} | ||
case other => report.errorAndAbort(s"Expected a selector of the form `s => a`, but got: ${other}") | ||
|
||
implicit transparent inline def makeContainses[S]: Any = ${ makeContainsesImpl[S] } | ||
|
||
def makeContainsesImpl[S: Type](using Quotes): Expr[Any] = | ||
import quotes.reflect.* | ||
|
||
val productMirror = MacroMirror.summonProduct[S] | ||
|
||
val containsMap = Expr.ofMap(productMirror.elems.map { elem => | ||
import elem.asType | ||
val selector = '{ (s: S) => ${ elem.get('s) } } | ||
elem.label -> mkContainsImpl(selector) | ||
}) | ||
|
||
val refinedType = | ||
Refinement.of[ContainsSelector[S]]( | ||
productMirror.elemsWithTypes.map { case (elem, '[a]) => | ||
elem.label -> TypeRepr.of[PContains[S, S, a, a]] | ||
} | ||
) | ||
|
||
refinedType.asType match | ||
case '[t] => | ||
'{ new ContainsSelector[S]($containsMap).asInstanceOf[t] } | ||
|
||
private[macros] trait ContainsFor[A]: | ||
type Out | ||
|
||
def contains: Out | ||
|
||
private[macros] object ContainsFor: | ||
transparent inline given derived[A]: ContainsFor[A] = ${ containsForImpl[A] } | ||
|
||
private def containsForImpl[A: Type](using Quotes) = | ||
import quotes.reflect.* | ||
val lensesExpr = ContainsMacro.makeContainsesImpl[A] | ||
lensesExpr.asTerm.tpe.asType match | ||
case '[t] => | ||
'{ | ||
new ContainsFor[A]: | ||
type Out = t | ||
|
||
def contains: t = $lensesExpr.asInstanceOf[t] | ||
} | ||
|
||
private[macros] trait CompanionClass[A]: | ||
type Type | ||
|
||
private[macros] object CompanionClass: | ||
transparent inline given [A]: CompanionClass[A] = ${ companionImpl[A] } | ||
|
||
private def companionImpl[A: Type](using Quotes) = | ||
import quotes.reflect.* | ||
val companionClass = TypeRepr.companionClassOf[A] | ||
if companionClass.typeSymbol.isNoSymbol then report.errorAndAbort(s"No companion class found for ${Type.show[A]}") | ||
|
||
TypeRepr.companionClassOf[A].asType match | ||
case '[t] => | ||
'{ | ||
new CompanionClass[A]: | ||
type Type = t | ||
} |
53 changes: 0 additions & 53 deletions
53
modules/macro/src/main/scala-3/glass/macros/internal/utils.scala
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ case object B extends A | |
case object C extends A | ||
|
||
case class Bar(i: Int) | ||
object Bar extends DeriveContains |