Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Luis Miguel Mejía Suárez
    @BalmungSan
    Did you checked how literally does it?
    Mason Lazalier Edmison
    @masonedmison
    Ah I have not, good call.
    I was looking at protoquill for some inspo but that stuff is still above my head.
    Mason Lazalier Edmison
    @masonedmison
    Ah it doesn't look like Literally actually uses the Expr[Seq[Any]] - only in reporting an error if interpolation is not supported (here)[https://github.com/typelevel/literally/blob/main/core/shared/src/main/scala-3/org/typelevel/literally/Literally.scala#L41]

    Alex Ioffe suggested doing something like this

    def myMacro(builder: DeferredQueryBuilder): Something = ${ myMacroImpl('builder) }
    def myMacroImpl(builder: Expr[DeferredQueryBuilder])(using Quotes): Expr[Something] =
      builder match
        case '{ CypherStringInterpolator($partsExpr).c(${ Varargs(params) }: _*) } => 
          partsExpr match
            case '{ StringContext.apply(${ Varargs(parts) }: _*) } =>
              // at this point you have parts: Expr[Seq[String]] and params: Expr[Seq[Any]] or something like that

    but I am not sure how we would pass in DeferredQueryBuilder since that is what the macro itself returns.

    Luis Miguel Mejía Suárez
    @BalmungSan
    So I think it should be the opposite.
    def myMacroImpl(builder: Expr[Seq[Any]])(using Quotes): Expr[DeferredQueryBuilder] =
    Or something, I really have not even looked into a hello world example of Scala 3 macros
    Mason Lazalier Edmison
    @masonedmison
    Still plugging away on this. Getting... closer I think/hope?
    Luis Miguel Mejía Suárez
    @BalmungSan
    No worries, thanks a lot fot he hard work!
    Mason Lazalier Edmison
    @masonedmison
    This still needs a lot of work (and the way parts is currently is downright wonky) but after a few days of wrestling with this, I at least have something that compiles so I will savor this as a milestone :sweat_smile:
    package neotypes
    
    import scala.quoted._
    import internal.utils.queryparts.createQuery
    import scala.reflect.*
    import neotypes.types.QueryParam
    import scala.annotation.tailrec
    
    final case class CypherStringInterpolator(private val sc: StringContext) extends AnyVal {
      inline def c(inline args: Any*): DeferredQueryBuilder = ${ CypherStringInterpolator.macroImpl('args, 'sc) }
    }
    
    object CypherStringInterpolator {
    
      type Res = Either[String, QueryArg]
    
      def macroImpl(argsExpr: Expr[Seq[Any]], clz: Expr[StringContext])(using quotes: Quotes): Expr[DeferredQueryBuilder] =
        import quotes.reflect.*
    
        def invert[T: Type](exprs: Expr[Seq[T]]): List[Expr[T]] =
          exprs match {
            case Varargs(props)                     => props.toList
            case '{ Seq(${ Varargs(props) }) }      => props.toList.map(_.asExprOf[T])
            case _ => println(s"Unable to match ${exprs.show} "); null
          }
    
        def argMapperFor(tt: TypeRepr) =
          TypeRepr.of[QueryArgMapper].appliedTo(tt)
    
        def asRightQueryArg(expr: Expr[Any]): Expr[Res] =  
          val tt = expr.asTerm.tpe.widen
          Implicits.search(argMapperFor(tt)) match {
            case iss: ImplicitSearchSuccess => {
              val tcl = iss.tree
              val e = Apply(Select.unique(tcl, "toArg"), expr.asTerm :: Nil)
                .asExprOf[QueryArg]
              '{ Right($e) }  
    
          }
            case isf: ImplicitSearchFailure =>
              val e = Expr(isf.explanation)
              '{ compiletime.error($e) }
        }
    
        def parts: List[Expr[Boolean => Res]] = {
          val inverted = invert(argsExpr)
          inverted  
            .map { (expr: Expr[Any]) => 
              val qarg: Expr[Res] = asRightQueryArg(expr)
              '{
                (b: Boolean) => 
                  if (b) 
                    $qarg
                  else Left($expr.toString)
              } 
            }
        }
    
        val partsPacked: Expr[List[Boolean => Res]] = Expr.ofList(parts)
    
        val boolsAndRes: Expr[(List[Boolean], List[Res])] = '{ 
          $clz
            .parts
            .foldLeft((List.empty[Boolean], List.empty[Res])) { case ((hashTags, res), s) =>
                val nextRes = Left(s) :: res
                if (s.endsWith("#"))
                  (false :: hashTags) -> nextRes
                else
                  (true :: hashTags) -> nextRes
            }
        }
    
        val interleaved: Expr[List[Res]] = 
          '{
            Interleave($partsPacked, $boolsAndRes._2, $boolsAndRes._1)
          }
        '{ createQuery($interleaved: _*) }
      }
    
      object Interleave {
        import CypherStringInterpolator.Res
        def apply(parts: List[Boolean => Res], queries: List[Res], endWithHashTags: List[Boolean]): List[Res] =
          interleave(parts, queries, endWithHashTags, List.empty)
        private[this] def interleave(parts: List[Boolean => Res], queries: List[Res], endWithHashTags: List[Boolean], acc: List[Res]): List[Res] =
          (queries, parts, endWithHashTags) match {
            case (Nil, l2, b)            => acc.reverse ++ (l2 zip b).map { case (e, b) => e(b)} 
            case (l1, Nil, _)            => acc.reverse ++ l1
            case (h1 :: t1, h2 :: t2, bh :: bt) => interleave(t2, t1, bt, h2(bh) +: h1 +: acc)
            case _ => acc
        }
      }
    Luis Miguel Mejía Suárez
    @BalmungSan
    :tada: :tada: :tada:
    Aaron Hiniker
    @hindog
    hey all, is there a way to execute a query with results and ALSO get the ResultSummary somehow? From what I've seen, the only way to get a ResultSummary back is by using the execute method but I also want to return records
    Luis Miguel Mejía Suárez
    @BalmungSan
    @hindog hi, not really, you are right.
    But, it should be possible quite easily to fix that.
    Please, open an issue
    Aaron Hiniker
    @hindog
    will do, thanks
    Luis Miguel Mejía Suárez
    @BalmungSan
    Hi @masonedmison now that neotypes/neotypes#563 is ready
    I was planning to merge and release 0.23.0 soon. However, wanted to confirm first with you, because I would rather publish for Scala 3 before doing that.
    (BTW, any review in that PR would be welcome)
    Mason Lazalier Edmison
    @masonedmison
    @BalmungSan Hi. Sorry I haven't done much work on the scala3 support since my last post above. Assuming my first attempts at the generic and CypherStringInterpolator stuff is not totally off base, the remaining work to be done it to move the shapeless2 specific tests to a separate scala-2 directory. I can try to spend some time on this week in which case we might have something ready for review in the next week or two? Sorry this is taking so long btw.
    I'll try to peek that MR in the next day or two :)
    Luis Miguel Mejía Suárez
    @BalmungSan
    @masonedmison hey no worries, I didn't want to push rather to know the current state and maybe to know if I can help.
    I don't mind waiting a couple of days more, since I would rather publish Scala 3 support before dropping Java 8 and Java 11 support.
    But, also, I actually don't mind that much since I personally am already using Java 17 but no Scala 3.
    And based on the feedback from the issue it seems most folks using neotypes also don't have a problem upgrading Java
    Mason Lazalier Edmison
    @masonedmison
    @BalmungSan Sounds good. I will try to push my latest changes tomorrow and provide a more detailed to-do list in case you would like to help out a bit :).
    Luis Miguel Mejía Suárez
    @BalmungSan
    :D
    Luis Miguel Mejía Suárez
    @BalmungSan
    Oh, I forgot to mention here, sorry.
    @/all neotypes version 0.23.0 was released last weekend! It upgraded to the Java driver series 5 and thus requires Java 17.
    Luis Miguel Mejía Suárez
    @BalmungSan
    @/all neotypes version 0.23.1 was released! It upgraded to the Java driver to 5.3.0
    geoffjohn11
    @geoffjohn11
    :tada:
    Luis Miguel Mejía Suárez
    @BalmungSan

    Hi all, I have been working on something related to neotypes.
    I am calling the project Neotypes-Schema, and is basically a complete refactor of the decoders API from the current approach based on typeclasses (full implicit) into a combinators-based API which focuses on explicit with opt-in implicit derivation when useful (for example, to preserve a similar UX for simple use cases).
    As some may know, this is also my current Master's project.

    I am just starting with the real work, but I have an initial draft of how the API will look like here: https://gist.github.com/BalmungSan/075a7485163dce26ea5a7029ec6f9fcd
    In case anyone would like to give it a look and leave feedback, I would be very grateful.
    (PS: Sorry for the spanglish in the gist, is for my professor)

    Mason Lazalier Edmison
    @masonedmison
    @BalmungSan Sorry for ghosting regarding the scala 3 support. I have the next couple of days off and am hoping to at least get my first pass implementation working (with fixed and passing tests).
    Luis Miguel Mejía Suárez
    @BalmungSan
    @masonedmison hey no worries, I just hope it was just boring stuff like work raher than something serious :)
    BTW, since my work here neotypes/neotypes#584 will change a lot of things I don't recommend continue working on your PR
    Since all that work may get lost
    Unless we decide to merge yours first to make a Scala 3 release and then mine
    That was the original plan before I started working on that refactor
    But now, I think it would be best to tackle Scala 3 support after that
    However, I would appreciate a lot your input both in that as well as in my refactor
    Mason Lazalier Edmison
    @masonedmison

    BTW, since my work here neotypes/neotypes#584 will change a lot of things I don't recommend continue working on your PR

    I see. I figured I would need to rebase one way or the other since it's been a few months.

    But now, I think it would be best to tackle Scala 3 support after that

    That sounds good to me. Do you think the MR you linked to is far enough along for me to base my work off of the respective branch?

    Luis Miguel Mejía Suárez
    @BalmungSan
    Not yet, since I haven't pushed the chnages to generic.
    But, I have to finish this before the next Thursday in order to graduate in this semester so :sweat_smile:
    I plan to push the unit test suite next Saturday, which is what I want most folks to review and provide feedback, since that will show how the final API will look like when used.
    And then I hope to push the changes to generic next Tuesday
    I would really appreciate if you can comment after the first milestone and then, you may rebase or start again after the second milestone
    Does that sound good?
    Mason Lazalier Edmison
    @masonedmison
    yeah! sounds good to me. I think tomorrow I will still probably just rebase on top of the neotypes master branch and push what I have so far (since it's already done and won't take very long) to my scala 3 PR.
    Let me know if there is anything that you would like a review of :)
    Luis Miguel Mejía Suárez
    @BalmungSan
    Cool!
    :D