From 96a881c2bb19f93ed5131785881b58dce8d27a5e Mon Sep 17 00:00:00 2001 From: molarmanful Date: Tue, 24 Oct 2023 04:34:14 -0400 Subject: [PATCH] fread --- build.sc | 5 +---- sclin/src/Lib.scala | 20 ++++++++++---------- sclin/src/Main.scala | 5 ++++- sclin/src/Types.scala | 39 +++++++++++++++++++++++++-------------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/build.sc b/build.sc index 5deabc7..b76ccdf 100644 --- a/build.sc +++ b/build.sc @@ -30,10 +30,7 @@ object sclin extends ScoverageModule with PublishModule { ivy"com.lihaoyi::fansi:0.4.0", ivy"com.lihaoyi::upickle:3.1.3", ivy"io.monix::monix:3.4.1", - ivy"io.monix::monix-nio:0.1.0", - ivy"dev.zio::zio:2.0.18", - ivy"dev.zio::zio-streams:2.0.18", - ivy"dev.zio::zio-connect-file:0.4.4", + ivy"com.lihaoyi::geny:1.0.0", ivy"com.lihaoyi::os-lib:0.9.1" ) diff --git a/sclin/src/Lib.scala b/sclin/src/Lib.scala index f3c91fd..c2249b2 100644 --- a/sclin/src/Lib.scala +++ b/sclin/src/Lib.scala @@ -2,8 +2,6 @@ package sclin import monix.eval.Task import monix.execution.Scheduler.Implicits.global -import monix.nio.file._ -import monix.nio.text._ import monix.reactive.Observable import scala.annotation._ import scala.collection.immutable.VectorMap @@ -425,6 +423,8 @@ extension (env: ENV) case "f>o" => outf // TODO: docs case "fs>" => fread + // TODO: docs + case "fs>n" => freadl /* @s a -> a a */ @@ -2343,7 +2343,7 @@ extension (env: ENV) def evalTRY: ENV = env.arg1((x, env) => env.push(x.vec1(f => Try(env.push(f).quar.getStack(0)).toTRY)) ) - def throwERR: ENV = env.arg1((x, env) => throw x.toThrow) + def throwERR: ENV = env.arg1((x, env) => throw x.toERR.x) def evalArrSt: ENV = env.arg2((x, f, env) => env.push(env.push(x).unwrap$.push(f).evale.stack.toARR.matchType(x)) ) @@ -2442,15 +2442,15 @@ extension (env: ENV) def fread: ENV = env.mod2((x, y) => y.vec1(n => - val n1 = n.toInt - if n1 < 2 then throw LinEx("BUF_N", "buffer size < 2") - else - readAsync(x.toPath.toNIO, n1) - .pipeThrough(UTF8Codec.utf8Decode) - .map(_.sSTR) - .toOBS + os.read + .chunks(x.toPath, n.toInt) + .obs + .map { case (xs, n) => xs.take(n).toVector.map(_.toChar).mkString.sSTR } + .toOBS ) ) + def freadl: ENV = + env.mod1(x => os.read.lines.stream(x.toPath).obs.map(_.sSTR).toOBS) def dup: ENV = env.mods1(x => Vector(x, x)) def dups: ENV = env.push(env.stack.toARR) diff --git a/sclin/src/Main.scala b/sclin/src/Main.scala index db7f379..4dfe7cf 100644 --- a/sclin/src/Main.scala +++ b/sclin/src/Main.scala @@ -40,7 +40,10 @@ object Main: case e: java.nio.file.NoSuchFileException => err(s"no file ${e.getFile()}") case e: LinERR => err(e.toString) - case e => err(s"ERR: $e\n${e.getStackTrace.mkString("\n")}") + case e => + err( + s"ERR: $e\n ---\n${e.getStackTrace.map(" " + _).mkString("\n")}" + ) given TokensReader.Simple[os.Path] with diff --git a/sclin/src/Types.scala b/sclin/src/Types.scala index b36f852..2e9fabc 100644 --- a/sclin/src/Types.scala +++ b/sclin/src/Types.scala @@ -1,10 +1,12 @@ package sclin import cats.kernel.Eq +import geny.Generator import monix.eval.Task -import monix.execution.CancelableFuture +import monix.execution._ +import monix.execution.Ack.Continue import monix.execution.Scheduler.Implicits.global -import monix.reactive.Observable +import monix.reactive._ import scala.collection.immutable.HashMap import scala.collection.immutable.VectorMap import scala.concurrent._ @@ -107,7 +109,7 @@ enum ANY: .find(_ != 0) .getOrElse(x1.sizeCompare(t1)) case (_, Itr(_)) => -t.cmp(this) - case (DBL(x), Nmy(y)) => x.compare(y.toDouble) + case (DBL(x), Nmy(y)) => x.compare(y.toDBL.x) case (Nmy(x), DBL(y)) => -t.cmp(this) case (NUM(x), NUM(y)) => x.compare(y) case (NUM(x), _) => @@ -449,8 +451,8 @@ enum ANY: def toNUM: NUM = try this match - case UN => NUM(0) case x: NUM => x + case UN => NUM(0) case TF(x) => x.boolNUM case Sty(x) => x.toNUM case _ => toSTR.x.toNUM @@ -459,17 +461,14 @@ enum ANY: throw LinEx("CAST", "bad NUM cast " + toForm) case e => throw e - def toDBL: DBL = DBL(toDouble) - - def toDouble: Double = toNUM.x.toDouble - - def toThrow: Throwable = this match - case ERR(x) => x - case x => LinEx("_", x.toString) + def toDBL: DBL = this match + case x: DBL => x + case UN => DBL(0) + case _ => toNUM.x.toDouble.toDBL def toERR: ERR = this match case x: ERR => x - case _ => toThrow.pipe(ERR(_)) + case x => LinEx("_", x.toString).pipe(ERR(_)) def toTRY: TRY = this match case x: TRY => x @@ -1032,8 +1031,8 @@ enum ANY: def fNum2(t: ANY, f: (Double, Double) => ANY, g: (NUMF, NUMF) => ANY) = (this, t) match - case (DBL(x), Nmy(y)) => f(x, y.toDouble) - case (Nmy(x), DBL(y)) => f(x.toDouble, y) + case (DBL(x), Nmy(y)) => f(x, y.toDBL.x) + case (Nmy(x), DBL(y)) => f(x.toDBL.x, y) case (x, y) => g(x.toNUM.x, y.toNUM.x) given ReadWriter[ANY] = readwriter[ujson.Value].bimap[ANY](_.toJSON, _.toANY) @@ -1206,6 +1205,18 @@ object ANY: extension (t: Observable[ANY]) def toOBS: OBS = OBS(t) + extension [T](g: Generator[T]) + + def obs: Observable[T] = + Observable.create(OverflowStrategy.Unbounded)(s => + g.generate(s.onNext(_) match + case Ack.Continue => Generator.Continue + case Ack.Stop => Generator.End + ) + s.onComplete() + Cancelable.empty + ) + /** Pattern for `SEQ`-like. */ object Itr: