Created
April 30, 2025 14:49
-
-
Save p-pavel/1a916cbe947f98949e6f7138ad26cd40 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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