# HG changeset patch # User Christian Urban # Date 1595591899 -3600 # Node ID 084e2843f478c5e7a97f81b956a2a33e66edc3c4 # Parent 14a348d050b3bf2154726e9b22682dabb8c60162 updated diff -r 14a348d050b3 -r 084e2843f478 progs/bf/bfc0.scala --- a/progs/bf/bfc0.scala Tue Jul 21 00:12:34 2020 +0100 +++ b/progs/bf/bfc0.scala Fri Jul 24 12:58:19 2020 +0100 @@ -1,7 +1,12 @@ -// A Transpiler for the Brainf*** language -//========================================= +// A Transpiler for the Brainf*** language to C +//=============================================== +// +// Call with +// +// amm bfc0.sc <> +// -import io.Source + import scala.util._ @@ -64,21 +69,15 @@ (end - start)/(n * 1.0e9) } -// the mandelbrot program -val b0 = load_bff("mandelbrot.bf") +// Running Testcases +//=================== -println(s"${time_needed(1, compile_run(b0))} secs") +@doc(" the argument should be a BF program ") +@main +def main(fname: String) = { + val bf_str = os.read(os.pwd / fname) + println(s"${time_needed(1, run(bf_str))} secs") +} -// a benchmark program (counts down from 'Z' to 'A') -val b1 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ - [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++ - ++++++++[>++++++++++[>++++++++++[>++++++++++[>+ - +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.""" - -println(s"${time_needed(1, compile_run(b1))} secs") - - - - diff -r 14a348d050b3 -r 084e2843f478 progs/bf/bfi.sc --- a/progs/bf/bfi.sc Tue Jul 21 00:12:34 2020 +0100 +++ b/progs/bf/bfi.sc Fri Jul 24 12:58:19 2020 +0100 @@ -1,9 +1,10 @@ // A simple Interpreter for BF*** Programs //========================================= // -// Call +// Call with // // amm bfi.sc <> +// import scala.util._ @@ -18,7 +19,6 @@ def write(mem: Mem, mp: Int, v: Int) : Mem = mem.updated(mp, v) - // Right and Left Jumps in BF loops def jumpRight(prog: String, pc: Int, level: Int) : Int = { if (prog.length <= pc) pc @@ -73,8 +73,8 @@ (end - start)/(n * 1.0e9) } -// Testcases -//=========== +// Running Testcases +//=================== @doc(" the argument should be a BF program ") @main diff -r 14a348d050b3 -r 084e2843f478 progs/display/MinimalApplication.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/progs/display/MinimalApplication.scala Fri Jul 24 12:58:19 2020 +0100 @@ -0,0 +1,72 @@ +package app + +import scalatags.Text.all._ +import scala.util.Random + + +object MinimalApplication extends cask.MainRoutes{ + + val bootstrap = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.css" + + var x = Random.between(0, 7) + var y = Random.between(0, 7) + var z = Random.between(0, 7) + + abstract class Answer + case object No extends Answer + case object Correct extends Answer + case class Wrong(n: Int) extends Answer + + var ans : Answer = No + var cnt = 1 + + val heart = raw("❤️") + val unicorn = raw("🦄") + + var nms = List("Christiane", "Sebastian") + + @cask.get("/") + def hello() = + doctype("html")( + html( + head(link(rel := "stylesheet", href := bootstrap)), + body( + div(cls := "container")( + //h1(s"Hello ${nms((cnt / 3) % 2)}!"), + h1(s"Hello Christiane"), + h1(s"$x + $y = ??"), + ans match { + case No => "" + case Correct => i(color.green)("Correct!") + case Wrong(n) => i(color.red)(s"$n is wrong!") + }, + form(action := "/", method := "post")( + frag( + for (i <- 0 to 12) yield button(`type` := "submit", name := "name", value := i.toString)(i.toString) + ) + ), + frag( + for (i <- 0 until cnt) yield + if ((i + 1) % 10 != 0) heart else unicorn + ) + ) + ) + ) + ) + + @cask.postForm("/") + def answer(name: String) = { + if (x + y == name.toInt) { + ans = Correct + x = Random.between(0, 7) + y = Random.between(0, 7) + z = Random.between(0, 7) + cnt = cnt + 1 + } + else + ans = Wrong(name.toInt) + hello() + } + + initialize() +} diff -r 14a348d050b3 -r 084e2843f478 progs/display/build.sc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/progs/display/build.sc Fri Jul 24 12:58:19 2020 +0100 @@ -0,0 +1,18 @@ +import mill._ +import scalalib._ + +val baseDir = build.millSourcePath + + +object app extends ScalaModule { + def scalaVersion = "2.13.3" + + def ivyDeps = Agg( + ivy"com.lihaoyi::cask:0.6.7", + ivy"com.lihaoyi::scalatags:0.9.1" + ) + + override def sources = T.sources(baseDir / "display.scala") + //override def resources = T.sources(baseDir / "static") + +} diff -r 14a348d050b3 -r 084e2843f478 progs/display/dfa.scala --- a/progs/display/dfa.scala Tue Jul 21 00:12:34 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -// DFAs in Scala using partial functions -import scala.util.Try - -// type abbreviation for partial functions -type :=>[A, B] = PartialFunction[A, B] - -case class DFA[A, C](start: A, // starting state - delta: (A, C) :=> A, // transition (partial fun) - fins: A => Boolean) { // final states - - def deltas(q: A, s: List[C]) : A = s match { - case Nil => q - case c::cs => deltas(delta(q, c), cs) - } - - def accepts(s: List[C]) : Boolean = - Try(fins(deltas(start, s))) getOrElse false -} - -// the example shown earlier in the handout -abstract class State -case object Q0 extends State -case object Q1 extends State -case object Q2 extends State -case object Q3 extends State -case object Q4 extends State - -val delta : (State, Char) :=> State = - { case (Q0, 'a') => Q1 - case (Q0, 'b') => Q2 - case (Q1, 'a') => Q4 - case (Q1, 'b') => Q2 - case (Q2, 'a') => Q3 - case (Q2, 'b') => Q2 - case (Q3, 'a') => Q4 - case (Q3, 'b') => Q0 - case (Q4, 'a') => Q4 - case (Q4, 'b') => Q4 } - -val dfa = DFA(Q0, delta, Set[State](Q4)) - -dfa.accepts("bbabaab".toList) // true -dfa.accepts("baba".toList) // false diff -r 14a348d050b3 -r 084e2843f478 progs/display/display.scala --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/progs/display/display.scala Fri Jul 24 12:58:19 2020 +0100 @@ -0,0 +1,100 @@ + +import scalatags.Text.all._ +import scalatags.Text._ +import scala.util.Random + + + +object MinimalApplication extends cask.MainRoutes{ + + abstract class Rexp + case object ZERO extends Rexp + case object ONE extends Rexp + case class CHAR(c: Char) extends Rexp + case class ALT(r1: Rexp, r2: Rexp) extends Rexp + case class SEQ(r1: Rexp, r2: Rexp) extends Rexp + case class STAR(r: Rexp) extends Rexp + + val evil2 = ALT(SEQ(STAR(STAR(CHAR('a'))), CHAR('b')), ONE) + + def pp(r: Rexp) : TypedTag[String] = r match { + case CHAR(c) => li(code(c.toString)) + case ALT(r1, r2) => li(code("+"), ul(pp(r1), pp(r2))) + case SEQ(r1, r2) => li(code("o"), ul(pp(r1), pp(r2))) + case STAR(r1) => li(code("*"), ul(pp(r1))) + case ZERO => li(code("0")) + case ONE => li(code(div(style :="line-height:50%") + ("1",br, + div(color:="blue", fontSize:=6.pt)("0101010101")))) + } + + abstract class ARexp + case object AZERO extends ARexp + case class AONE(bs: String) extends ARexp + case class ACHAR(bs:String, c: Char) extends ARexp + case class AALT(bs:String, r1: ARexp, r2: ARexp) extends ARexp + case class ASEQ(bs: String,r1: ARexp, r2: ARexp) extends ARexp + case class ASTAR(bs:String,r: ARexp) extends ARexp + + + def node(s: String, bs: String) = { + if (bs == "") + code(div(div(style :="line-height:75%")(s, br, div(color:="blue", fontSize:=6.pt)(raw(" "))))) + else + code(div(div(style :="line-height:75%")(s, br, div(color:="blue", fontSize:=6.pt)(bs)))) + } + + + val aevil2 = AALT("", ASEQ(" ",ASTAR("111",ASTAR("0",ACHAR("00",'a'))), ACHAR("00",'b')), AONE("01")) + + def ppa(r: ARexp) : TypedTag[String] = r match { + case ACHAR(bs, c) => li(node(c.toString, bs)) + case AALT(bs, r1, r2) => li(node("+", bs), ul(ppa(r1), ppa(r2))) + case ASEQ(bs, r1, r2) => li(node("o", bs), ul(ppa(r1), ppa(r2))) + case ASTAR(bs, r1) => li(node("*", bs), ul(ppa(r1))) + case AZERO => li(node("0", "")) + case AONE(bs) => li(node("1", bs)) + } + + + + + + val bootstrap = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.css" + + var cnt = 0 + + @cask.get("/") + def hello() = + doctype("html")( + html( + head(link(rel := "stylesheet", href := bootstrap), + link(rel := "stylesheet", href := "static/style.css")), + body( + div(cls := "container")( + h1(s"Hello"), + i(color.green)(s"$cnt"), + form(action := "/", method := "post")( + button(`type` := "submit", name := "name", value := 1)(s"1"), + ), + ul(cls := "tree")(pp(evil2)), + ul(cls := "tree")(ppa(aevil2)) + ) + ) + ) + ) + + @cask.postForm("/") + def answer(name: String) = { + cnt = cnt + 1 + hello() + } + + //@cask.staticFiles("/static/") + //def staticFileRoutes() = "static" + + @cask.staticResources("/static") + def staticResourceRoutes() = "static" + + initialize() +} diff -r 14a348d050b3 -r 084e2843f478 progs/display/enfa.scala --- a/progs/display/enfa.scala Tue Jul 21 00:12:34 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -// epsilon NFAs...immediately translated into NFAs -// (needs dfa.scala and nfa.scala) - -// fixpoint construction -import scala.annotation.tailrec -@tailrec -def fixpT[A](f: A => A, x: A): A = { - val fx = f(x) - if (fx == x) x else fixpT(f, fx) -} - -// translates eNFAs directly into NFAs -def eNFA[A, C](starts: Set[A], // starting states - delta: (A, Option[C]) :=> Set[A], // epsilon-transitions - fins: A => Boolean) : NFA[A, C] = { // final states - - // epsilon transitions - def enext(q: A) : Set[A] = - applyOrElse(delta, (q, None)) - - def enexts(qs: Set[A]) : Set[A] = - qs | qs.flatMap(enext(_)) // | is the set-union in Scala - - // epsilon closure - def ecl(qs: Set[A]) : Set[A] = - fixpT(enexts, qs) - - // "normal" transitions - def next(q: A, c: C) : Set[A] = - applyOrElse(delta, (q, Some(c))) - - def nexts(qs: Set[A], c: C) : Set[A] = - ecl(ecl(qs).flatMap(next(_, c))) - - // result NFA - NFA(ecl(starts), - { case (q, c) => nexts(Set(q), c) }, - q => ecl(Set(q)) exists fins) -} diff -r 14a348d050b3 -r 084e2843f478 progs/display/nfa.scala --- a/progs/display/nfa.scala Tue Jul 21 00:12:34 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -// NFAs in Scala using partial functions (returning -// sets of states) -// -// needs :load dfa.scala for states - - -// type abbreviation for partial functions -type :=>[A, B] = PartialFunction[A, B] - -// return an empty set when not defined -def applyOrElse[A, B](f: A :=> Set[B], x: A) : Set[B] = - Try(f(x)) getOrElse Set[B]() - - -// NFAs -case class NFA[A, C](starts: Set[A], // starting states - delta: (A, C) :=> Set[A], // transition function - fins: A => Boolean) { // final states - - // given a state and a character, what is the set of - // next states? if there is none => empty set - def next(q: A, c: C) : Set[A] = - applyOrElse(delta, (q, c)) - - def nexts(qs: Set[A], c: C) : Set[A] = - qs.flatMap(next(_, c)) - - // given some states and a string, what is the set - // of next states? - def deltas(qs: Set[A], s: List[C]) : Set[A] = s match { - case Nil => qs - case c::cs => deltas(nexts(qs, c), cs) - } - - // is a string accepted by an NFA? - def accepts(s: List[C]) : Boolean = - deltas(starts, s).exists(fins) -} diff -r 14a348d050b3 -r 084e2843f478 progs/display/style.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/progs/display/style.css Fri Jul 24 12:58:19 2020 +0100 @@ -0,0 +1,93 @@ +body { + font-family: Calibri, Segoe, "Segoe UI", "Gill Sans", "Gill Sans MT", sans-serif; +} + +/* It's supposed to look like a tree diagram */ +.tree, .tree ul, .tree li { + list-style: none; + margin: 0; + padding: 0; + position: relative; +} + +.tree { + margin: 0 0 1em; + text-align: center; +} +.tree, .tree ul { + display: table; +} +.tree ul { + width: 100%; +} + .tree li { + display: table-cell; + padding: .5em 0; + vertical-align: top; + } + /* _________ */ + .tree li:before { + outline: solid 1px #666; + content: ""; + left: 0; + position: absolute; + right: 0; + top: 0; + } + .tree li:first-child:before {left: 50%;} + .tree li:last-child:before {right: 50%;} + + .tree code, .tree span { + border: solid .1em #666; + border-radius: .2em; + display: inline-block; + margin: 0 .2em .5em; + padding: .2em .5em; + position: relative; + } + /* If the tree represents DOM structure */ + .tree code { + font-family: monaco, Consolas, 'Lucida Console', monospace; + } + + /* | */ + .tree ul:before, + .tree code:before, + .tree span:before { + outline: solid 1px #666; + content: ""; + height: .5em; + left: 50%; + position: absolute; + } + .tree ul:before { + top: -.5em; + } + .tree code:before, + .tree span:before { + top: -.55em; + } + +/* The root node doesn't connect upwards */ +.tree > li {margin-top: 0;} + .tree > li:before, + .tree > li:after, + .tree > li > code:before, + .tree > li > span:before { + outline: none; + } + + +/* Create two equal columns that floats next to each other */ +.column { + float: left; + width: 40%; + padding: 10px; +} + +/* Clear floats after the columns */ +.row:after { + content: ""; + display: table; + clear: both; +} diff -r 14a348d050b3 -r 084e2843f478 progs/display/thompson1.scala --- a/progs/display/thompson1.scala Tue Jul 21 00:12:34 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -// Thompson Construction (Part 1) -// (needs :load dfa.scala -// :load nfa.scala -// :load enfa.scala) - - -// states for Thompson construction -case class TState(i: Int) extends State - -object TState { - var counter = 0 - - def apply() : TState = { - counter += 1; - new TState(counter - 1) - } -} - - -// a type abbreviation -type NFAt = NFA[TState, Char] - - -// a NFA that does not accept any string -def NFA_ZERO(): NFAt = { - val Q = TState() - NFA(Set(Q), { case _ => Set() }, Set()) -} - -// a NFA that accepts the empty string -def NFA_ONE() : NFAt = { - val Q = TState() - NFA(Set(Q), { case _ => Set() }, Set(Q)) -} - -// a NFA that accepts the string "c" -def NFA_CHAR(c: Char) : NFAt = { - val Q1 = TState() - val Q2 = TState() - NFA(Set(Q1), { case (Q1, d) if (c == d) => Set(Q2) }, Set(Q2)) -} diff -r 14a348d050b3 -r 084e2843f478 progs/display/thompson2.scala --- a/progs/display/thompson2.scala Tue Jul 21 00:12:34 2020 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -// Thompson Construction (Part 2) - -// some more type abbreviations -type NFAtrans = (TState, Char) :=> Set[TState] -type eNFAtrans = (TState, Option[Char]) :=> Set[TState] - - -// for composing an eNFA transition with a NFA transition -implicit class RichPF(val f: eNFAtrans) extends AnyVal { - def +++(g: NFAtrans) : eNFAtrans = - { case (q, None) => applyOrElse(f, (q, None)) - case (q, Some(c)) => - applyOrElse(f, (q, Some(c))) | applyOrElse(g, (q, c)) } -} - -// sequence of two NFAs -def NFA_SEQ(enfa1: NFAt, enfa2: NFAt) : NFAt = { - val new_delta : eNFAtrans = - { case (q, None) if enfa1.fins(q) => enfa2.starts } - - eNFA(enfa1.starts, new_delta +++ enfa1.delta +++ enfa2.delta, - enfa2.fins) -} - -// alternative of two NFAs -def NFA_ALT(enfa1: NFAt, enfa2: NFAt) : NFAt = { - val new_delta : NFAtrans = { - case (q, c) => applyOrElse(enfa1.delta, (q, c)) | - applyOrElse(enfa2.delta, (q, c)) } - val new_fins = (q: TState) => enfa1.fins(q) || enfa2.fins(q) - - NFA(enfa1.starts | enfa2.starts, new_delta, new_fins) -} - -// star of a NFA -def NFA_STAR(enfa: NFAt) : NFAt = { - val Q = TState() - val new_delta : eNFAtrans = - { case (Q, None) => enfa.starts - case (q, None) if enfa.fins(q) => Set(Q) } - - eNFA(Set(Q), new_delta +++ enfa.delta, Set(Q)) -}