diff -r 6709fa87410b -r 2d91b2107656 progs/fun.scala --- a/progs/fun.scala Sun Jul 28 16:15:03 2019 +0100 +++ b/progs/fun.scala Sun Jul 28 17:29:53 2019 +0100 @@ -3,13 +3,6 @@ import scala.language.implicitConversions import scala.language.reflectiveCalls -import scala.util._ -import scala.annotation.tailrec -import scala.sys.process._ - -def fromFile(name: String) : String = - io.Source.fromFile(name).mkString - abstract class Rexp case object ZERO extends Rexp @@ -19,7 +12,7 @@ case class SEQ(r1: Rexp, r2: Rexp) extends Rexp case class STAR(r: Rexp) extends Rexp case class RECD(x: String, r: Rexp) extends Rexp - + abstract class Val case object Empty extends Val case class Chr(c: Char) extends Val @@ -101,8 +94,6 @@ // The Injection Part of the lexer -// calculates a value for how a nullable regex -// matches the empty string def mkeps(r: Rexp) : Val = r match { case ONE => Empty case ALT(r1, r2) => @@ -112,7 +103,6 @@ case RECD(x, r) => Rec(x, mkeps(r)) } -// injects back a character into a value def inj(r: Rexp, c: Char, v: Val) : Val = (r, v) match { case (STAR(r), Sequ(v1, Stars(vs))) => Stars(inj(r, c, v1)::vs) case (SEQ(r1, r2), Sequ(v1, v2)) => Sequ(inj(r1, c, v1), v2) @@ -122,9 +112,9 @@ case (ALT(r1, r2), Right(v2)) => Right(inj(r2, c, v2)) case (CHAR(d), Empty) => Chr(c) case (RECD(x, r1), _) => Rec(x, inj(r1, c, v)) + case _ => { println ("Injection error") ; sys.exit(-1) } } - // some "rectification" functions for simplification def F_ID(v: Val): Val = v def F_RIGHT(f: Val => Val) = (v:Val) => Right(f(v)) @@ -145,8 +135,6 @@ } def F_ERROR(v: Val): Val = throw new Exception("error") -// simplification of regular expressions returns now also -// an rectification function; no simplification under STAR def simp(r: Rexp): (Rexp, Val => Val) = r match { case ALT(r1, r2) => { val (r1s, f1s) = simp(r1) @@ -210,7 +198,6 @@ val COMMENT = ("/*" ~ ALL2.% ~ "*/") | ("//" ~ ALL.% ~ "\n") - val WHILE_REGS = (("k" $ KEYWORD) | ("i" $ ID) | ("o" $ OP) | @@ -223,7 +210,7 @@ -// The tokens for the While language +// The tokens for the Fun language abstract class Token case object T_SEMI extends Token @@ -251,37 +238,6 @@ lexing_simp(WHILE_REGS, s).collect(token) -// Parser - Abstract syntax trees -abstract class Exp -abstract class BExp -abstract class Decl - -case class Def(name: String, args: List[String], body: Exp) extends Decl -case class Main(e: Exp) extends Decl - -case class Call(name: String, args: List[Exp]) extends Exp -case class If(a: BExp, e1: Exp, e2: Exp) extends Exp -case class Write(e: Exp) extends Exp -case class Var(s: String) extends Exp -case class Num(i: Int) extends Exp -case class Aop(o: String, a1: Exp, a2: Exp) extends Exp -case class Sequence(e1: Exp, e2: Exp) extends Exp - -case class Bop(o: String, a1: Exp, a2: Exp) extends BExp - -// calculating the maximal needed stack size -def max_stack_exp(e: Exp): Int = e match { - case Call(_, args) => args.map(max_stack_exp).sum - case If(a, e1, e2) => max_stack_bexp(a) + (List(max_stack_exp(e1), max_stack_exp(e2)).max) - case Write(e) => max_stack_exp(e) + 1 - case Var(_) => 1 - case Num(_) => 1 - case Aop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) - case Sequence(e1, e2) => List(max_stack_exp(e1), max_stack_exp(e2)).max -} -def max_stack_bexp(e: BExp): Int = e match { - case Bop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) -} // Parser combinators abstract class Parser[I, T](implicit ev: I => Seq[_]) { @@ -356,7 +312,27 @@ } -// Grammar Rules + +// Abstract syntax trees for Fun +abstract class Exp +abstract class BExp +abstract class Decl + +case class Def(name: String, args: List[String], body: Exp) extends Decl +case class Main(e: Exp) extends Decl + +case class Call(name: String, args: List[Exp]) extends Exp +case class If(a: BExp, e1: Exp, e2: Exp) extends Exp +case class Write(e: Exp) extends Exp +case class Var(s: String) extends Exp +case class Num(i: Int) extends Exp +case class Aop(o: String, a1: Exp, a2: Exp) extends Exp +case class Sequence(e1: Exp, e2: Exp) extends Exp +case class Bop(o: String, a1: Exp, a2: Exp) extends BExp + + + +// Grammar Rules for Fun // arithmetic expressions lazy val Exp: Parser[List[Token], Exp] = @@ -422,6 +398,21 @@ """ +// calculating the maximal needed stack size +def max_stack_exp(e: Exp): Int = e match { + case Call(_, args) => args.map(max_stack_exp).sum + case If(a, e1, e2) => max_stack_bexp(a) + (List(max_stack_exp(e1), max_stack_exp(e2)).max) + case Write(e) => max_stack_exp(e) + 1 + case Var(_) => 1 + case Num(_) => 1 + case Aop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) + case Sequence(e1, e2) => List(max_stack_exp(e1), max_stack_exp(e2)).max +} +def max_stack_bexp(e: BExp): Int = e match { + case Bop(_, a1, a2) => max_stack_exp(a1) + max_stack_exp(a2) +} + + // for generating new labels var counter = -1 @@ -514,23 +505,7 @@ } } - -def compile(class_name: String, input: String) : String = { - val tks = tokenise(input) - println(Prog.parse_single(tks).mkString("\n")) - val ast = Prog.parse_single(tks) - val instructions = ast.map(compile_decl).mkString - (library + instructions).replaceAllLiterally("XXX", class_name) -} - - -def compile_file(file_name: String) = { - val class_name = file_name.split('.')(0) - val output = compile(class_name, fromFile(file_name)) - val fw = new java.io.FileWriter(class_name + ".j") - fw.write(output) - fw.close() -} +// main compiler functions def time_needed[T](i: Int, code: => T) = { val start = System.nanoTime() @@ -539,15 +514,29 @@ (end - start)/(i * 1.0e9) } -def compile_run(file_name: String) : Unit = { - val class_name = file_name.split('.')(0) - compile_file(file_name) - val test = (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! +def compile(class_name: String, input: String) : String = { + val tks = tokenise(input) + val ast = Prog.parse_single(tks) + val instructions = ast.map(compile_decl).mkString + (library + instructions).replaceAllLiterally("XXX", class_name) +} + +def compile_file(class_name: String) = { + val input = io.Source.fromFile(s"${class_name}.fun").mkString + val output = compile(class_name, input) + scala.tools.nsc.io.File(s"${class_name}.j").writeAll(output) +} + +import scala.sys.process._ + +def compile_run(class_name: String) : Unit = { + compile_file(class_name) + (s"java -jar jvm/jasmin-2.4/jasmin.jar ${class_name}.j").!! println("Time: " + time_needed(2, (s"java ${class_name}/${class_name}").!)) } -// some examples -compile_file("fact.rec") -compile_run("defs.rec") -compile_run("fact.rec") +// some examples of .fun files +//compile_file("fact") +//compile_run("defs") +compile_run("fact")