Permalink
Browse files

added functions

  • Loading branch information...
edofic committed Aug 27, 2012
1 parent 0859c66 commit 181d513801567cb51e7ebc5637d1a64913290b13
@@ -2,7 +2,7 @@ package com.edofic.scrat
import com.edofic.scrat.Util.Exceptions._
import Tokens._
import ScratRuntime.FunctionVarArg
import ScratRuntime._
/**
* User: andraz
@@ -37,7 +37,8 @@ class Evaluator(runtime: ScratRuntime) {
case ExpList(lst) => lst map apply
case FunctionCall(name, args) => scope.get(name.id) match {
case Some(f: FunctionVarArg) => f.apply(apply(args))
case None => throw new ScratSemanticError("function " + name + "not found")
case Some(f: StoredFunction) => f.apply(this, apply(args))
case _ => throw new ScratSemanticError("function " + name + "not found")
}
case Assignment(name, exp) => {
val e = apply(exp)
@@ -50,6 +51,12 @@ class Evaluator(runtime: ScratRuntime) {
}
case Equals(l, r) => (if (apply(l) == apply(r)) 1 else 0): Double
case NotEquals(l, r) => (if (apply(l) != apply(r)) 1 else 0): Double
case FunctionDef(name, args, body) => {
val fun = ScratRuntime.createFunFromAst(args, body, scope)
scope.put(name.id, fun)
fun
}
case t => throw new ScratInvalidTokenError(t + " not implemented in evaluator")
}
}
@@ -90,12 +90,21 @@ object Parser extends RegexParsers {
private def noEqExpr: Parser[Expression] = sum ||| assignment ||| ifThenElse
private def expr = noEqExpr ||| equality
private def expr: Parser[Expression] = noEqExpr ||| equality ||| functionDef
private def exprList = rep1sep(expr, "\n")
private def exprList: Parser[List[Expression]] = repsep(expr, "\\n+".r)
private def block: Parser[List[Expression]] = """\{\n*""".r ~> exprList <~ """\n*\}""".r
private def functionDef: Parser[FunctionDef] =
"func" ~ identifier ~ ("(" ~> repsep(identifier, ",") <~ ")") ~ block ^^ {
case "func" ~ id ~ args ~ body => FunctionDef(id, args, body)
}
def apply(s: String): List[Expression] = parseAll(exprList, s) match {
case Success(tree, _) => tree
case e: NoSuccess => throw new ScratSyntaxError("parsing error")
case Failure(msg, next) => throw new ScratSyntaxError("parsing failure: " + msg + " near: " + next.rest.source)
case Error(msg, next) => throw new ScratSyntaxError("parsing error: " + msg + " near: " + next.source)
case NoSuccess(msg, next) => throw new ScratSyntaxError("parser NoSuccess: " + msg + " near: " + next.source)
}
}
@@ -2,6 +2,7 @@ package com.edofic.scrat
import com.edofic.scrat.Util.Exceptions._
import Util.Implicits._
import com.edofic.scrat.Tokens.{Identifier, Expression}
/**
* User: andraz
@@ -10,6 +11,23 @@ import Util.Implicits._
*/
object ScratRuntime {
type FunctionVarArg = Any => Any
type StoredFunction = (Evaluator, Any) => Any
def createFunFromAst(arglist: List[Identifier], body: List[Expression], scope: SScope): StoredFunction =
(eval: Evaluator, args: Any) => args match {
case lst: List[Any] => {
if (lst.length != arglist.length) {
throw new ScratInvalidTypeError("expected " + arglist.length + " arguments, but got " + lst.length)
} else {
implicit val closure = new SScope(Some(scope))
val b = (arglist zip lst) foreach {
t => closure.put(t._1.id, t._2)
}
body --> eval.apply
}
}
case other => throw new ScratInvalidTypeError("expected list of arguments but got" + other)
}
}
class ScratRuntime {
@@ -37,4 +37,6 @@ object Tokens {
case class NotEquals(left: Expression, right: Expression) extends Expression
case class FunctionDef(name: Identifier, args: List[Identifier], body: List[Expression]) extends Expression
}
View
@@ -0,0 +1,3 @@
func fib(n) { if n==0 then 1 else if n==1 then 1 else fib(n-1) + fib(n-2) }
n = fib(20)
println("20th fibbonacci number is", n)

0 comments on commit 181d513

Please sign in to comment.