Compare commits

...

2 commits

Author SHA1 Message Date
jilen
2d30969ec5 save 2024-11-14 19:46:36 +08:00
jilen
1878d59821 rename 2024-11-05 17:17:59 +08:00
25 changed files with 121 additions and 107 deletions

2
.gitignore vendored
View file

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

View file

@ -1,4 +1,4 @@
version = "3.8.1"
version = "3.8.3"
style = defaultWithAlign
runner.dialect=scala3
maxColumn = 80

View file

@ -1,9 +1,8 @@
name := "minisql"
scalaVersion := "3.5.0-RC4"
scalaVersion := "3.5.2"
libraryDependencies ++= Seq(
)
scalacOptions ++= Seq("-experimental")
scalacOptions ++= Seq("-experimental", "-language:experimental.namedTuples")

View file

@ -1 +1 @@
sbt.version=1.10.0
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

@ -1 +0,0 @@
jilen@jilendeiMac.2465

View file

@ -1,28 +0,0 @@
package minisql
import scala.collection.immutable.{Map => IMap}
import scala.quoted.*
import minisql.ast.{*, given}
import scala.deriving.*
import scala.compiletime.*
sealed trait Query[T] {
def ast: Ast
}
case class Column
case class EntityQuery[A](ast: Entity) extends Query
inline def compile(inline e: Ast): Unit = ${ compileImpl('e) }
private def compileImpl(e: Expr[Ast])(using Quotes) = {
import quotes.reflect.*
e.value match {
case Some(v) =>
report.info("Static:" + v.toString())
case None =>
report.info("Dynamic")
}
'{ () }
}

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)
extends Query
sealed trait Ordering extends Ast
sealed trait Ordering extends Ast
case class TupleOrdering(elems: List[Ordering]) extends Ordering
sealed trait PropertyOrdering extends Ordering
case object Asc extends PropertyOrdering
case object Desc extends PropertyOrdering
case object AscNullsFirst extends PropertyOrdering
case object DescNullsFirst extends PropertyOrdering
case object AscNullsLast extends PropertyOrdering
case object DescNullsLast extends PropertyOrdering
case object Asc extends PropertyOrdering
case object Desc extends PropertyOrdering
case object AscNullsFirst extends PropertyOrdering
case object DescNullsFirst extends PropertyOrdering
case object AscNullsLast extends PropertyOrdering
case object DescNullsLast extends PropertyOrdering
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 {
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 {
def apply(name: String, visibilityNew: Visibility): Ident =
@ -188,7 +188,7 @@ sealed trait OpinionValues[T <: Opinion[T]] {
sealed trait Visibility extends Opinion[Visibility]
object Visibility extends OpinionValues[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
}
@ -201,7 +201,7 @@ sealed trait Renameable extends Opinion[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]
inline override def neutral: Renameable = ByStrategy
@ -248,8 +248,8 @@ object Property {
}
}
sealed trait OptionOperation extends Ast
case class OptionFlatten(ast: Ast) extends OptionOperation
sealed trait OptionOperation extends Ast
case class OptionFlatten(ast: Ast) extends OptionOperation
case class OptionGetOrElse(ast: Ast, body: Ast) extends OptionOperation
case class OptionFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
@ -259,9 +259,9 @@ case class OptionForall(ast: Ast, alias: Ident, body: Ast)
case class OptionExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionContains(ast: Ast, body: Ast) extends OptionOperation
case class OptionIsEmpty(ast: Ast) extends OptionOperation
case class OptionNonEmpty(ast: Ast) extends OptionOperation
case class OptionIsDefined(ast: Ast) extends OptionOperation
case class OptionIsEmpty(ast: Ast) extends OptionOperation
case class OptionNonEmpty(ast: Ast) extends OptionOperation
case class OptionIsDefined(ast: Ast) extends OptionOperation
case class OptionTableFlatMap(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionTableMap(ast: Ast, alias: Ident, body: Ast)
@ -270,15 +270,15 @@ case class OptionTableExists(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
case class OptionTableForall(ast: Ast, alias: Ident, body: Ast)
extends OptionOperation
object OptionNone extends OptionOperation
case class OptionSome(ast: Ast) extends OptionOperation
case class OptionApply(ast: Ast) extends OptionOperation
case class OptionOrNull(ast: Ast) extends OptionOperation
object OptionNone extends OptionOperation
case class OptionSome(ast: Ast) extends OptionOperation
case class OptionApply(ast: Ast) extends OptionOperation
case class OptionOrNull(ast: Ast) extends OptionOperation
case class OptionGetOrNull(ast: Ast) extends OptionOperation
sealed trait IterableOperation extends Ast
case class MapContains(ast: Ast, body: Ast) extends IterableOperation
case class SetContains(ast: Ast, body: Ast) extends IterableOperation
sealed trait IterableOperation extends Ast
case class MapContains(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 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 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 {
def action: Ast
@ -358,11 +358,11 @@ object OnConflict {
}
sealed trait Target
case object NoTarget extends Target
case object NoTarget extends Target
case class Properties(props: List[Property]) extends Target
sealed trait Action
case object Ignore extends Action
case object Ignore extends Action
case class Update(assignments: List[Assignment]) extends Action
}
//************************************************************
@ -386,34 +386,15 @@ sealed trait ScalarLift extends Lift
case class ScalarValueLift(
name: String,
liftId: String
) 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}]")
}
) extends ScalarLift
object ScalarLift {
given ToExpr[ScalarLift] with {
def apply(l: ScalarLift)(using Quotes) = l match {
case ScalarValueLift(n, id) =>
'{ ScalarValueLift(${ Expr(n) }, ${ Expr(id) }) }
case ScalarQueryLift(n, id) =>
'{ ScalarQueryLift(${ Expr(n) }, ${ Expr(id) }) }
}
}
}
sealed trait CaseClassLift extends Lift
case class CaseClassQueryLift(name: String, liftId: String)
extends CaseClassLift

View file

@ -68,6 +68,9 @@ private given FromExpr[Property] with {
)
} =>
Some(Property(a, n, r, v))
case o =>
println(s"Canot extrat ${o.show}:${x}")
None
}
}
@ -103,6 +106,9 @@ private given FromExpr[Query] with {
Some(Take(b, n))
case '{ SortBy(${ Expr(b) }, ${ Expr(p) }, ${ Expr(s) }, ${ Expr(o) }) } =>
Some(SortBy(b, p, s, o))
case o =>
println(s"Cannot extract ${o.show}")
None
}
}
@ -220,17 +226,37 @@ private given FromExpr[If] with {
}
}
private[minisql] given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] {
private def isAstType[t](using Quotes, Type[t]) = {
import quotes.reflect.*
val t1 = TypeRepr.of[t].dealias.simplified
println(s"isAstType ${TypeRepr.of[t]} ===> ${t1}")
t1 <:< TypeRepr.of[Ast]
private def extractTerm(using Quotes)(x: quotes.reflect.Term) = {
import quotes.reflect.*
def unwrapTerm(t: Term): Term = t match {
case Inlined(_, _, o) => unwrapTerm(o)
case Block(Nil, last) => last
case Typed(t, _) =>
unwrapTerm(t)
case Select(t, "$asInstanceOf$") =>
unwrapTerm(t)
case TypeApply(t, _) =>
unwrapTerm(t)
case o => o
}
val o = unwrapTerm(x)
println(s"From ========== ${x.show}")
println(s"To ========== ${o.show}")
o
}
extension (e: Expr[Any]) {
def toTerm(using Quotes) = {
import quotes.reflect.*
e.asTerm
}
}
given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] {
def unapply(e: Expr[Ast])(using Quotes): Option[Ast] = {
e match {
extractTerm(e.toTerm).asExpr match {
case '{ $x: Query } => x.value
case '{ $x: ScalarValueLift } => x.value
case '{ $x: Property } => x.value
@ -242,26 +268,7 @@ private[minisql] given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] {
case '{ $x: Action } => x.value
case '{ $x: If } => x.value
case '{ $x: Infix } => x.value
case '{ ($x: Ast).asInstanceOf } =>
unapply(x.asInstanceOf)
case '{ (${ x }: t1).asInstanceOf[t2] } if isAstType[t2] =>
unapply(x.asInstanceOf)
case o =>
import quotes.reflect.*
def unwrapInline(x: Term): Unit = x match {
case Inlined(_, bs, t) =>
unwrapInline(t)
case Typed(t, _) =>
unwrapInline(t)
case TypeApply(t, _) =>
unwrapInline(t)
// case Select(x, "$asInstanceOf$") =>
// unwrapInline(x)
case o =>
println(s"unwrapped term(${o.getClass}): ${o.show}")
}
unwrapInline(o.asTerm)
None
case o => None
}
}
}

View file

@ -0,0 +1,46 @@
package minisql.dsl
import minisql.ast.{Ast, Entity, given}
import scala.quoted.*
import scala.compiletime.*
import scala.compiletime.ops.string.*
sealed trait Dsl {
def ast: Ast
}
trait Query[E] extends Dsl
class EntityQuery[E](val ast: Ast) extends Query
given FromExpr[EntityQuery[?]] with {
def unapply(x: Expr[EntityQuery[?]])(using Quotes): Option[EntityQuery[?]] = {
x match {
case '{ EntityQuery(${ Expr(ast) }) } =>
Some(EntityQuery(ast))
case _ =>
import quotes.reflect.*
println(s"cannot unlift ${x.asTerm}")
None
}
}
}
given FromExpr[Dsl] with {
def unapply(d: Expr[Dsl])(using Quotes): Option[Dsl] = d match {
case '{ ($x: EntityQuery[?]) } => x.value
}
}
inline def query[E](inline table: String) =
EntityQuery[E](Entity(table, Nil))
inline def compile(inline x: Dsl): Option[String] = ${ compileImpl('x) }
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 }
}
}