Commit 48d36448 authored by Jim Newton's avatar Jim Newton

adding scala code

parent 1d19149e
...@@ -3,3 +3,5 @@ name := "clcompat" ...@@ -3,3 +3,5 @@ name := "clcompat"
version := "0.1" version := "0.1"
scalaVersion := "2.13.3" scalaVersion := "2.13.3"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.0" % "test"
// Copyright (c) 2019 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package accumulators
case class successor[A](init:A){
var current:A = init
def apply(f:A=>A):A = {
current = f(current)
current
}
}
object Accumulators {
def withCollector[A](f: (A => Unit) => Unit): List[A] = {
var objects: List[A] = Nil
def collect(obj: A): Unit = {
objects = obj :: objects
}
f(collect)
objects.reverse
}
def withSetCollector[A](f: (A => Unit) => Unit): Set[A] = {
var objects: Set[A] = Set()
def collect(obj: A): Unit = {
objects = objects+obj
}
f(collect)
objects
}
def withNconc[A](f: (List[A] => Unit) => Unit): List[A] = {
withCollector[List[A]] { nconc =>
f(nconc)
}.flatten
}
def withReducer[A](init:A,folder:(A,A)=>A)(f:(A=>Unit)=>Unit):A = {
var acc = init
def reduce(obj:A):Unit = {
acc = folder(acc,obj)
}
f(reduce)
acc
}
def withMaximizer[A <% Ordered[A]](init: A)(f: (A => Unit) => Unit): A = {
withReducer(init, (a:A,b:A)=>if (a < b) b else a)(f)
}
def withMinimizer[A <% Ordered[A]](init: A)(f: (A => Unit) => Unit): A = {
withReducer(init, (a:A,b:A)=>if (a > b) b else a)(f)
}
def withSummer[A](init:A,plus:(A,A)=>A)(f:(A=>Unit)=>Unit): A = {
withReducer(init,plus)(f)
}
def withCounter(f:(()=>Unit)=>Unit):Int = {
var i = 0
def reduce():Unit = {
i = i+1
}
f(reduce)
i
}
def withOutputToString(f:(String=>Unit)=>Unit):String = {
withOutputToString(f, java.nio.charset.StandardCharsets.UTF_8)
}
def withOutputToString(f:(String=>Unit)=>Unit,
encoding:java.nio.charset.Charset):String = {
import java.io.{ByteArrayOutputStream, PrintWriter}
val baos = new ByteArrayOutputStream()
val pw = new PrintWriter(baos)
var str = ""
def printer(str: String): Unit = {
pw.print(str)
}
try {
f(printer)
pw.flush()
str = new String(baos.toByteArray, encoding)
} finally pw.close()
str
}
def main(argv: Array[String]): Unit = {
import java.io.{ByteArrayOutputStream, PrintWriter}
import java.nio.charset.StandardCharsets
def printToOutputString(f: PrintWriter => Unit): String = {
val baos = new ByteArrayOutputStream()
val pw = new PrintWriter(baos)
try {
f(pw)
pw.flush()
new String(baos.toByteArray, StandardCharsets.UTF_8)
} finally pw.close()
}
val helloWorld = printToOutputString { pw =>
pw.print("hello ")
pw.print("world")
}
println(s"helloWorld=$helloWorld")
}
}
\ No newline at end of file
// Copyright (c) 2019,20 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package cl
object CLcompat {
def prog1[A,B](val1:A, code2: => B):A = {
code2 // eval for side effect
val1
}
def prog2[A,B,C](val1:A, val2:B, code2: => C):B = {
code2 // eval for side effect
val2
}
def every[A, B](L1: List[A], L2: List[B])(f: (A, B) => Boolean): Boolean = {
(L1, L2) match {
case (a :: as, b :: bs) => f(a, b) && every(as, bs)(f)
case (_, _) => true
}
}
def merge[A](clauses1: List[A], clauses2: List[A], clauseLess:(A,A)=>Boolean): List[A] = {
// Merge two lists which are already in sorted order, according to clauseLess
// into a new list which is likewise in sorted order.
def loop(clauses1: List[A], clauses2: List[A], acc: List[A]): List[A] = {
(clauses1, clauses2) match {
case (Nil, Nil) => acc.reverse
case (a :: as, Nil) => loop(as, Nil, a :: acc)
case (Nil, b :: bs) => loop(Nil, bs, b :: acc)
case (a :: as, b :: bs) if clauseLess(a, b) => loop(as, b :: bs, a :: acc)
case (a :: as, b :: bs) => loop(a :: as, bs, b :: acc)
}
}
loop(clauses1, clauses2, Nil)
}
def mapcan[A1, A2, B](f: (A1, A2) => List[B], L1: List[A1], L2: List[A2]): List[B] = {
(L1, L2).zipped.flatMap(f)
}
def block[A](body:(A=>Nothing)=>A):A = {
// CL like block/return, the name of the return() function is provided
// by the caller.
// Usage: block{ ret => ... ret(someValue) ...}
// extending Exception with NoStackTrace prevents throwing the
// exception from computing the stacktrace and storing the information.
// We don't need a stacktrace because the purpose of this exception
// is simply to perform a non-local exit.
import scala.util.control.NoStackTrace
class NonLocalExit(val data:A,val ident:(A=>Nothing)=>A) extends Exception with NoStackTrace {}
def ret(data:A):Nothing = {
throw new NonLocalExit(data,body)
}
try{
body(ret)
}
catch{
case nonLocalExit: NonLocalExit if nonLocalExit.ident eq body => nonLocalExit.data
}
}
}
// Copyright (c) 2019 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import org.scalatest.funsuite.AnyFunSuite
import accumulators.Accumulators._
import accumulators._
class AccumulatorSuite extends AnyFunSuite {
test("successor"){
val primes = List(11,13,17,19)
val odds = Array(3,5,7)
val s1 = successor(0)
val accumulated = for {
w <- primes
x = s1(_+3)
s2 = successor(false)
y <- odds
z = s2(!_)
} yield (w,x,y,z)
assert( accumulated == List((11,3,3,true), (11,3,5,false), (11,3,7,true), (13,6,3,true), (13,6,5,false), (13,6,7,true),
(17,9,3,true), (17,9,5,false), (17,9,7,true), (19,12,3,true), (19,12,5,false), (19,12,7,true)))
}
test("collector") {
assert(List(1, 2, 3) == withCollector[Int](collect =>
(1 to 3).foreach { i => collect(i) }
))
}
test("maximize") {
assert(10 == withMaximizer[Int](0)(
maximize => {
maximize(1)
maximize(3)
maximize(10)
maximize(4)
}))
}
test("minimize") {
assert(-10 == withMinimizer[Int](0)(
maximize => {
maximize(-1)
maximize(-3)
maximize(-10)
maximize(-4)
}))
}
test("nconc") {
assert(List(1, 2, 3, 4, 5, 6) == withNconc[Int](
nconc => {
nconc(List(1, 2, 3))
nconc(List(4, 5))
nconc(List(6))
}
))
}
test("summer") {
assert(8 == withSummer[Int](0, (a: Int, b: Int) => a + b)(summing => {
summing(1)
summing(3)
summing(4)
}))
}
test("printer") {
assert("hello world" == withOutputToString(printer => {
printer("hello")
printer(" ")
printer("world")
}))
}
}
// Copyright (c) 2020 EPITA Research and Development Laboratory
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import org.scalatest.funsuite.AnyFunSuite
import cl.CLcompat._
class CLcompatTestSuite extends AnyFunSuite {
type T= Int=>Nothing
assert(42 == block{ret:T => ret(42)})
assert(43 == block{ret:T => 43})
assert(44 == block{ret1:T =>
block{ret2:T =>
ret1(44)
}})
assert(45 == block{ret1:T =>
block{ret2:T =>
ret1(45)
}
ret1(46)})
assert(48 == block{ret1:T =>
block{ret2:T =>
ret2(47)
}
ret1(48)})
assert(49 == block{ret1:T =>
block{ret2:T =>
ret1(49)
}
assert(false, "this line should never be reached")
})
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment