fork download
  1. import scala.util.parsing.combinator._
  2. import scala.collection.mutable.Map
  3.  
  4. case class Val(value: Double) extends Expr
  5. case class Var(name: String) extends Expr
  6. case class FunCall(name: String, args: List[Expr]) extends Expr
  7. case class Neg(expr: Expr) extends Expr
  8. case class Mul(left: Expr, right: Expr) extends Expr
  9. case class Div(left: Expr, right: Expr) extends Expr
  10. case class Add(left: Expr, right: Expr) extends Expr
  11. case class Sub(left: Expr, right: Expr) extends Expr
  12. case class VarDef(name: String, expr: Expr) extends Expr
  13. case class FunDef(name: String, args: List[String], body: Expr) extends Expr
  14. case class BoolVal(value: Boolean) extends Expr
  15. case class Not(expr: Expr) extends Expr
  16. case class And(left: Expr, right: Expr) extends Expr
  17. case class Or(left: Expr, right: Expr) extends Expr
  18. case class BoolEQ(left: Expr, right: Expr) extends Expr
  19. case class BoolNE(left: Expr, right: Expr) extends Expr
  20. case class BoolLT(left: Expr, right: Expr) extends Expr
  21. case class BoolGT(left: Expr, right: Expr) extends Expr
  22. case class BoolLE(left: Expr, right: Expr) extends Expr
  23. case class BoolGE(left: Expr, right: Expr) extends Expr
  24. case class If(condition: Expr, thenBody: Expr, elseBody: Expr) extends Expr
  25. case class EList(list: List[Expr]) extends Expr
  26. case class IndexOp(expr: Expr, index: Expr) extends Expr
  27.  
  28. class MyParser extends JavaTokenParsers {
  29.  
  30. def statement = defFun | defVar | expr
  31. def defFun = ("def" ~> ident <~ "(") ~ (repsep(ident, ",") <~ ")" <~ "=") ~ expr ^^ {
  32. case n ~ al ~ e => FunDef(n, al, e) }
  33. def defVar = (ident <~ "=") ~ expr ^^ { case n ~ e => VarDef(n, e) }
  34. def expr = expr100
  35. def expr100 = chainl1(expr110, "||" ^^^ {Or})
  36. def expr110 = chainl1(expr120, "&&" ^^^ {And})
  37. def expr120 = expr130 ~ ("==" | "!=" | "<=" | ">=" | "<" | ">") ~ expr130 ^^ {
  38. case l ~ "==" ~ r => BoolEQ(l, r) case l ~ "!=" ~ r => BoolNE(l, r)
  39. case l ~ "<=" ~ r => BoolLE(l, r) case l ~ ">=" ~ r => BoolGE(l, r)
  40. case l ~ "<" ~ r => BoolLT(l, r) case l ~ ">" ~ r => BoolGT(l, r)
  41. } | expr130
  42. def expr130: Parser[Expr] = "!" ~> expr130 ^^ {Not} | expr140
  43. def expr140 = chainl1(expr150, "+" ^^^ {Add} | "-" ^^^ {Sub})
  44. def expr150 = chainl1(expr160, "*" ^^^ {Mul} | "/" ^^^ {Div})
  45. def expr160: Parser[Expr] = "-" ~> expr160 ^^ {Neg} | expr170
  46. def expr170 = primary ~ rep("[" ~> expr <~ "]") ^^ { case e ~ is => (e /: is)(IndexOp) } | primary
  47. def primary = decimalNumber ^^ { case s => Val(s.toDouble) } |
  48. "#T" ^^^ {BoolVal(true)} | "#F" ^^^ {BoolVal(false)} | ifExpr |
  49. (ident <~ "(") ~ (repsep(expr, ",") <~ ")") ^^ { case n ~ al => FunCall(n, al) } |
  50. ident ^^ {Var} | "{" ~> repsep(expr, ",") <~ "}" ^^ {EList} | "(" ~> expr <~ ")"
  51. def ifExpr = ("if" ~ "(") ~> expr ~ (")" ~> expr <~ "else") ~ expr ^^ { case i ~ t ~ e => If(i, t, e) }
  52. }
  53.  
  54. object Main extends MyParser {
  55.  
  56. def eval(expr: Expr, vars: Map[String, Expr], funs: Map[String, FunDef]): Expr = {
  57.  
  58. def evalMathBinOp(op: ((Double, Double) => Double), e1: Expr, e2: Expr, cons: ((Expr, Expr) => Expr)) = {
  59. val ev1 = eval(e1, vars, funs) ; val ev2 = eval(e2, vars, funs)
  60. (ev1, ev2) match { case (Val(v1), Val(v2)) => Val(op(v1, v2)) case (e1, e2) => cons(e1, e2) }
  61. }
  62.  
  63. def evalAndOr(op: ((Boolean, Boolean) => Boolean), e1: Expr, e2: Expr, cons: ((Expr, Expr) => Expr)) = {
  64. val ev1 = eval(e1, vars, funs) ; val ev2 = eval(e2, vars, funs)
  65. (ev1, ev2) match { case (BoolVal(v1), BoolVal(v2)) => BoolVal(op(v1, v2)) case (e1, e2) => cons(e1, e2) }
  66. }
  67.  
  68. def evalEqUneq(op: ((AnyVal, AnyVal) => Boolean), e1: Expr, e2: Expr, cons: ((Expr, Expr) => Expr)) = {
  69. val ev1 = eval(e1, vars, funs) ; val ev2 = eval(e2, vars, funs)
  70. (ev1, ev2) match {
  71. case (Val(v1), Val(v2)) => BoolVal(op(v1, v2))
  72. case (BoolVal(v1), BoolVal(v2)) => BoolVal(op(v1, v2))
  73. case (e1, e2) => cons(e1, e2) }
  74. }
  75.  
  76. def evalRelBinOp(op: ((Double, Double) => Boolean), e1: Expr, e2: Expr, cons: ((Expr, Expr) => Expr)) = {
  77. val ev1 = eval(e1, vars, funs) ; val ev2 = eval(e2, vars, funs)
  78. (ev1, ev2) match { case (Val(v1), Val(v2)) => BoolVal(op(v1, v2)) case (e1, e2) => cons(e1, e2) }
  79. }
  80.  
  81. def setupFunCall(fun: FunDef, args: List[Expr]): Expr = {
  82.  
  83. val repMap = (fun.args zip args).toMap
  84.  
  85. def replace(expr: Expr): Expr = expr match {
  86. case v @ Val(d) => v
  87. case v @ BoolVal(b) => v
  88. case v @ Var(n) => if (repMap contains n) repMap(n) else v
  89. case FunCall(n, al) => { FunCall(if (repMap contains n) repMap(n) match {
  90. case Var(s) => s case _ => "Wtf?! This is not a function -.-" } else n, al map replace) }
  91. case Neg(e) => Neg(replace(e))
  92. case Mul(e1, e2) => Mul(replace(e1), replace(e2))
  93. case Div(e1, e2) => Div(replace(e1), replace(e2))
  94. case Add(e1, e2) => Add(replace(e1), replace(e2))
  95. case Sub(e1, e2) => Sub(replace(e1), replace(e2))
  96. case Not(e) => Not(replace(e))
  97. case And(e1, e2) => And(replace(e1), replace(e2))
  98. case Or(e1, e2) => Or(replace(e1), replace(e2))
  99. case BoolEQ(e1, e2) => BoolEQ(replace(e1), replace(e2))
  100. case BoolNE(e1, e2) => BoolNE(replace(e1), replace(e2))
  101. case BoolLE(e1, e2) => BoolLE(replace(e1), replace(e2))
  102. case BoolGE(e1, e2) => BoolGE(replace(e1), replace(e2))
  103. case BoolLT(e1, e2) => BoolLT(replace(e1), replace(e2))
  104. case BoolGT(e1, e2) => BoolGT(replace(e1), replace(e2))
  105. case If(c, t, e) => If(replace(c), replace(t), replace(e))
  106. case EList(el) => EList(el map replace _)
  107. case IndexOp(e, i) => IndexOp(replace(e), replace(i))
  108. }
  109.  
  110. replace(fun.body)
  111. }
  112.  
  113. expr match {
  114. case m @ Val(_) => m
  115. case m @ BoolVal(_) => m
  116. case m @ Var(s) => if (vars contains s) vars(s) match {
  117. case v @ Var(n) if (n == s) => v case e => eval(e, vars, funs) } else m
  118. case m @ FunCall(s, al) => {
  119. if (!(funs contains s)) m
  120. else if (funs(s).args.size != al.size) m
  121. else eval(setupFunCall(funs(s), al), vars, funs)
  122. }
  123. case m @ Neg(e) => eval(e, vars, funs) match { case Val(d) => Val(-d) case _ => m }
  124. case Mul(e1, e2) => evalMathBinOp((_*_), e1, e2, Mul)
  125. case Div(e1, e2) => evalMathBinOp((_/_), e1, e2, Div)
  126. case Add(e1, e2) => evalMathBinOp((_+_), e1, e2, Add)
  127. case Sub(e1, e2) => evalMathBinOp((_-_), e1, e2, Sub)
  128. case VarDef(s, e) => { val ev = eval(e, vars, funs) ; vars += (s -> ev) ; ev }
  129. case m @ FunDef(s, al, e) => { funs += (s -> m) ; m }
  130. case m @ Not(e) => { eval(e, vars, funs) match { case BoolVal(b) => BoolVal(!b) case _ => m } }
  131. case And(e1, e2) => evalAndOr( (_&&_), e1, e2, And)
  132. case Or(e1, e2) => evalAndOr( (_||_), e1, e2, Or)
  133. case BoolEQ(e1, e2) => evalEqUneq( (_==_), e1, e2, BoolEQ)
  134. case BoolNE(e1, e2) => evalEqUneq( (_!=_), e1, e2, BoolNE)
  135. case BoolLE(e1, e2) => evalRelBinOp((_<=_), e1, e2, BoolLE)
  136. case BoolGE(e1, e2) => evalRelBinOp((_>=_), e1, e2, BoolGE)
  137. case BoolLT(e1, e2) => evalRelBinOp( (_<_), e1, e2, BoolLT)
  138. case BoolGT(e1, e2) => evalRelBinOp( (_>_), e1, e2, BoolGT)
  139. case m @ If(c, t, e) => {
  140. eval(c, vars, funs) match {
  141. case BoolVal(true) => eval(t, vars, funs)
  142. case BoolVal(false) => eval(e, vars, funs)
  143. case _ => m }
  144. }
  145. case m @ IndexOp(e: Expr, i: Expr) => eval(e, vars, funs) match {
  146. case EList(el) => eval(i, vars, funs) match {
  147. case Val(v) if (v.toInt > 0 && v.toInt <= el.size) => el(v.toInt - 1)
  148. case i => IndexOp(EList(el), i) }
  149. case _ => m
  150. }
  151. case EList(el) => EList(for (e <- el) yield eval(e, vars, funs))
  152. }
  153. }
  154.  
  155. def main(args: Array[String]) {
  156.  
  157. val vars: Map[String, Expr] = Map()
  158. val funs: Map[String, FunDef] = Map()
  159. var input = ""
  160.  
  161. do { input = readLine() ; if (input != null && input != "") {
  162.  
  163. val output = parseAll(statement, input) match {
  164. case Failure(msg, _) => "failure: " + msg
  165. case Error(msg, _) => "error: " + msg
  166. case Success(parsed, _) => {
  167. " input : " + input + "\nparsed : " + parsed +
  168. "\neval'd : " + eval(parsed, vars, funs) }
  169. }
  170.  
  171. println(output + "\n") }
  172. } while (input != null && input != "")
  173. }
  174. }
Success #stdin #stdout 0.81s 383424KB
stdin
1 + 2 + 3 + 4
1 * 2 * 3 * 4
1 + x
x = 5
1 - x
x < 5
!(x != 5)
x < -1 || x >= -1
#F + #T
1 && 2
def add(x, y) = x + y
add(1, 2)
add(3 * 3, 4 * 4)
-add(1, add(2, 3)) == -6
def mul(x, y) = x * y
mul(4 / 2, 6 - 3)
list = {1, 2 + 3, #T || #F, { nested }, add(mul(2, a), mul(b, 5))}
a = -5
list
b = 2
list
ilist = {1, 2, 3, 4, 5}
list[ilist[list[5] + add(1, mul(2, 2))]]
mat = {{1, 2}, {3, 4}}
def trans2(m) = {{m[1][1], m[2][1]}, {m[1][2], m[2][2]}}
trans2(mat)
trans2(trans2(mat))
def max(x, y) = if (x > y) x else y
max(2, 1)
max(3, 4)
def max3(x, y, z) = max(x, max(y, z))
max3(1, 2, 3)
max3(3, 2, 1)
def factorial(n) = if (n == 0) 1 else n * factorial(n - 1)
factorial(4)
factorial(5)
def f(x) = x * x - 5 * x + 6
f(1)
f(2)
f(3)
def root(p, x) = p(x) == 0
root(f, 1)
root(f, 2)
root(f, 3)
def fold(f, c, n) = if (n == 0) c else f(n, fold(f, c, n - 1))
fold(mul, 1, 4)
fold(mul, 1, 5) == factorial(5)
fold(add, 0, 10)
def even(n) = if (n == 0) #T else if (n == 1) #F else even(n - 2)
def odd(n) = !even(n)
def foldif(p, f, c, n) = if (n == 0) c else if (p(n) == #T) f(n, foldif(p, f, c, n - 1)) else foldif(p, f, c, n - 1)
foldif(even, add, 0, 10)
foldif(odd, add, 0, 10)
stdout
 input : 1 + 2 + 3 + 4
parsed : Add(Add(Add(Val(1.0),Val(2.0)),Val(3.0)),Val(4.0))
eval'd : Val(10.0)

 input : 1 * 2 * 3 * 4
parsed : Mul(Mul(Mul(Val(1.0),Val(2.0)),Val(3.0)),Val(4.0))
eval'd : Val(24.0)

 input : 1 + x
parsed : Add(Val(1.0),Var(x))
eval'd : Add(Val(1.0),Var(x))

 input : x = 5
parsed : VarDef(x,Val(5.0))
eval'd : Val(5.0)

 input : 1 - x
parsed : Sub(Val(1.0),Var(x))
eval'd : Val(-4.0)

 input : x < 5
parsed : BoolLT(Var(x),Val(5.0))
eval'd : BoolVal(false)

 input : !(x != 5)
parsed : Not(BoolNE(Var(x),Val(5.0)))
eval'd : BoolVal(true)

 input : x < -1 || x >= -1
parsed : Or(BoolLT(Var(x),Neg(Val(1.0))),BoolGE(Var(x),Neg(Val(1.0))))
eval'd : BoolVal(true)

 input : #F + #T
parsed : Add(BoolVal(false),BoolVal(true))
eval'd : Add(BoolVal(false),BoolVal(true))

 input : 1 && 2
parsed : And(Val(1.0),Val(2.0))
eval'd : And(Val(1.0),Val(2.0))

 input : def add(x, y) = x + y
parsed : FunDef(add,List(x, y),Add(Var(x),Var(y)))
eval'd : FunDef(add,List(x, y),Add(Var(x),Var(y)))

 input : add(1, 2)
parsed : FunCall(add,List(Val(1.0), Val(2.0)))
eval'd : Val(3.0)

 input : add(3 * 3, 4 * 4)
parsed : FunCall(add,List(Mul(Val(3.0),Val(3.0)), Mul(Val(4.0),Val(4.0))))
eval'd : Val(25.0)

 input : -add(1, add(2, 3)) == -6
parsed : BoolEQ(Neg(FunCall(add,List(Val(1.0), FunCall(add,List(Val(2.0), Val(3.0)))))),Neg(Val(6.0)))
eval'd : BoolVal(true)

 input : def mul(x, y) = x * y
parsed : FunDef(mul,List(x, y),Mul(Var(x),Var(y)))
eval'd : FunDef(mul,List(x, y),Mul(Var(x),Var(y)))

 input : mul(4 / 2, 6 - 3)
parsed : FunCall(mul,List(Div(Val(4.0),Val(2.0)), Sub(Val(6.0),Val(3.0))))
eval'd : Val(6.0)

 input : list = {1, 2 + 3, #T || #F, { nested }, add(mul(2, a), mul(b, 5))}
parsed : VarDef(list,EList(List(Val(1.0), Add(Val(2.0),Val(3.0)), Or(BoolVal(true),BoolVal(false)), EList(List(Var(nested))), FunCall(add,List(FunCall(mul,List(Val(2.0), Var(a))), FunCall(mul,List(Var(b), Val(5.0))))))))
eval'd : EList(List(Val(1.0), Val(5.0), BoolVal(true), EList(List(Var(nested))), Add(Mul(Val(2.0),Var(a)),Mul(Var(b),Val(5.0)))))

 input : a = -5
parsed : VarDef(a,Neg(Val(5.0)))
eval'd : Val(-5.0)

 input : list
parsed : Var(list)
eval'd : EList(List(Val(1.0), Val(5.0), BoolVal(true), EList(List(Var(nested))), Add(Val(-10.0),Mul(Var(b),Val(5.0)))))

 input : b = 2
parsed : VarDef(b,Val(2.0))
eval'd : Val(2.0)

 input : list
parsed : Var(list)
eval'd : EList(List(Val(1.0), Val(5.0), BoolVal(true), EList(List(Var(nested))), Val(0.0)))

 input : ilist = {1, 2, 3, 4, 5}
parsed : VarDef(ilist,EList(List(Val(1.0), Val(2.0), Val(3.0), Val(4.0), Val(5.0))))
eval'd : EList(List(Val(1.0), Val(2.0), Val(3.0), Val(4.0), Val(5.0)))

 input : list[ilist[list[5] + add(1, mul(2, 2))]]
parsed : IndexOp(Var(list),IndexOp(Var(ilist),Add(IndexOp(Var(list),Val(5.0)),FunCall(add,List(Val(1.0), FunCall(mul,List(Val(2.0), Val(2.0))))))))
eval'd : Val(0.0)

 input : mat = {{1, 2}, {3, 4}}
parsed : VarDef(mat,EList(List(EList(List(Val(1.0), Val(2.0))), EList(List(Val(3.0), Val(4.0))))))
eval'd : EList(List(EList(List(Val(1.0), Val(2.0))), EList(List(Val(3.0), Val(4.0)))))

 input : def trans2(m) = {{m[1][1], m[2][1]}, {m[1][2], m[2][2]}}
parsed : FunDef(trans2,List(m),EList(List(EList(List(IndexOp(IndexOp(Var(m),Val(1.0)),Val(1.0)), IndexOp(IndexOp(Var(m),Val(2.0)),Val(1.0)))), EList(List(IndexOp(IndexOp(Var(m),Val(1.0)),Val(2.0)), IndexOp(IndexOp(Var(m),Val(2.0)),Val(2.0)))))))
eval'd : FunDef(trans2,List(m),EList(List(EList(List(IndexOp(IndexOp(Var(m),Val(1.0)),Val(1.0)), IndexOp(IndexOp(Var(m),Val(2.0)),Val(1.0)))), EList(List(IndexOp(IndexOp(Var(m),Val(1.0)),Val(2.0)), IndexOp(IndexOp(Var(m),Val(2.0)),Val(2.0)))))))

 input : trans2(mat)
parsed : FunCall(trans2,List(Var(mat)))
eval'd : EList(List(EList(List(Val(1.0), Val(3.0))), EList(List(Val(2.0), Val(4.0)))))

 input : trans2(trans2(mat))
parsed : FunCall(trans2,List(FunCall(trans2,List(Var(mat)))))
eval'd : EList(List(EList(List(Val(1.0), Val(2.0))), EList(List(Val(3.0), Val(4.0)))))

 input : def max(x, y) = if (x > y) x else y
parsed : FunDef(max,List(x, y),If(BoolGT(Var(x),Var(y)),Var(x),Var(y)))
eval'd : FunDef(max,List(x, y),If(BoolGT(Var(x),Var(y)),Var(x),Var(y)))

 input : max(2, 1)
parsed : FunCall(max,List(Val(2.0), Val(1.0)))
eval'd : Val(2.0)

 input : max(3, 4)
parsed : FunCall(max,List(Val(3.0), Val(4.0)))
eval'd : Val(4.0)

 input : def max3(x, y, z) = max(x, max(y, z))
parsed : FunDef(max3,List(x, y, z),FunCall(max,List(Var(x), FunCall(max,List(Var(y), Var(z))))))
eval'd : FunDef(max3,List(x, y, z),FunCall(max,List(Var(x), FunCall(max,List(Var(y), Var(z))))))

 input : max3(1, 2, 3)
parsed : FunCall(max3,List(Val(1.0), Val(2.0), Val(3.0)))
eval'd : Val(3.0)

 input : max3(3, 2, 1)
parsed : FunCall(max3,List(Val(3.0), Val(2.0), Val(1.0)))
eval'd : Val(3.0)

 input : def factorial(n) = if (n == 0) 1 else n * factorial(n - 1)
parsed : FunDef(factorial,List(n),If(BoolEQ(Var(n),Val(0.0)),Val(1.0),Mul(Var(n),FunCall(factorial,List(Sub(Var(n),Val(1.0)))))))
eval'd : FunDef(factorial,List(n),If(BoolEQ(Var(n),Val(0.0)),Val(1.0),Mul(Var(n),FunCall(factorial,List(Sub(Var(n),Val(1.0)))))))

 input : factorial(4)
parsed : FunCall(factorial,List(Val(4.0)))
eval'd : Val(24.0)

 input : factorial(5)
parsed : FunCall(factorial,List(Val(5.0)))
eval'd : Val(120.0)

 input : def f(x) = x * x - 5 * x + 6
parsed : FunDef(f,List(x),Add(Sub(Mul(Var(x),Var(x)),Mul(Val(5.0),Var(x))),Val(6.0)))
eval'd : FunDef(f,List(x),Add(Sub(Mul(Var(x),Var(x)),Mul(Val(5.0),Var(x))),Val(6.0)))

 input : f(1)
parsed : FunCall(f,List(Val(1.0)))
eval'd : Val(2.0)

 input : f(2)
parsed : FunCall(f,List(Val(2.0)))
eval'd : Val(0.0)

 input : f(3)
parsed : FunCall(f,List(Val(3.0)))
eval'd : Val(0.0)

 input : def root(p, x) = p(x) == 0
parsed : FunDef(root,List(p, x),BoolEQ(FunCall(p,List(Var(x))),Val(0.0)))
eval'd : FunDef(root,List(p, x),BoolEQ(FunCall(p,List(Var(x))),Val(0.0)))

 input : root(f, 1)
parsed : FunCall(root,List(Var(f), Val(1.0)))
eval'd : BoolVal(false)

 input : root(f, 2)
parsed : FunCall(root,List(Var(f), Val(2.0)))
eval'd : BoolVal(true)

 input : root(f, 3)
parsed : FunCall(root,List(Var(f), Val(3.0)))
eval'd : BoolVal(true)

 input : def fold(f, c, n) = if (n == 0) c else f(n, fold(f, c, n - 1))
parsed : FunDef(fold,List(f, c, n),If(BoolEQ(Var(n),Val(0.0)),Var(c),FunCall(f,List(Var(n), FunCall(fold,List(Var(f), Var(c), Sub(Var(n),Val(1.0))))))))
eval'd : FunDef(fold,List(f, c, n),If(BoolEQ(Var(n),Val(0.0)),Var(c),FunCall(f,List(Var(n), FunCall(fold,List(Var(f), Var(c), Sub(Var(n),Val(1.0))))))))

 input : fold(mul, 1, 4)
parsed : FunCall(fold,List(Var(mul), Val(1.0), Val(4.0)))
eval'd : Val(24.0)

 input : fold(mul, 1, 5) == factorial(5)
parsed : BoolEQ(FunCall(fold,List(Var(mul), Val(1.0), Val(5.0))),FunCall(factorial,List(Val(5.0))))
eval'd : BoolVal(true)

 input : fold(add, 0, 10)
parsed : FunCall(fold,List(Var(add), Val(0.0), Val(10.0)))
eval'd : Val(55.0)

 input : def even(n) = if (n == 0) #T else if (n == 1) #F else even(n - 2)
parsed : FunDef(even,List(n),If(BoolEQ(Var(n),Val(0.0)),BoolVal(true),If(BoolEQ(Var(n),Val(1.0)),BoolVal(false),FunCall(even,List(Sub(Var(n),Val(2.0)))))))
eval'd : FunDef(even,List(n),If(BoolEQ(Var(n),Val(0.0)),BoolVal(true),If(BoolEQ(Var(n),Val(1.0)),BoolVal(false),FunCall(even,List(Sub(Var(n),Val(2.0)))))))

 input : def odd(n) = !even(n)
parsed : FunDef(odd,List(n),Not(FunCall(even,List(Var(n)))))
eval'd : FunDef(odd,List(n),Not(FunCall(even,List(Var(n)))))

 input : def foldif(p, f, c, n) = if (n == 0) c else if (p(n) == #T) f(n, foldif(p, f, c, n - 1)) else foldif(p, f, c, n - 1)
parsed : FunDef(foldif,List(p, f, c, n),If(BoolEQ(Var(n),Val(0.0)),Var(c),If(BoolEQ(FunCall(p,List(Var(n))),BoolVal(true)),FunCall(f,List(Var(n), FunCall(foldif,List(Var(p), Var(f), Var(c), Sub(Var(n),Val(1.0)))))),FunCall(foldif,List(Var(p), Var(f), Var(c), Sub(Var(n),Val(1.0)))))))
eval'd : FunDef(foldif,List(p, f, c, n),If(BoolEQ(Var(n),Val(0.0)),Var(c),If(BoolEQ(FunCall(p,List(Var(n))),BoolVal(true)),FunCall(f,List(Var(n), FunCall(foldif,List(Var(p), Var(f), Var(c), Sub(Var(n),Val(1.0)))))),FunCall(foldif,List(Var(p), Var(f), Var(c), Sub(Var(n),Val(1.0)))))))

 input : foldif(even, add, 0, 10)
parsed : FunCall(foldif,List(Var(even), Var(add), Val(0.0), Val(10.0)))
eval'd : Val(30.0)

 input : foldif(odd, add, 0, 10)
parsed : FunCall(foldif,List(Var(odd), Var(add), Val(0.0), Val(10.0)))
eval'd : Val(25.0)