Skip to content

Instantly share code, notes, and snippets.

@nbenns
Last active November 8, 2023 19:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nbenns/1b007847940ef9c9ce6278da056c315f to your computer and use it in GitHub Desktop.
Save nbenns/1b007847940ef9c9ce6278da056c315f to your computer and use it in GitHub Desktop.
Scala 3 macro to return lambda
type Params[N <: Num] <: Tuple = N match {
case 0 => EmptyTuple
case _ => Double *: Params[N - 1]
}
type Num = Singleton & Int
opaque type Multivector[DIM <: Num] = Array[Double]
transparent inline def vector[N <: Num](using v: ValueOf[N], ev: (N > 0) =:= true): Params[N] => Multivector[N] =
${ vectorImpl[N]('{valueOf[N]}) }
def vectorImpl[N <: Num: Type](v: Expr[Int])(using q: Quotes): Expr[Params[N] => Multivector[N]] = {
import q.reflect.*
val dim = v.valueOrAbort
val mtpe = MethodType(List("basis"))(
_ => List(TypeRepr.of[Params[N]]),
_ => TypeRepr.of[Multivector[N]]
)
val constructor = Lambda(
Symbol.spliceOwner,
mtpe,
{ case (methSym, List(basis)) =>
given Quotes = methSym.asQuotes
'{
val edim = ${Expr(dim)}
val m: Params[N] = ${ basis.asExprOf[Params[N]] }
val arr = Array.fill(edim)(0d)
var i = 0
for (v <- m.productIterator) {
arr(i) = v.asInstanceOf[Double]
i += 1
}
_vector(edim)(arr*).asInstanceOf[Multivector[N]]
}.asTerm
}
)
constructor.asExprOf[Params[N] => Multivector[N]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment