diff --git a/src/main/scala/minisql/ast/FromExprs.scala b/src/main/scala/minisql/ast/FromExprs.scala index ef62299..b66e4b9 100644 --- a/src/main/scala/minisql/ast/FromExprs.scala +++ b/src/main/scala/minisql/ast/FromExprs.scala @@ -300,7 +300,8 @@ private def fromBlock(using given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] { def unapply(e: Expr[Ast])(using Quotes): Option[Ast] = { - e match { + val t = extractTerm(e.toTerm) + t.asExpr match { case '{ $x: Query } => x.value case '{ $x: ScalarValueLift } => x.value case '{ $x: Property } => x.value @@ -312,7 +313,10 @@ given astFromExpr: FromExpr[Ast] = new FromExpr[Ast] { case '{ $x: Action } => x.value case '{ $x: If } => x.value case '{ $x: Infix } => x.value - case o => None + case o => + import quotes.reflect.* + report.warning(s"Cannot get value from ${o.show}", o.asTerm.pos) + None } } } diff --git a/src/main/scala/minisql/dsl.scala b/src/main/scala/minisql/dsl.scala index 58f452c..43cc9c0 100644 --- a/src/main/scala/minisql/dsl.scala +++ b/src/main/scala/minisql/dsl.scala @@ -1,69 +1,44 @@ package minisql.dsl import minisql.* -import minisql.parsing +import minisql.parsing.* import minisql.ast.{Ast, Entity, Map, Property, Ident, given} import scala.quoted.* import scala.compiletime.* import scala.compiletime.ops.string.* import scala.collection.immutable.{Map => IMap} -sealed trait Quoted { - def ast: Ast - def lifts: IMap[String, (Any, ParamEncoder[?])] = IMap.empty -} +opaque type Quoted <: Ast = Ast -trait Query[E] extends Quoted +opaque type Query[E] <: Quoted = Quoted -case class EntityQuery[E](ast: Ast) extends Query[E] +opaque type EntityQuery[E] <: Query[E] = Query[E] extension [E](inline e: EntityQuery[E]) { inline def map[E1](inline f: E => E1): EntityQuery[E1] = { - transform(e.ast)(f)(Map.apply)(EntityQuery.apply[E1]) + transform(e)(f)(Map.apply) } } -private inline def transform[D1 <: Quoted, D2 <: Quoted, A, B](inline ast: Ast)( +private inline def transform[A, B](inline q1: Quoted)( inline f: A => B -)(inline fast: (Ast, Ident, Ast) => Ast)(inline f2: Ast => D2): D2 = { - f2(fast(ast, f.param0, f.body)) +)(inline fast: (Ast, Ident, Ast) => Ast): Quoted = { + fast(q1, f.param0, f.body) } -private given FromExpr[EntityQuery[?]] with { - def unapply(x: Expr[EntityQuery[?]])(using Quotes): Option[EntityQuery[?]] = { - x match { - case '{ - val x: Ast = ${ Expr(ast) } - EntityQuery(x) - } => - Some(EntityQuery(ast)) - case '{ EntityQuery(${ Expr(ast) }) } => - Some(EntityQuery(ast)) - case _ => - import quotes.reflect.* - println(s"cannot unlift ${x.show}: ${x.asTerm.getClass}") - None - } - } -} -private given FromExpr[Quoted] with { - def unapply(x: Expr[Quoted])(using Quotes): Option[Quoted] = { - import quotes.reflect.* - x match { - case '{ ($x: EntityQuery[?]) } => x.value - } - } +inline def query[E](inline table: String): EntityQuery[E] = + Entity(table, Nil) + +inline def compile(inline x: Ast): Option[String] = ${ + compileImpl('{ x }) } -inline def query[E](inline table: String) = - EntityQuery[E](Entity(table, Nil)) - -inline def compile(inline x: Quoted): Option[String] = ${ compileImpl('x) } - -private def compileImpl(x: Expr[Quoted])(using Quotes): Expr[Option[String]] = { +private def compileImpl( + x: Expr[Ast] +)(using Quotes): Expr[Option[String]] = { import quotes.reflect.* x.value match { - case Some(xv) => '{ Some(${ Expr(xv.ast.toString()) }) } + case Some(xv) => '{ Some(${ Expr(xv.toString()) }) } case None => '{ None } } } @@ -78,3 +53,7 @@ extension [A1, A2, B](inline f1: (A1, A2) => B) { private inline def param1 = parsing.parseParamAt(f1, 1) private inline def body = parsing.parseBody(f1) } + +case class Foo(id: Int) + +inline def queryFooId = query[Foo]("foo").map(_.id)