allow parsing block

This commit is contained in:
jilen 2024-11-16 20:04:56 +08:00
parent 2d30969ec5
commit 26572ffa0d
2 changed files with 60 additions and 18 deletions

View file

@ -69,7 +69,7 @@ private given FromExpr[Property] with {
} =>
Some(Property(a, n, r, v))
case o =>
println(s"Canot extrat ${o.show}:${x}")
println(s"Cannot extrat ${o.show}")
None
}
}
@ -252,23 +252,54 @@ extension (e: Expr[Any]) {
}
}
given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] {
private def fromBlock(using
Quotes
)(block: quotes.reflect.Block): Option[Ast] = {
import quotes.reflect.*
val empty: Option[List[Ast]] = Some(Nil)
val stmts = block.statements.foldLeft(empty) { (r, stmt) =>
stmt match {
case ValDef(n, _, Some(body)) =>
r.flatMap { astList =>
body.asExprOf[Ast].value.map { v =>
astList :+ v
}
}
def unapply(e: Expr[Ast])(using Quotes): Option[Ast] = {
extractTerm(e.toTerm).asExpr match {
case '{ $x: Query } => x.value
case '{ $x: ScalarValueLift } => x.value
case '{ $x: Property } => x.value
case '{ $x: Ident } => x.value
case '{ $x: Tuple } => x.value
case '{ $x: Constant } => x.value
case '{ $x: Operation } => x.value
case '{ $x: Ordering } => x.value
case '{ $x: Action } => x.value
case '{ $x: If } => x.value
case '{ $x: Infix } => x.value
case o => None
case o =>
None
}
}
stmts.flatMap { stmts =>
block.expr.asExprOf[Ast].value.map { last =>
minisql.ast.Block(stmts :+ last)
}
}
}
given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] {
def unapply(e: Expr[Ast])(using Quotes): Option[Ast] = {
val et = extractTerm(e.toTerm)
et match {
case b: quotes.reflect.Block => fromBlock(b)
case b: quotes.reflect.Ident => Some(Ident(b.name))
case o =>
o.asExpr match {
case '{ $x: Query } => x.value
case '{ $x: ScalarValueLift } => x.value
case '{ $x: Property } => x.value
case '{ $x: Ident } => x.value
case '{ $x: Tuple } => x.value
case '{ $x: Constant } => x.value
case '{ $x: Operation } => x.value
case '{ $x: Ordering } => x.value
case '{ $x: Action } => x.value
case '{ $x: If } => x.value
case '{ $x: Infix } => x.value
case o => None
}
}
}
}

View file

@ -1,6 +1,6 @@
package minisql.dsl
import minisql.ast.{Ast, Entity, given}
import minisql.ast.{Ast, Entity, Map, Property, Ident, given}
import scala.quoted.*
import scala.compiletime.*
import scala.compiletime.ops.string.*
@ -13,6 +13,11 @@ trait Query[E] extends Dsl
class EntityQuery[E](val ast: Ast) extends Query
extension [E](inline e: EntityQuery[E]) {
inline def mapAst[E1](inline f: Ast => Ast): EntityQuery[E1] =
EntityQuery[E1](f(e.ast))
}
given FromExpr[EntityQuery[?]] with {
def unapply(x: Expr[EntityQuery[?]])(using Quotes): Option[EntityQuery[?]] = {
x match {
@ -44,3 +49,9 @@ private def compileImpl(x: Expr[Dsl])(using Quotes): Expr[Option[String]] = {
}
}
case class Foo(id: Int)
inline def queryFooId =
query[Foo]("foo").mapAst[Int](x =>
Map(x, Ident("x"), Property(Ident("x"), "id"))
)