progs/fun.scala
changeset 626 2d91b2107656
parent 625 6709fa87410b
child 628 8067d0a8ba04
--- 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")