--- 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("❤️")
+ 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()
+}
--- /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(" ")))))
+ 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))
-}