--- 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")