Compare commits

...

2 commits

Author SHA1 Message Date
2d30969ec5 save 2024-11-14 19:46:36 +08:00
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

@ -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]) = {
private def extractTerm(using Quotes)(x: quotes.reflect.Term) = {
import quotes.reflect.*
val t1 = TypeRepr.of[t].dealias.simplified
println(s"isAstType ${TypeRepr.of[t]} ===> ${t1}")
t1 <:< TypeRepr.of[Ast]
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 }
}
}