Last active
June 26, 2022 13:48
-
-
Save Ghurtchu/c5af4851ce4f1e10d203c58c14364080 to your computer and use it in GitHub Desktop.
ArithmeticExpressionsDSL.scala
This file contains 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
import scala.language.implicitConversions | |
object ArithmeticExpressionsDSL extends scala.App { | |
sealed trait Expr | |
object Expr { | |
final case class Literal private(n: Int) extends Expr | |
final case class Negate private(expr: Expr) extends Expr | |
final case class Add private (left: Expr, right: Expr) extends Expr | |
final case class Subtract private (left: Expr, right: Expr) extends Expr | |
final case class Multiply private (left: Expr, right: Expr) extends Expr | |
final case class Divide private (left: Expr, right: Expr) extends Expr | |
def apply(expr: Expr): Int = expr match { | |
case Literal(n) => n | |
case Negate(expr) => -apply(expr) | |
case Add(left, right) => apply(left) + apply(right) | |
case Subtract(left, right) => apply(left) - apply(right) | |
case Multiply(left, right) => apply(left) * apply(right) | |
case Divide(left, right) => right match { | |
case Literal(n) if n == 0 => throw new ArithmeticException("Division by zero") | |
case _ => apply(left) / apply(right) | |
} | |
} | |
def stringify(expr: Expr): String = expr match { | |
case Literal(n) => s"$n" | |
case Negate(expr) => s"-$expr" | |
case Add(left, right) => s"(${stringify(left)} + ${stringify(right)})" | |
case Subtract(left, right) => s"(${stringify(left)} - ${stringify(right)})" | |
case Multiply(left, right) => s"(${stringify(left)} * ${stringify(right)})" | |
case Divide(left, right) => s"(${stringify(left)} / ${stringify(right)})" | |
} | |
def neg(e: Expr): Expr = Negate(e) | |
def add(left: Expr, right: Expr): Expr = Add(left, right) | |
def sub(left: Expr, right: Expr): Expr = Subtract(left, right) | |
def mul(left: Expr, right: Expr): Expr = Multiply(left, right) | |
def div(left: Expr, right: Expr): Expr = Divide(left, right) | |
} | |
implicit def intToLiteral(n: Int): Expr = Expr.Literal(n) | |
implicit class ShowExpr(expr: Expr) { | |
def show(): Unit = { | |
val expression: String = Expr.stringify(expr) | |
val result : Int = Expr(expr) | |
println(s"$expression = $result") | |
} | |
def evaluate: Int = Expr(expr) | |
} | |
import Expr._ | |
val expr: Expr = mul(20, sub(10, add(1, div(5, 3)))) | |
assert(expr.evaluate == 160) | |
expr.show() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment