This commit is contained in:
jilen 2024-11-14 19:46:36 +08:00
parent 1878d59821
commit 2d30969ec5
5 changed files with 68 additions and 70 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
target/ target/
.bsp/ .bsp/
.metals/ .metals/
.bloop/
project/metals.sbt

View file

@ -1 +1 @@
sbt.version=1.10.2 sbt.version=1.10.5

View file

@ -0,0 +1,8 @@
// format: off
// DO NOT EDIT! This file is auto-generated.
// This file enables sbt-bloop to create bloop config files.
addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.6.0")
// format: on

View file

@ -81,16 +81,16 @@ case class ConcatMap(query: Ast, alias: Ident, body: Ast) extends Query
case class SortBy(query: Ast, alias: Ident, criterias: Ast, ordering: Ordering) case class SortBy(query: Ast, alias: Ident, criterias: Ast, ordering: Ordering)
extends Query extends Query
sealed trait Ordering extends Ast sealed trait Ordering extends Ast
case class TupleOrdering(elems: List[Ordering]) extends Ordering case class TupleOrdering(elems: List[Ordering]) extends Ordering
sealed trait PropertyOrdering extends Ordering sealed trait PropertyOrdering extends Ordering
case object Asc extends PropertyOrdering case object Asc extends PropertyOrdering
case object Desc extends PropertyOrdering case object Desc extends PropertyOrdering
case object AscNullsFirst extends PropertyOrdering case object AscNullsFirst extends PropertyOrdering
case object DescNullsFirst extends PropertyOrdering case object DescNullsFirst extends PropertyOrdering
case object AscNullsLast extends PropertyOrdering case object AscNullsLast extends PropertyOrdering
case object DescNullsLast extends PropertyOrdering case object DescNullsLast extends PropertyOrdering
case class GroupBy(query: Ast, alias: Ident, body: Ast) extends Query case class GroupBy(query: Ast, alias: Ident, body: Ast) extends Query
@ -154,7 +154,7 @@ case class Ident(name: String, visibility: Visibility) extends Ast {
*/ */
object Ident { object Ident {
def apply(name: String): Ident = Ident(name, Visibility.neutral) def apply(name: String): Ident = Ident(name, Visibility.neutral)
def unapply(p: Ident) = Some((p.name)) def unapply(p: Ident) = Some((p.name))
object Opinionated { object Opinionated {
def apply(name: String, visibilityNew: Visibility): Ident = def apply(name: String, visibilityNew: Visibility): Ident =
@ -188,7 +188,7 @@ sealed trait OpinionValues[T <: Opinion[T]] {
sealed trait Visibility extends Opinion[Visibility] sealed trait Visibility extends Opinion[Visibility]
object Visibility extends OpinionValues[Visibility] { object Visibility extends OpinionValues[Visibility] {
case object Visible extends Visibility with Opinion[Visibility] case object Visible extends Visibility with Opinion[Visibility]
case object Hidden extends Visibility with Opinion[Visibility] case object Hidden extends Visibility with Opinion[Visibility]
inline override def neutral: Visibility = Visible inline override def neutral: Visibility = Visible
} }
@ -201,7 +201,7 @@ sealed trait Renameable extends Opinion[Renameable] {
} }
} }
object Renameable extends OpinionValues[Renameable] { object Renameable extends OpinionValues[Renameable] {
case object Fixed extends Renameable with Opinion[Renameable] case object Fixed extends Renameable with Opinion[Renameable]
case object ByStrategy extends Renameable with Opinion[Renameable] case object ByStrategy extends Renameable with Opinion[Renameable]
inline override def neutral: Renameable = ByStrategy inline override def neutral: Renameable = ByStrategy
@ -248,8 +248,8 @@ object Property {
} }
} }
sealed trait OptionOperation extends Ast sealed trait OptionOperation extends Ast
case class OptionFlatten(ast: Ast) extends OptionOperation case class OptionFlatten(ast: Ast) extends OptionOperation
case class OptionGetOrElse(ast: Ast, body: Ast) extends OptionOperation case class OptionGetOrElse(ast: Ast, body: Ast) extends OptionOperation
case class OptionFlatMap(ast: Ast, alias: Ident, body: Ast) case class OptionFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation extends OptionOperation
@ -259,9 +259,9 @@ case class OptionForall(ast: Ast, alias: Ident, body: Ast)
case class OptionExists(ast: Ast, alias: Ident, body: Ast) case class OptionExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation extends OptionOperation
case class OptionContains(ast: Ast, body: Ast) extends OptionOperation case class OptionContains(ast: Ast, body: Ast) extends OptionOperation
case class OptionIsEmpty(ast: Ast) extends OptionOperation case class OptionIsEmpty(ast: Ast) extends OptionOperation
case class OptionNonEmpty(ast: Ast) extends OptionOperation case class OptionNonEmpty(ast: Ast) extends OptionOperation
case class OptionIsDefined(ast: Ast) extends OptionOperation case class OptionIsDefined(ast: Ast) extends OptionOperation
case class OptionTableFlatMap(ast: Ast, alias: Ident, body: Ast) case class OptionTableFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation extends OptionOperation
case class OptionTableMap(ast: Ast, alias: Ident, body: Ast) case class OptionTableMap(ast: Ast, alias: Ident, body: Ast)
@ -270,15 +270,15 @@ case class OptionTableExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation extends OptionOperation
case class OptionTableForall(ast: Ast, alias: Ident, body: Ast) case class OptionTableForall(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation extends OptionOperation
object OptionNone extends OptionOperation object OptionNone extends OptionOperation
case class OptionSome(ast: Ast) extends OptionOperation case class OptionSome(ast: Ast) extends OptionOperation
case class OptionApply(ast: Ast) extends OptionOperation case class OptionApply(ast: Ast) extends OptionOperation
case class OptionOrNull(ast: Ast) extends OptionOperation case class OptionOrNull(ast: Ast) extends OptionOperation
case class OptionGetOrNull(ast: Ast) extends OptionOperation case class OptionGetOrNull(ast: Ast) extends OptionOperation
sealed trait IterableOperation extends Ast sealed trait IterableOperation extends Ast
case class MapContains(ast: Ast, body: Ast) extends IterableOperation case class MapContains(ast: Ast, body: Ast) extends IterableOperation
case class SetContains(ast: Ast, body: Ast) extends IterableOperation case class SetContains(ast: Ast, body: Ast) extends IterableOperation
case class ListContains(ast: Ast, body: Ast) extends IterableOperation case class ListContains(ast: Ast, body: Ast) extends IterableOperation
case class If(condition: Ast, `then`: Ast, `else`: Ast) extends Ast case class If(condition: Ast, `then`: Ast, `else`: Ast) extends Ast
@ -318,7 +318,7 @@ sealed trait Action extends Ast
case class Update(query: Ast, assignments: List[Assignment]) extends Action case class Update(query: Ast, assignments: List[Assignment]) extends Action
case class Insert(query: Ast, assignments: List[Assignment]) extends Action case class Insert(query: Ast, assignments: List[Assignment]) extends Action
case class Delete(query: Ast) extends Action case class Delete(query: Ast) extends Action
sealed trait ReturningAction extends Action { sealed trait ReturningAction extends Action {
def action: Ast def action: Ast
@ -358,11 +358,11 @@ object OnConflict {
} }
sealed trait Target sealed trait Target
case object NoTarget extends Target case object NoTarget extends Target
case class Properties(props: List[Property]) extends Target case class Properties(props: List[Property]) extends Target
sealed trait Action sealed trait Action
case object Ignore extends Action case object Ignore extends Action
case class Update(assignments: List[Assignment]) extends Action case class Update(assignments: List[Assignment]) extends Action
} }
//************************************************************ //************************************************************
@ -386,34 +386,15 @@ sealed trait ScalarLift extends Lift
case class ScalarValueLift( case class ScalarValueLift(
name: String, name: String,
liftId: String liftId: String
) extends ScalarLift { ) extends ScalarLift
def expandedLiftId: Option[(String, Int)] = {
val idxStart = liftId.indexOf('[')
val idxEnd = liftId.indexOf(']')
if (idxStart != -1 && idxEnd != -1) {
val idx = liftId.substring(idxStart + 1, idxEnd).toIntOption
idx.map(i => liftId.substring(0, idxStart) -> i)
} else None
}
}
case class ScalarQueryLift(name: String, liftId: String) extends ScalarLift {
def at(idx: Int): ScalarValueLift =
ScalarValueLift(s"${name}[$idx]", s"${liftId}[${idx}]")
}
object ScalarLift { object ScalarLift {
given ToExpr[ScalarLift] with { given ToExpr[ScalarLift] with {
def apply(l: ScalarLift)(using Quotes) = l match { def apply(l: ScalarLift)(using Quotes) = l match {
case ScalarValueLift(n, id) => case ScalarValueLift(n, id) =>
'{ ScalarValueLift(${ Expr(n) }, ${ Expr(id) }) } '{ ScalarValueLift(${ Expr(n) }, ${ Expr(id) }) }
case ScalarQueryLift(n, id) =>
'{ ScalarQueryLift(${ Expr(n) }, ${ Expr(id) }) }
} }
} }
} }
sealed trait CaseClassLift extends Lift sealed trait CaseClassLift extends Lift
case class CaseClassQueryLift(name: String, liftId: String)
extends CaseClassLift

View file

@ -1,39 +1,46 @@
package minisql.dsl package minisql.dsl
import minisql.ast.{Ast, Entity, given}
import scala.quoted.* import scala.quoted.*
import scala.compiletime.* import scala.compiletime.*
import scala.compiletime.ops.string.* import scala.compiletime.ops.string.*
trait Quoted[E] { sealed trait Dsl {
type Ast
def ast: Ast def ast: Ast
def liftings: Map[String, Any]
} }
object Quoted { trait Query[E] extends Dsl
def apply[_Ast <: String, E](
_ast: Ast, class EntityQuery[E](val ast: Ast) extends Query
_liftings: Map[String, Any]
): Quoted[_Ast, E] = given FromExpr[EntityQuery[?]] with {
new Quoted[_Ast] { def unapply(x: Expr[EntityQuery[?]])(using Quotes): Option[EntityQuery[?]] = {
type Ast = _Ast x match {
def ast = _ast case '{ EntityQuery(${ Expr(ast) }) } =>
def liftings = _liftings Some(EntityQuery(ast))
case _ =>
import quotes.reflect.*
println(s"cannot unlift ${x.asTerm}")
None
} }
}
inline def transform[A1 <: String, A2 <: String, A3 <: String]( }
inline q1: Quoted[A1], given FromExpr[Dsl] with {
inline q2: Quoted[A2] def unapply(d: Expr[Dsl])(using Quotes): Option[Dsl] = d match {
)(inline f: (A1, A2) => A3): Quoted[A3] = case '{ ($x: EntityQuery[?]) } => x.value
Quoted[A3](q1.liftings ++ q2.liftings) }
} }
case class Foo() inline def query[E](inline table: String) =
EntityQuery[E](Entity(table, Nil))
opaque type Query[E] <: Quoted[E] = Quoted[E] inline def compile(inline x: Dsl): Option[String] = ${ compileImpl('x) }
opaque type EntityQuery[E] <: Quoted[E] & Query[E] = Quoted[E]
private def compileImpl(x: Expr[Dsl])(using Quotes): Expr[Option[String]] = {
import quotes.reflect.*
x.value match {
case Some(xv) => '{ Some(${ Expr(xv.ast.toString()) }) }
case None => '{ None }
}
extension [E](e: EntityQuery[E]) {
inline def map[E1](inline f: E => E1): EntityQuery[E1] = Quoted[]()
} }