Skip to content

Commit

Permalink
Remove optional ops from PlatformIO (#1328)
Browse files Browse the repository at this point in the history
* Remove optional ops from PlatformIO

* fix some js code

* minor fixes
  • Loading branch information
johnynek authored Dec 22, 2024
1 parent 0800f9f commit 34aa4a8
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 180 deletions.
50 changes: 21 additions & 29 deletions cli/src/main/scala/org/bykn/bosatsu/IOPlatformIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,23 @@ object IOPlatformIO extends PlatformIO[IO, JPath] {
override def pathArg: Argument[Path] =
Argument.readPath

def resolve(base: JPath, p: List[String]): JPath =
p.foldLeft(base)(_.resolve(_))

override def moduleIOMonad: MonadError[IO, Throwable] =
cats.effect.IO.asyncForIO

def readPath(path: Path): IO[String] =
def readUtf8(path: Path): IO[String] =
IO.blocking(new String(java.nio.file.Files.readAllBytes(path), "utf-8"))

val resolvePath: Some[(Path, PackageName) => IO[Option[Path]]] =
Some(
{ (root: Path, pack: PackageName) =>
val dir = pack.parts.init.foldLeft(root)(_.resolve(_))
val filePath = dir.resolve(pack.parts.last + ".bosatsu")
IO.blocking {
// this is a side-effect since file is mutable
// and talks to the file system
val file = filePath.toFile
if (file.exists()) Some(filePath)
else None
}
def fsDataType(p: Path): IO[Option[PlatformIO.FSDataType]] =
IO.blocking {
val f = p.toFile()
if (f.exists()) Some {
if (f.isDirectory()) PlatformIO.FSDataType.Dir
else PlatformIO.FSDataType.File
}
)
else None
}

def resolve(p: Path, c: String): Path = p.resolve(c)

def read[A <: GeneratedMessage](
path: Path
Expand Down Expand Up @@ -106,18 +100,16 @@ object IOPlatformIO extends PlatformIO[IO, JPath] {
IO.fromTry(ProtoConverter.packagesToProto(packages))
.flatMap(write(_, path))

def unfoldDir: Option[Path => IO[Option[IO[List[Path]]]]] = Some {
(path: Path) =>
IO.blocking {
val f = path.toFile
def unfoldDir(path: Path): IO[Option[IO[List[Path]]]] =
IO.blocking {
val f = path.toFile

if (f.isDirectory()) {
Some(IO.blocking {
f.listFiles.iterator.map(_.toPath).toList
})
} else None
}
}
if (f.isDirectory()) {
Some(IO.blocking {
f.listFiles.iterator.map(_.toPath).toList
})
} else None
}

def hasExtension(str: String): Path => Boolean = { (path: Path) =>
path.toString.endsWith(str)
Expand All @@ -142,7 +134,7 @@ object IOPlatformIO extends PlatformIO[IO, JPath] {
}
}

def print(str: String): IO[Unit] =
def println(str: String): IO[Unit] =
IO.println(str)

def writeStdout(doc: Doc): IO[Unit] =
Expand Down
41 changes: 24 additions & 17 deletions cliJS/src/main/scala/org/bykn/bosatsu/Fs2PlatformIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,21 @@ object Fs2PlatformIO extends PlatformIO[IO, Path] {

private val FilesIO = Files.forIO

def readPath(p: Path): IO[String] =
def readUtf8(p: Path): IO[String] =
FilesIO.readUtf8(p).compile.string

def fsDataType(p: Path): IO[Option[PlatformIO.FSDataType]] =
FilesIO.exists(p, followLinks = true)
.flatMap {
case false => IO.pure(None)
case true =>
FilesIO.isDirectory(p, followLinks = true)
.map {
case true => Some(PlatformIO.FSDataType.Dir)
case false => Some(PlatformIO.FSDataType.File)
}
}

def readPackages(paths: List[Path]): IO[List[Package.Typed[Unit]]] =
paths.parTraverse { path =>
for {
Expand Down Expand Up @@ -66,6 +78,8 @@ object Fs2PlatformIO extends PlatformIO[IO, Path] {
else None
}

def resolve(p: Path, c: String): Path = p.resolve(c)

/** Modules optionally have the capability to combine paths into a tree
*/
val resolvePath: Option[(Path, PackageName) => IO[Option[Path]]] = Some {
Expand All @@ -84,18 +98,15 @@ object Fs2PlatformIO extends PlatformIO[IO, Path] {
*
* if the given path is a directory, return Some and all the first children.
*/
def unfoldDir: Option[Path => IO[Option[IO[List[Path]]]]] = Some {
(path: Path) => {
FilesIO.isDirectory(path, followLinks = true)
.map {
case true => Some {
// create a list of children
FilesIO.list(path).compile.toList
}
case false => None
def unfoldDir(path: Path): IO[Option[IO[List[Path]]]] =
FilesIO.isDirectory(path, followLinks = true)
.map {
case true => Some {
// create a list of children
FilesIO.list(path).compile.toList
}
}
}
case false => None
}

def hasExtension(str: String): Path => Boolean =
{ (path: Path) => path.extName == str }
Expand All @@ -114,11 +125,7 @@ object Fs2PlatformIO extends PlatformIO[IO, Path] {
.compile
.drain

def resolve(base: Path, p: List[String]): Path =
p.foldLeft(base)(_.resolve(_))

// this is println actually
def print(str: String): IO[Unit] =
def println(str: String): IO[Unit] =
IO.println(str)

def writeInterfaces(
Expand Down
92 changes: 42 additions & 50 deletions core/src/main/scala/org/bykn/bosatsu/MainModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
paths
.traverse { path =>
val defaultPack = packRes.packageNameFor(path)
readPath(path).map { str =>
readUtf8(path).map { str =>
parseStart(Package.headerParser(defaultPack), path, str)
.map { case (_, pp) => (path, pp) }
}
Expand Down Expand Up @@ -189,7 +189,7 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
packRes
.pathFor(search)
.flatMap(_.traverse { path =>
readPath(path).map((path, _))
readUtf8(path).map((path, _))
})
}

Expand Down Expand Up @@ -299,7 +299,7 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
p: P0[A],
path: Path
): IO[Either[Throwable, ValidatedNel[ParseError, (LocationMap, A)]]] =
readPath(path).attempt
readUtf8(path).attempt
.map(_.map(parseString(p, path, _)))

/** like typecheck, but a no-op for empty lists
Expand Down Expand Up @@ -520,7 +520,7 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
def read = moduleIOMonad.pure(asString)
}
case class FromPath(path: Path) extends JsonInput {
def read = readPath(path)
def read = readUtf8(path)
}
}

Expand Down Expand Up @@ -666,35 +666,31 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
.orEmpty
.map(paths => paths.foldMap(PathGen.Direct[IO, Path](_): PathGen))

unfoldDir match {
case None => direct
case Some(unfold) =>
val select = hasExtension(ext)
val child1 = Opts
.options[Path](arg + "_dir", help = s"all $help in directory")
.orEmpty
.map { paths =>
paths.foldMap(
PathGen
.ChildrenOfDir[IO, Path](_, select, false, unfold): PathGen
)
}
val childMany = Opts
.options[Path](
arg + "_all_subdir",
help = s"all $help recursively in all directories"
)
.orEmpty
.map { paths =>
paths.foldMap(
PathGen
.ChildrenOfDir[IO, Path](_, select, true, unfold): PathGen
)
}
val select = hasExtension(ext)
val child1 = Opts
.options[Path](arg + "_dir", help = s"all $help in directory")
.orEmpty
.map { paths =>
paths.foldMap(
PathGen
.ChildrenOfDir[IO, Path](_, select, false, unfoldDir(_)): PathGen
)
}
val childMany = Opts
.options[Path](
arg + "_all_subdir",
help = s"all $help recursively in all directories"
)
.orEmpty
.map { paths =>
paths.foldMap(
PathGen
.ChildrenOfDir[IO, Path](_, select, true, unfoldDir(_)): PathGen
)
}

(direct, child1, childMany).mapN { (a, b, c) =>
(a :: b :: c :: Nil).combineAll
}
(direct, child1, childMany).mapN { (a, b, c) =>
(a :: b :: c :: Nil).combineAll
}
}
private val srcs =
Expand All @@ -712,21 +708,17 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
help = "for implicit package names, consider these paths as roots"
)
private val packSearch =
resolvePath match {
case None => Opts(None)
case some @ Some(_) =>
Opts
.flag(
"search",
help =
"if set, we search the package_roots for imports not explicitly given"
)
.orFalse
.map {
case true => some
case false => None
}
}
Opts
.flag(
"search",
help =
"if set, we search the package_roots for imports not explicitly given"
)
.orFalse
.map {
case true => Some((p, pn) => resolveFile(p, pn))
case false => None
}

private val packRes: Opts[PackageResolver] =
(packRoot
Expand Down Expand Up @@ -774,7 +766,7 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
for {
pn <- inputs.packMap(this, Nil, errColor)
(packs, names) = pn
optString <- generator.traverse(readPath)
optString <- generator.traverse(readUtf8)
dataTry = optString.transpiler.renderAll(packs, optString.args)
data <- moduleIOMonad.fromTry(dataTry)
} yield Output.TranspileOut(data, outDir)
Expand Down Expand Up @@ -1334,12 +1326,12 @@ abstract class MainModule[IO[_], Path](val platformIO: PlatformIO[IO, Path]) {
val testReport = Test.outputFor(evalTest, color)
val success = !hasMissing && (testReport.fails == 0)
val code = if (success) ExitCode.Success else ExitCode.Error
print(testReport.doc.render(80)).as(code)
println(testReport.doc.render(80)).as(code)
case Output.EvaluationResult(_, tpe, resDoc) =>
val tDoc = rankn.Type.fullyResolvedDocument.document(tpe)
val doc =
resDoc.value + (Doc.lineOrEmpty + Doc.text(": ") + tDoc).nested(4)
print(doc.render(100)).as(ExitCode.Success)
println(doc.render(100)).as(ExitCode.Success)
case Output.JsonOutput(json, pathOpt) =>
writeOut(json.toDoc, pathOpt)
.as(ExitCode.Success)
Expand Down
Loading

0 comments on commit 34aa4a8

Please sign in to comment.