updated
authorChristian Urban <christian dot urban at kcl dot ac dot uk>
Fri, 24 Jul 2020 12:58:19 +0100
changeset 738 084e2843f478
parent 737 14a348d050b3
child 739 220aea0e5517
updated
progs/bf/bfc0.scala
progs/bf/bfi.sc
progs/display/MinimalApplication.scala
progs/display/build.sc
progs/display/dfa.scala
progs/display/display.scala
progs/display/enfa.scala
progs/display/nfa.scala
progs/display/style.css
progs/display/thompson1.scala
progs/display/thompson2.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 <<bf_program.bf>>
+//
 
-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")
-
-
-
-
--- 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 <<bf_program.bf>>
+//
 
 
 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
--- /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("&#10084;&#65039;")
+  val unicorn = raw("&#129412;")
+
+  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()
+}
--- /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")
+
+}
--- 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
--- /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("&nbsp")))))
+    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()
+}
--- 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)
-}
--- 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)
-}
--- /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;
+}    
--- 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))
-}
--- 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))
-}