# HG changeset patch # User Christian Urban # Date 1353892315 0 # Node ID 191daa3ee29e1106f9c20ec660e129056ed36fee # Parent fd894e017e125d5453d61f199f2a979b9ff53503 tuned diff -r fd894e017e12 -r 191daa3ee29e compile.scala --- a/compile.scala Sat Nov 24 15:10:43 2012 +0000 +++ b/compile.scala Mon Nov 26 01:11:55 2012 +0000 @@ -10,7 +10,7 @@ val NUM = PLUS(DIGIT) val KEYWORD = ALTS("skip", "while", "do", "if", "then", "else", "true", "false", "write") val SEMI: Rexp = ";" -val OP: Rexp = ALTS(":=", "=", "-", "+", "*", "!", "<", ">") +val OP: Rexp = ALTS(":=", "=", "-", "+", "*", "!=", "<", ">") val WHITESPACE = PLUS(RANGE(" \n")) val RPAREN: Rexp = ")" val LPAREN: Rexp = "(" @@ -65,7 +65,7 @@ case object True extends BExp case object False extends BExp -case class Bop(o: String, a1: AExp, a2: AExp) extends BExp +case class Relop(o: String, a1: AExp, a2: AExp) extends BExp // atomic parsers case class TokParser(tok: Token) extends Parser[List[Token], Token] { @@ -107,10 +107,10 @@ (T_KWD("true") ==> ((_) => True: BExp)) || (T_KWD("false") ==> ((_) => False: BExp)) || (T_LPAREN ~> BExp <~ T_RPAREN) || - (AExp ~ T_OP("=") ~ AExp) ==> { case ((x, y), z) => Bop("=", x, z): BExp } || - (AExp ~ T_OP("!=") ~ AExp) ==> { case ((x, y), z) => Bop("!=", x, z): BExp } || - (AExp ~ T_OP("<") ~ AExp) ==> { case ((x, y), z) => Bop("<", x, z): BExp } || - (AExp ~ T_OP(">") ~ AExp) ==> { case ((x, y), z) => Bop("<", z, x): BExp } + (AExp ~ T_OP("=") ~ AExp) ==> { case ((x, y), z) => Relop("=", x, z): BExp } || + (AExp ~ T_OP("!=") ~ AExp) ==> { case ((x, y), z) => Relop("!=", x, z): BExp } || + (AExp ~ T_OP("<") ~ AExp) ==> { case ((x, y), z) => Relop("<", x, z): BExp } || + (AExp ~ T_OP(">") ~ AExp) ==> { case ((x, y), z) => Relop("<", z, x): BExp } lazy val Stmt: Parser[List[Token], Stmt] = (T_KWD("skip") ==> ((_) => Skip: Stmt)) || @@ -128,9 +128,9 @@ (T_BEGIN ~> Stmts <~ T_END) || (Stmt ==> ((s) => List(s))) -// interpreter +// compiler val beginning = """ -.class public examples/HelloWorld +.class public XXX.XXX .super java/lang/Object .method public ()V @@ -172,8 +172,9 @@ } type Env = Map[String, String] +type Instrs = List[String] -def compile_aexp(a: AExp, env : Env) : List[String] = a match { +def compile_aexp(a: AExp, env : Env) : Instrs = a match { case Num(i) => List("ldc " + i.toString + "\n") case Var(s) => List("iload " + env(s) + "\n") case Aop("+", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("iadd\n") @@ -181,19 +182,24 @@ case Aop("*", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("imul\n") } -def compile_bexp(b: BExp, env : Env, jmp: String) : List[String] = b match { - case Bop("=", a1, a2) => +def compile_bexp(b: BExp, env : Env, jmp: String) : Instrs = b match { + case True => Nil + case False => List("goto " + jmp + "\n") + case Relop("=", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpne " + jmp + "\n") - case Bop("<", a1, a2) => + case Relop("!=", a1, a2) => + compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpeq " + jmp + "\n") + case Relop("<", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpge " + jmp + "\n") } -def compile_stmt(s: Stmt, env: Env) : (List[String], Env) = s match { +def compile_stmt(s: Stmt, env: Env) : (Instrs, Env) = s match { case Skip => (Nil, env) case Assign(x, a) => { val index = if (env.isDefinedAt(x)) env(x) else env.keys.size.toString - (compile_aexp(a, env) ++ List("istore " + index + "\n"), env + (x -> index)) + (compile_aexp(a, env) ++ + List("istore " + index + "\n"), env + (x -> index)) } case If(b, bl1, bl2) => { val if_else = Fresh("If_else") @@ -218,10 +224,10 @@ List("\n" + loop_end + ":\n\n"), env1) } case Write(x) => - (List("iload " + env(x) + "\n" + "invokestatic examples/HelloWorld/write(I)V\n"), env) + (List("iload " + env(x) + "\n" + "invokestatic XXX/XXX/write(I)V\n"), env) } -def compile_bl(bl: Block, env: Env) : (List[String], Env) = bl match { +def compile_bl(bl: Block, env: Env) : (Instrs, Env) = bl match { case Nil => (Nil, env) case s::bl => { val (instrs1, env1) = compile_stmt(s, env) @@ -230,18 +236,88 @@ } } -def compile(name: String) : String = { - val tks = Tok.fromFile(name) +def compile(input: String) : String = { + val class_name = input.split('.')(0) + val tks = Tok.fromFile(input) val ast = Stmts.parse_single(tks) val instructions = compile_bl(ast, Map.empty)._1 - beginning ++ instructions.mkString ++ ending + (beginning ++ instructions.mkString ++ ending).replaceAllLiterally("XXX", class_name) } +def compile_to(input: String, output: String) = { + val fw = new java.io.FileWriter(output) + fw.write(compile(input)) + fw.close() +} + +// +val tks = Tok.fromString("x := x + 1") +val ast = Stmt.parse_single(tks) +println(compile_stmt(ast, Map("x" -> "n"))._1.mkString) + + + //examples -println(compile("loops.while")) -//println(compile("fib.while")) +//compile_to("loops.while", "loops.j") +//compile_to("fib.while", "fib.j") + + +// testing cases for time measurements + +def time_needed[T](i: Int, code: => T) = { + val start = System.nanoTime() + for (j <- 1 to i) code + val end = System.nanoTime() + (end - start)/(i * 1.0e9) +} + +// for testing +import scala.sys.process._ + +val test_prog = """ +start := XXX; +x := start; +y := start; +z := start; +while 0 < x do { + while 0 < y do { + while 0 < z do { + z := z - 1 + }; + z := start; + y := y - 1 + }; + y := start; + x := x - 1 +}; +write x; +write y; +write z +""" + + +def compile_test(n: Int) : Unit = { + val class_name = "LOOP" + val tks = Tok.fromString(test_prog.replaceAllLiterally("XXX", n.toString)) + val ast = Stmts.parse_single(tks) + val instructions = compile_bl(ast, Map.empty)._1 + val assembly = (beginning ++ instructions.mkString ++ ending).replaceAllLiterally("XXX", class_name) + val fw = new java.io.FileWriter(class_name + ".j") + fw.write(assembly) + fw.close() + val test = ("java -jar jvm/jasmin-2.4/jasmin.jar " + class_name + ".j").!! + println(n + " " + time_needed(2, ("java " + class_name + "/" + class_name).!!)) +} + +List(1, 5000, 10000, 50000, 100000, 250000, 500000, 750000, 1000000).map(compile_test(_)) + + + +// javabyte code assmbler +// +// java -jar jvm/jasmin-2.4/jasmin.jar loops.j @@ -249,5 +325,3 @@ - - diff -r fd894e017e12 -r 191daa3ee29e compile1.scala --- a/compile1.scala Sat Nov 24 15:10:43 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -// A parser and evaluator for teh while language -// -//:load matcher.scala -//:load parser3.scala - -// some regular expressions -val SYM = RANGE("ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz_") -val DIGIT = RANGE("0123456789") -val ID = SEQ(SYM, STAR(ALT(SYM, DIGIT))) -val NUM = PLUS(DIGIT) -val KEYWORD = ALTS("skip", "while", "do", "if", "then", "else", "true", "false", "write") -val SEMI: Rexp = ";" -val OP: Rexp = ALTS(":=", "=", "-", "+", "*", "!=", "<", ">") -val WHITESPACE = PLUS(RANGE(" \n")) -val RPAREN: Rexp = ")" -val LPAREN: Rexp = "(" -val BEGIN: Rexp = "{" -val END: Rexp = "}" -val COMMENT = SEQS("/*", NOT(SEQS(STAR(ALLC), "*/", STAR(ALLC))), "*/") - -// tokens for classifying the strings that have been recognised -abstract class Token -case object T_WHITESPACE extends Token -case object T_COMMENT extends Token -case object T_SEMI extends Token -case object T_LPAREN extends Token -case object T_RPAREN extends Token -case object T_BEGIN extends Token -case object T_END extends Token -case class T_ID(s: String) extends Token -case class T_OP(s: String) extends Token -case class T_NUM(s: String) extends Token -case class T_KWD(s: String) extends Token - -val lexing_rules: List[Rule[Token]] = - List((KEYWORD, (s) => T_KWD(s.mkString)), - (ID, (s) => T_ID(s.mkString)), - (OP, (s) => T_OP(s.mkString)), - (NUM, (s) => T_NUM(s.mkString)), - (SEMI, (s) => T_SEMI), - (LPAREN, (s) => T_LPAREN), - (RPAREN, (s) => T_RPAREN), - (BEGIN, (s) => T_BEGIN), - (END, (s) => T_END), - (WHITESPACE, (s) => T_WHITESPACE), - (COMMENT, (s) => T_COMMENT)) - -// the tokenizer -val Tok = Tokenizer(lexing_rules, List(T_WHITESPACE, T_COMMENT)) - -// the abstract syntax trees -abstract class Stmt -abstract class AExp -abstract class BExp -type Block = List[Stmt] -case object Skip extends Stmt -case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt -case class While(b: BExp, bl: Block) extends Stmt -case class Assign(s: String, a: AExp) extends Stmt -case class Write(s: String) extends Stmt - -case class Var(s: String) extends AExp -case class Num(i: Int) extends AExp -case class Aop(o: String, a1: AExp, a2: AExp) extends AExp - -case object True extends BExp -case object False extends BExp -case class Relop(o: String, a1: AExp, a2: AExp) extends BExp - -// atomic parsers -case class TokParser(tok: Token) extends Parser[List[Token], Token] { - def parse(ts: List[Token]) = ts match { - case t::ts if (t == tok) => Set((t, ts)) - case _ => Set () - } -} -implicit def token2tparser(t: Token) = TokParser(t) - -case object NumParser extends Parser[List[Token], Int] { - def parse(ts: List[Token]) = ts match { - case T_NUM(s)::ts => Set((s.toInt, ts)) - case _ => Set () - } -} - -case object IdParser extends Parser[List[Token], String] { - def parse(ts: List[Token]) = ts match { - case T_ID(s)::ts => Set((s, ts)) - case _ => Set () - } -} - - -// arithmetic expressions -lazy val AExp: Parser[List[Token], AExp] = - (T ~ T_OP("+") ~ AExp) ==> { case ((x, y), z) => Aop("+", x, z): AExp } || - (T ~ T_OP("-") ~ AExp) ==> { case ((x, y), z) => Aop("-", x, z): AExp } || T -lazy val T: Parser[List[Token], AExp] = - (F ~ T_OP("*") ~ T) ==> { case ((x, y), z) => Aop("*", x, z): AExp } || F -lazy val F: Parser[List[Token], AExp] = - (T_LPAREN ~> AExp <~ T_RPAREN) || - IdParser ==> Var || - NumParser ==> Num - -// boolean expressions -lazy val BExp: Parser[List[Token], BExp] = - (T_KWD("true") ==> ((_) => True: BExp)) || - (T_KWD("false") ==> ((_) => False: BExp)) || - (T_LPAREN ~> BExp <~ T_RPAREN) || - (AExp ~ T_OP("=") ~ AExp) ==> { case ((x, y), z) => Relop("=", x, z): BExp } || - (AExp ~ T_OP("!=") ~ AExp) ==> { case ((x, y), z) => Relop("!=", x, z): BExp } || - (AExp ~ T_OP("<") ~ AExp) ==> { case ((x, y), z) => Relop("<", x, z): BExp } || - (AExp ~ T_OP(">") ~ AExp) ==> { case ((x, y), z) => Relop("<", z, x): BExp } - -lazy val Stmt: Parser[List[Token], Stmt] = - (T_KWD("skip") ==> ((_) => Skip: Stmt)) || - (IdParser ~ T_OP(":=") ~ AExp) ==> { case ((x, y), z) => Assign(x, z): Stmt } || - (T_KWD("if") ~ BExp ~ T_KWD("then") ~ Block ~ T_KWD("else") ~ Block) ==> - { case (((((x,y),z),u),v),w) => If(y, u, w): Stmt } || - (T_KWD("while") ~ BExp ~ T_KWD("do") ~ Block) ==> { case (((x, y), z), w) => While(y, w) } || - (T_KWD("write") ~ IdParser) ==> { case (x, y) => Write(y) } - -lazy val Stmts: Parser[List[Token], Block] = - (Stmt ~ T_SEMI ~ Stmts) ==> { case ((x, y), z) => x :: z : Block } || - (Stmt ==> ((s) => List(s) : Block)) - -lazy val Block: Parser[List[Token], Block] = - (T_BEGIN ~> Stmts <~ T_END) || - (Stmt ==> ((s) => List(s))) - -// compiler -val beginning = """ -.class public examples/HelloWorld -.super java/lang/Object - -.method public ()V - aload_0 - invokenonvirtual java/lang/Object/()V - return -.end method - -.method public static write(I)V - .limit locals 5 - .limit stack 5 - iload 0 - getstatic java/lang/System/out Ljava/io/PrintStream; - swap - invokevirtual java/io/PrintStream/println(I)V - return -.end method - - -.method public static main([Ljava/lang/String;)V - .limit locals 200 - .limit stack 200 - -""" - -val ending = """ - - return - -.end method -""" - -// for generating new labels -var counter = -1 - -def Fresh(x: String) = { - counter += 1 - x ++ "_" ++ counter.toString() -} - -type Env = Map[String, String] -type Instrs = List[String] - -def compile_aexp(a: AExp, env : Env) : Instrs = a match { - case Num(i) => List("ldc " + i.toString + "\n") - case Var(s) => List("iload " + env(s) + "\n") - case Aop("+", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("iadd\n") - case Aop("-", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("isub\n") - case Aop("*", a1, a2) => compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("imul\n") -} - -def compile_bexp(b: BExp, env : Env, jmp: String) : Instrs = b match { - case True => Nil - case False => List("goto " + jmp + "\n") - case Relop("=", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpne " + jmp + "\n") - case Relop("!=", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpeq " + jmp + "\n") - case Relop("<", a1, a2) => - compile_aexp(a1, env) ++ compile_aexp(a2, env) ++ List("if_icmpge " + jmp + "\n") -} - - -def compile_stmt(s: Stmt, env: Env) : (Instrs, Env) = s match { - case Skip => (Nil, env) - case Assign(x, a) => { - val index = if (env.isDefinedAt(x)) env(x) else env.keys.size.toString - (compile_aexp(a, env) ++ - List("istore " + index + "\n"), env + (x -> index)) - } - case If(b, bl1, bl2) => { - val if_else = Fresh("If_else") - val if_end = Fresh("If_end") - val (instrs1, env1) = compile_bl(bl1, env) - val (instrs2, env2) = compile_bl(bl2, env1) - (compile_bexp(b, env, if_else) ++ - instrs1 ++ - List("goto " + if_end + "\n") ++ - List("\n" + if_else + ":\n\n") ++ - instrs2 ++ - List("\n" + if_end + ":\n\n"), env2) - } - case While(b, bl) => { - val loop_begin = Fresh("Loop_begin") - val loop_end = Fresh("Loop_end") - val (instrs1, env1) = compile_bl(bl, env) - (List("\n" + loop_begin + ":\n\n") ++ - compile_bexp(b, env, loop_end) ++ - instrs1 ++ - List("goto " + loop_begin + "\n") ++ - List("\n" + loop_end + ":\n\n"), env1) - } - case Write(x) => - (List("iload " + env(x) + "\n" + "invokestatic examples/HelloWorld/write(I)V\n"), env) -} - -def compile_bl(bl: Block, env: Env) : (Instrs, Env) = bl match { - case Nil => (Nil, env) - case s::bl => { - val (instrs1, env1) = compile_stmt(s, env) - val (instrs2, env2) = compile_bl(bl, env1) - (instrs1 ++ instrs2, env2) - } -} - -def compile(input: String) : String = { - val tks = Tok.fromFile(input) - val ast = Stmts.parse_single(tks) - val instructions = compile_bl(ast, Map.empty)._1 - beginning ++ instructions.mkString ++ ending -} - - -def compile_to(input: String, output: String) = { - val fw = new java.io.FileWriter(output) - fw.write(compile(input)) - fw.close() -} - - -//examples - -compile_to("loops.while", "loops.j") -compile_to("fib.while", "fib.j") - - - - - - - - - diff -r fd894e017e12 -r 191daa3ee29e fib.while --- a/fib.while Sat Nov 24 15:10:43 2012 +0000 +++ b/fib.while Mon Nov 26 01:11:55 2012 +0000 @@ -1,17 +1,12 @@ -/* - - Fibonacci Program - - input: n - output: fib_res - -*/ +/* Fibonacci Program + input: n + output: fib_res */ n := 90; minus1 := 0; minus2 := 1; temp := 0; -while n > 0 do { +while n > 0 do { temp := minus2; minus2 := minus1 + minus2; minus1 := temp; diff -r fd894e017e12 -r 191daa3ee29e slides09.pdf Binary file slides09.pdf has changed diff -r fd894e017e12 -r 191daa3ee29e slides09.tex --- a/slides09.tex Sat Nov 24 15:10:43 2012 +0000 +++ b/slides09.tex Mon Nov 26 01:11:55 2012 +0000 @@ -105,17 +105,27 @@ % The data files, written on the first run. \begin{filecontents}{compiled.data} -1 0.0207 -5000 0.0217 -10000 0.0297 -50000 0.1034 -100000 0.3873 -500000 1.27949 -1000000 5. 35424 +%1 0.234146 +%5000 0.227539 +%10000 0.280748 +50000 1.087897 +100000 3.713165 +250000 21.6624545 +500000 85.872613 +750000 203.6408015 +1000000 345.736574 \end{filecontents} \begin{filecontents}{interpreted.data} - +%1 0.00503 +200 1.005863 +400 7.8296765 +500 15.43106 +600 27.2321885 +800 65.249271 +1000 135.4493445 +1200 232.134097 +1400 382.527227 \end{filecontents} @@ -146,6 +156,26 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \mode{ \begin{frame}[c] + +Imagine the following situation: You talk to somebody +and you find out that she/he has implemented a compiler.\smallskip + +What is your reaction? Check all that apply.\bigskip\pause + + \begin{itemize} + \item[$\Box$] You think she/he is God + \item[$\Box$] \"Uberhacker + \item[$\Box$] superhuman + \item[$\Box$] wizard + \item[$\Box$] supremo + \end{itemize} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[c] \frametitle{\begin{tabular}{c}While-Language\end{tabular}} @@ -177,7 +207,7 @@ \mbox{}\\[-18mm]\mbox{} {\lstset{language=While}\fontsize{10}{12}\selectfont -\texttt{\lstinputlisting{app9.while}}} +\texttt{\lstinputlisting{fib.while}}} \end{frame}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -187,11 +217,468 @@ \begin{frame}[c] \frametitle{\begin{tabular}{c}Interpreter\end{tabular}} +\begin{center} +\bl{\begin{tabular}{@{}lcl@{}} +$\text{eval}(n, E)$ & $\dn$ & $n$\\ +$\text{eval}(x, E)$ & $\dn$ & $E(x)$ \;\;\;\textcolor{black}{lookup \bl{$x$} in \bl{$E$}}\\ +$\text{eval}(a_1 + a_2, E)$ & $\dn$ & $\text{eval}(a_1, E) + \text{eval}(a_2, E)$\\ +$\text{eval}(a_1 - a_2, E)$ & $\dn$ & $\text{eval}(a_1, E) - \text{eval}(a_2, E)$\\ +$\text{eval}(a_1 * a_2, E)$ & $\dn$ & $\text{eval}(a_1, E) * \text{eval}(a_2, E)$\bigskip\\ +$\text{eval}(a_1 = a_2, E)$ & $\dn$ & $\text{eval}(a_1, E) = \text{eval}(a_2, E)$\\ +$\text{eval}(a_1\,!\!= a_2, E)$ & $\dn$ & $\neg(\text{eval}(a_1, E) = \text{eval}(a_2, E))$\\ +$\text{eval}(a_1 < a_2, E)$ & $\dn$ & $\text{eval}(a_1, E) < \text{eval}(a_2, E)$\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[c] +\frametitle{\begin{tabular}{c}Interpreter (2)\end{tabular}} + +\begin{center} +\bl{\begin{tabular}{@{}lcl@{}} +$\text{eval}(\text{skip}, E)$ & $\dn$ & $E$\\ +$\text{eval}(x:=a, E)$ & $\dn$ & \bl{$E(x \mapsto \text{eval}(a, E))$}\\ +\multicolumn{3}{@{}l@{}}{$\text{eval}(\text{if}\;b\;\text{then}\;cs_1\;\text{else}\;cs_2 , E) \dn$}\\ +\multicolumn{3}{@{}l@{}}{\hspace{2cm}$\text{if}\;\text{eval}(b,E)\;\text{then}\; +\text{eval}(cs_1,E)$}\\ +\multicolumn{3}{@{}l@{}}{\hspace{2cm}$\phantom{\text{if}\;\text{eval}(b,E)\;}\text{else}\;\text{eval}(cs_2,E)$}\\ +\multicolumn{3}{@{}l@{}}{$\text{eval}(\text{while}\;b\;\text{do}\;cs, E) \dn$}\\ +\multicolumn{3}{@{}l@{}}{\hspace{2cm}$\text{if}\;\text{eval}(b,E)$}\\ +\multicolumn{3}{@{}l@{}}{\hspace{2cm}$\text{then}\; +\text{eval}(\text{while}\;b\;\text{do}\;cs, \text{eval}(cs,E))$}\\ +\multicolumn{3}{@{}l@{}}{\hspace{2cm}$\text{else}\; E$}\\ +$\text{eval}(\text{print}\; x, E)$ & $\dn$ & $\{\;\text{println}(E(x))\; ;\;E\;\}$\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[c] +\frametitle{\begin{tabular}{c}Test Program\end{tabular}} + +\mbox{}\\[-18mm]\mbox{} + +{\lstset{language=While}\fontsize{10}{12}\selectfont +\texttt{\lstinputlisting{loops.while}}} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Interpreted Code\end{tabular}} + +\begin{center} +\begin{tikzpicture} +\begin{axis}[axis x line=bottom, axis y line=left, xlabel=n, ylabel=secs] +\addplot+[smooth] file {interpreted.data}; +\end{axis} +\end{tikzpicture} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[c] +\frametitle{\begin{tabular}{c}Java Virtual Machine\end{tabular}} + +\begin{itemize} +\item introduced in 1995 +\item is a stack-based VM (like Postscript, CLR of .Net) +\item contains a JIT compiler +\item many languages take advantage of the infrastructure (JRE) +\item languages compiled to the JVM: Scala, Clojure\ldots +\item garbage collected +\end{itemize} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +{\Large\bl{1 + 2}} + +\begin{center} +\bl{\begin{tabular}{l} +ldc 1\\ +ldc 2\\ +iadd\\ +\end{tabular}} +\end{center}\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +{\Large\bl{1 + 2 + 3}} + +\begin{center} +\bl{\begin{tabular}{l} +ldc 1\\ +ldc 2\\ +iadd\\ +ldc 3\\ +iadd\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +{\Large\bl{1 + (2 + 3)}} + +\begin{center} +\bl{\begin{tabular}{l} +ldc 1\\ +ldc 2\\ +ldc 3\\ +iadd\\ +iadd\\ +\end{tabular}} +\end{center}\bigskip\pause +\vfill + +\bl{dadd, fadd, ladd, \ldots} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +\begin{center} +\bl{\begin{tabular}{@{}lcl@{}} +$\text{compile}(n)$ & $\dn$ & $\text{ldc}\;n$\\ +$\text{compile}(a_1 + a_2)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1) \;@\;\text{compile}(a_2)\;@\; \text{iadd}$}\smallskip\\ +$\text{compile}(a_1 - a_2)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1) \;@\; \text{compile}(a_2)\;@\; \text{isub}$}\smallskip\\ +$\text{compile}(a_1 * a_2)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1) \;@\; \text{compile}(a_2)\;@\; \text{imul}$}\smallskip\\ +\end{tabular}} +\end{center}\pause + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +{\Large\bl{1 + 2 * 3 + (4 - 3)}} + +\begin{center} +\bl{\begin{tabular}{l} +ldc 1\\ +ldc 2\\ +ldc 3\\ +imul\\ +ldc 4\\ +ldc 3\\ +isub\\ +iadd\\ +iadd\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Variables\end{tabular}} + +{\Large\bl{$x := 5 + y * 2$}}\bigskip\pause + +\begin{itemize} +\item lookup: \bl{$\text{iload}\; number$} +\item store: \bl{$\text{istore}\; number$} +\end{itemize}\bigskip\pause + +during compilation we have to maintain a map between our identifiers and the +java bytecode numbers + +\begin{center} +\bl{$\text{compile}(a, E)$} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +\begin{center} +\bl{\begin{tabular}{@{}lcl@{}} +$\text{compile}(n, E)$ & $\dn$ & $\text{ldc}\;n$\\ +$\text{compile}(a_1 + a_2, E)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1, E) \;@\;\text{compile}(a_2. E)\;@\; \text{iadd}$}\smallskip\\ +$\text{compile}(a_1 - a_2, E)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1, E) \;@\; \text{compile}(a_2, E)\;@\; \text{isub}$}\smallskip\\ +$\text{compile}(a_1 * a_2, E)$ & $\dn$\\ +\multicolumn{3}{l}{$\qquad\text{compile}(a_1, E) \;@\; \text{compile}(a_2, E)\;@\; \text{imul}$}\bigskip\\ +$\text{compile}(x, E)$ & $\dn$ & $\text{iload}\;E(x)$\\ +\end{tabular}} +\end{center}\pause + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Statements\end{tabular}} + +We return a list of instructions and an environment for the variables + +\begin{center} +\bl{\begin{tabular}{@{}l@{\hspace{1mm}}c@{\hspace{1mm}}l@{}} +$\text{compile}(\text{skip}, E)$ & $\dn$ & $(Nil, E)$\bigskip\\ +$\text{compile}(x := a, E)$ & $\dn$\\ +\multicolumn{3}{l}{$(\text{compile}(a, E) \;@\;\text{istore}\;index, E(x\mapsto index))$}\\ +\end{tabular}} +\end{center}\medskip + +where \bl{$index$} is \bl{$E(x)$} if it is already defined, or if it is not then the largest index not yet seen + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling AExps\end{tabular}} + +{\Large\bl{$x := x + 1$}} + +\begin{center} +\bl{\begin{tabular}{l} +iload $n_x$\\ +ldc 1\\ +iadd\\ +istore $n_x$\\ +\end{tabular}} +\end{center} + +where \bl{$n_x$} is the number corresponding to the variable \bl{$x$} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Ifs\end{tabular}} + +{\Large\bl{$\text{if}\;b\;\text{else}\;cs_1\;\text{then}\;cs_2$}}\bigskip\bigskip + +\onslide<2->{Case }\only<2>{True:}\only<3>{False:} + +\begin{center} +\begin{tikzpicture}[node distance=2mm and 4mm, + block/.style={rectangle, minimum size=1cm, draw=black, line width=1mm}, + point/.style={rectangle, inner sep=0mm, minimum size=0mm, fill=red}, + skip loop/.style={red, line width=1mm, to path={-- ++(0,-10mm) -| (\tikztotarget)}}] +\node (A1) [point] {}; +\node (b) [block, right=of A1] {code of \bl{$b$}}; +\node (A2) [point, right=of b] {}; +\node (cs1) [block, right=of A2] {code of \bl{$cs_1$}}; +\node (A3) [point, right=of cs1] {}; +\node (cs2) [block, right=of A3] {code of \bl{$cs_2$}}; +\node (A4) [point, right=of cs2] {}; + +\only<2>{ +\draw (A1) edge [->, red, line width=1mm] (b); +\draw (b) edge [->, red, line width=1mm] (cs1); +\draw (cs1) edge [->, red, line width=1mm] (A3); +\draw (A3) edge [->,skip loop] (A4); +\node [below=of cs2] {\raisebox{-5mm}{\small{}jump}};} +\only<3>{ +\draw (A1) edge [->, red, line width=1mm] (b); +\draw (b) edge [->, red, line width=1mm] (A2); +\draw (A2) edge [skip loop] (A3); +\draw (A3) edge [->, red, line width=1mm] (cs2); +\draw (cs2) edge [->,red, line width=1mm] (A4); +\node [below=of cs1] {\raisebox{-5mm}{\small{}conditional jump}};} +\end{tikzpicture} +\end{center} \end{frame}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[c] +\frametitle{\begin{tabular}{c}Conditional Jumps\end{tabular}} + +\begin{minipage}{1.1\textwidth} +\begin{itemize} +\item \bl{if\_icmpeq $label$} if two ints are equal, then jump\medskip +\item \bl{if\_icmpne $label$} if two ints aren't equal, then jump\medskip +\item \bl{if\_icmpge $label$} if one int is greater or equal then another, then jump +\item[]\ldots +\end{itemize} +\end{minipage}\pause + + +\begin{center} +\bl{\begin{tabular}{l} +$L_1$:\\ +\hspace{5mm}if\_icmpeq\;$L_2$\\ +\hspace{5mm}iload 1\\ +\hspace{5mm}ldc 1\\ +\hspace{5mm}iadd\\ +\hspace{5mm}if\_icmpeq\;$L_1$\\ +$L_1$: +\end{tabular}} +\end{center} + + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling BExps\end{tabular}} + +{\Large\bl{$a_1 = a_2$}} + +\begin{center} +\bl{\begin{tabular}{l} +iload $n_x$\\ +ldc 1\\ +iadd\\ +istore $n_x$\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Ifs\end{tabular}} + +{\Large\bl{if $b$ then $cs_1$ else $cs_2$}} + +\begin{center} +\bl{\begin{tabular}{l} +iload $n_x$\\ +ldc 1\\ +iadd\\ +istore $n_x$\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Whiles\end{tabular}} + +{\Large\bl{$\text{while}\;b\;\text{do}\;cs$}}\bigskip\bigskip + +\onslide<2->{Case }\only<2>{True:}\only<3>{False:} + +\begin{center} +\begin{tikzpicture}[node distance=2mm and 4mm, + block/.style={rectangle, minimum size=1cm, draw=black, line width=1mm}, + point/.style={rectangle, inner sep=0mm, minimum size=0mm, fill=red}, + skip loop/.style={red, line width=1mm, to path={-- ++(0,-10mm) -| (\tikztotarget)}}] +\node (A0) [point, left=of A1] {}; +\node (A1) [point] {}; +\node (b) [block, right=of A1] {code of \bl{$b$}}; +\node (A2) [point, right=of b] {}; +\node (cs1) [block, right=of A2] {code of \bl{$cs$}}; +\node (A3) [point, right=of cs1] {}; +\node (A4) [point, right=of A3] {}; + +\only<2>{ +\draw (A0) edge [->, red, line width=1mm] (b); +\draw (b) edge [->, red, line width=1mm] (cs1); +\draw (cs1) edge [->, red, line width=1mm] (A3); +\draw (A3) edge [->,skip loop] (A1);} +\only<3>{ +\draw (A0) edge [->, red, line width=1mm] (b); +\draw (b) edge [->, red, line width=1mm] (A2); +\draw (A2) edge [skip loop] (A3); +\draw (A3) edge [->, red, line width=1mm] (A4);} +\end{tikzpicture} +\end{center} + + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Whiles\end{tabular}} + +{\Large\bl{while $b$ do $cs$}} + +\begin{center} +\bl{\begin{tabular}{l} +iload $n_x$\\ +ldc 1\\ +iadd\\ +istore $n_x$\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\mode{ +\begin{frame}[t] +\frametitle{\begin{tabular}{c}Compiling Writes\end{tabular}} + +{\Large\bl{write $x$}} + +\begin{center} +\bl{\begin{tabular}{l} +iload $n_x$\\ +ldc 1\\ +iadd\\ +istore $n_x$\\ +\end{tabular}} +\end{center} + +\end{frame}} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \mode{ @@ -200,9 +687,10 @@ \begin{center} \begin{tikzpicture} -\begin{axis}[axis x line=bottom, axis y line=left, xlabel=n, ylabel=mins] -\addplot file {compiled.data}; -\end{axis} +\begin{loglogaxis}[axis x line=bottom, axis y line=left, xlabel=n, ylabel=secs] +\addplot+[smooth] file {interpreted.data}; +\addplot+[smooth] file {compiled.data}; +\end{loglogaxis} \end{tikzpicture} \end{center} @@ -210,44 +698,16 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \mode{ \begin{frame}[t] -\frametitle{\begin{tabular}{c}Compiled vs.~Interpreted Code\end{tabular}} - -\mbox{}\\[-25mm]\mbox{} +\frametitle{\begin{tabular}{c}Compiled Code\end{tabular}} \begin{center} -\begin{tikzpicture}[y=.4cm, x=.00000009cm] - %axis - \draw (0,0) -- coordinate (x axis mid) (5,0); - \draw (0,0) -- coordinate (y axis mid) (0,5); - %ticks - \foreach \x in {0, 1000,...,10000} - \draw (\x,1pt) -- (\x,-3pt) - node[anchor=north] {\small \x{}00}; - \foreach \y in {0,0.5,1, ..., 5.5} - \draw (1pt,\y) -- (-3pt,\y) - node[anchor=east] {\small\y}; - %labels - \node[below=0.6cm] at (x axis mid) {\bl{1}s}; - \node[rotate=90, left=1.2cm] at (y axis mid) {secs}; - - %plots - %\draw[color=blue] plot[mark=*, mark options={fill=white}] - % file {compiled.data}; - %\only<2->{\draw[color=red] plot[mark=triangle*, mark options={fill=white} ] - % file {interpreted.data};} - %legend - %\begin{scope}[shift={(400,20)}] - %\draw[color=blue] (0,0) -- - % plot[mark=*, mark options={fill=white}] (0.25,0) -- (0.5,0) - % node[right]{\small unambiguous}; - %\only<2->{\draw[yshift=\baselineskip, color=red] (0,0) -- - % plot[mark=triangle*, mark options={fill=white}] (0.25,0) -- (0.5,0) - % node[right]{\small ambiguous};} - %\end{scope} +\begin{tikzpicture} +\begin{axis}[axis x line=bottom, axis y line=left, xlabel=n, ylabel=secs] +\addplot+[smooth] file {compiled.data}; +\end{axis} \end{tikzpicture} \end{center} @@ -255,9 +715,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - \end{document} %%% Local Variables: diff -r fd894e017e12 -r 191daa3ee29e while1.scala --- a/while1.scala Sat Nov 24 15:10:43 2012 +0000 +++ b/while1.scala Mon Nov 26 01:11:55 2012 +0000 @@ -10,7 +10,7 @@ val NUM = PLUS(DIGIT) val KEYWORD = ALTS("skip", "while", "do", "if", "then", "else", "true", "false", "write") val SEMI: Rexp = ";" -val OP: Rexp = ALTS(":=", "=", "-", "+", "*", "!", "<", ">") +val OP: Rexp = ALTS(":=", "=", "-", "+", "*", "!=", "<", ">") val WHITESPACE = PLUS(RANGE(" \n")) val RPAREN: Rexp = ")" val LPAREN: Rexp = "(" @@ -137,8 +137,6 @@ case Bop("=", a1, a2) => eval_aexp(a1, env) == eval_aexp(a2, env) case Bop("!=", a1, a2) => !(eval_aexp(a1, env) == eval_aexp(a2, env)) case Bop("<", a1, a2) => eval_aexp(a1, env) < eval_aexp(a2, env) - case Bop("&&", a1, a2) => eval_aexp(a1, env) > eval_aexp(a2, env) - case Bop("||", a1, a2) => eval_aexp(a1, env) < eval_aexp(a2, env) } def eval_aexp(a: AExp, env : Env) : Int = a match { @@ -173,14 +171,49 @@ //examples -eval_prog("loops.while") +//eval_prog("loops.while") //eval_prog("fib.while") +def time_needed[T](i: Int, code: => T) = { + val start = System.nanoTime() + for (j <- 1 to i) code + val end = System.nanoTime() + (end - start)/(i * 1.0e9) +} + + +val test_prog = """ +start := XXX; +x := start; +y := start; +z := start; +while 0 < x do { + while 0 < y do { + while 0 < z do { + z := z - 1 + }; + z := start; + y := y - 1 + }; + y := start; + x := x - 1 +} +""" + + + +def eval_test(n: Int) : Unit = { + val tks = Tok.fromString(test_prog.replaceAllLiterally("XXX", n.toString)) + val ast = Stmts.parse_single(tks) + println(n + " " + time_needed(2, eval_bl(ast, Map.empty))) +} + +List(1, 200, 400, 600, 800, 1000, 1200, 1400, 1600).map(eval_test(_)) + + - -