|
| 1 | +sealed trait Expression: |
| 2 | + def eval(): Int |
| 3 | +case class Number(n: Int) extends Expression: |
| 4 | + def eval(): Int = n |
| 5 | +case class Plus(e1: Expression, e2: Expression) extends Expression: |
| 6 | + def eval(): Int = e1.eval() + e2.eval() |
| 7 | + |
| 8 | +//// |
| 9 | + |
| 10 | +@main def sum(n1: Int, n2: Int) = |
| 11 | + val x1 = Number(n1) |
| 12 | + val x2 = Number(n2) |
| 13 | + val expr = Plus(x1, x2) |
| 14 | + println(s"Expression: $expr") |
| 15 | + val result = expr.eval() |
| 16 | + println(s"Calculated: $result") |
| 17 | + |
| 18 | +//// |
| 19 | + |
| 20 | +import scala.annotation.{ MainAnnotation, experimental } |
| 21 | +import scala.annotation.MainAnnotation.{ Info, Parameter } |
| 22 | +import scala.util.CommandLineParser.FromString |
| 23 | + |
| 24 | +@experimental class showAndEval extends MainAnnotation[FromString, Expression]: |
| 25 | + def command(info: Info, args: Seq[String]): Option[Seq[String]] = |
| 26 | + assert(info.parameters.forall(param => param.typeName == "Number"), "Only Number parameters allowed") |
| 27 | + println(s"executing ${info.name} with inputs: ${args.mkString(" ")}") |
| 28 | + Some(args) |
| 29 | + |
| 30 | + def argGetter[T](param: Parameter, arg: String, defaultArgument: Option[() => T])(using parser: FromString[T]): () => T = |
| 31 | + () => parser.fromString(arg) |
| 32 | + |
| 33 | + def varargGetter[T](param: Parameter, args: Seq[String])(using parser: FromString[T]): () => Seq[T] = |
| 34 | + () => args.map(arg => parser.fromString(arg)) |
| 35 | + |
| 36 | + def run(program: () => Expression): Unit = |
| 37 | + val expr = program() |
| 38 | + println(s"Expression: $expr") |
| 39 | + val result = expr.eval() |
| 40 | + println(s"Calculated: $result") |
| 41 | +end showAndEval |
| 42 | + |
| 43 | +given FromString[Number] = (x: String) => Number(x.toInt) |
| 44 | + |
| 45 | +//// |
| 46 | + |
| 47 | +@showAndEval def sum2(x1: Number, x2: Number): Expression = |
| 48 | + sumAll(x1, x2) |
| 49 | + |
| 50 | +@showAndEval def sumAll(xs: Number*): Expression = |
| 51 | + if xs.isEmpty then Number(0) |
| 52 | + else xs.tail.fold[Expression](xs.head)(Plus) |
| 53 | + |
| 54 | +//// |
| 55 | + |
| 56 | +@main def Test: Unit = |
| 57 | + def callMain(name: String, args: String*): Unit = |
| 58 | + val clazz = Class.forName(name) |
| 59 | + val method = clazz.getMethod("main", classOf[Array[String]]) |
| 60 | + method.invoke(null, args.toArray) |
| 61 | + callMain("sum", "1", "2") |
| 62 | + callMain("sum2", "2", "3") |
| 63 | + callMain("sumAll", "1", "2", "3") |
| 64 | +end Test |
0 commit comments