Skip to content

Instantly share code, notes, and snippets.

@p-pavel
Created April 30, 2025 14:49
Show Gist options
  • Save p-pavel/1a916cbe947f98949e6f7138ad26cd40 to your computer and use it in GitHub Desktop.
Save p-pavel/1a916cbe947f98949e6f7138ad26cd40 to your computer and use it in GitHub Desktop.
trait Compiler:
type Env = Map[String, BigDecimal]
@throws[ParserError]
def compile(formula: String): Env => BigDecimal
import scala.quoted.*
type Env = Map[String, BigDecimal]
type E[A] = Expr[Env] ?=> Expr[A]
given exprLang: (q: Quotes) => Lang[E[BigDecimal], E[Boolean]]:
def env(using e: Expr[Env]) = e
extension (s: String)
override def func(args: E[BigDecimal]*): E[BigDecimal] =
require(args.length == 2, s"Function $s should have 2 arguments, given ${args.length}")
val Seq(a, b) = args
s match
case "max" => '{ $a.max($b) }
case "min" => '{ $a.min($b) }
end func
override def ident: E[BigDecimal] = '{ ${ env }(${ Expr(s) }) }
extension (b: BigDecimal) override def literal: E[BigDecimal] = Expr(b)
extension (a: E[Boolean])
override def ternary(forTrue: => E[BigDecimal])(
forFalse: => E[BigDecimal]
): E[BigDecimal] =
'{ if $a then $forTrue else $forFalse }
override def &&(b: E[Boolean]): E[Boolean] = '{ $a && $b }
override def ||(b: E[Boolean]): E[Boolean] = '{ $a || $b }
override def unary_! : E[Boolean] = '{ ! $a }
extension (a: E[BigDecimal])
override def *(b: E[BigDecimal]): E[BigDecimal] = '{ $a * $b }
override def /(b: E[BigDecimal]): E[BigDecimal] = '{ $a / $b }
override def +(b: E[BigDecimal]): E[BigDecimal] = '{ $a + $b }
override def -(b: E[BigDecimal]): E[BigDecimal] = '{ $a - $b }
override def unary_- = '{ - $a }
override def <(b: E[BigDecimal]): E[Boolean] = '{ $a < $b }
override def >(b: E[BigDecimal]): E[Boolean] = '{ $a > $b }
override def <=(b: E[BigDecimal]): E[Boolean] = '{$a <= $b}
override def >=(b: E[BigDecimal]): E[Boolean] = '{$a >= $b}
override def ===(b: E[BigDecimal]): E[Boolean] = '{$a == $b}
override def =!=(b: E[BigDecimal]): E[Boolean] = '{$a != $b}
end exprLang
object Compiler:
import scala.quoted.*
given stagingCompiler: staging.Compiler =
staging.Compiler.make(getClass().getClassLoader())
given default:Compiler:
override def compile(formula: String): Env => BigDecimal =
staging.run:
LangParser.parse(formula)(using exprLang) match
case Left(err) => ???
case Right(generator) =>
'{ (e: Map[String, BigDecimal]) => ${ generator(using 'e) } }
end Compiler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment