feat: introduce cats-effect and io
This commit is contained in:
@@ -5,23 +5,18 @@
|
|||||||
//> using dep com.github.j-mie6::parsley::5.0.0-M10
|
//> using dep com.github.j-mie6::parsley::5.0.0-M10
|
||||||
//> using dep com.github.j-mie6::parsley-cats::1.5.0
|
//> using dep com.github.j-mie6::parsley-cats::1.5.0
|
||||||
//> using dep com.lihaoyi::os-lib::0.11.4
|
//> using dep com.lihaoyi::os-lib::0.11.4
|
||||||
|
//> using dep org.typelevel::cats-core::2.13.0
|
||||||
|
//> using dep org.typelevel::cats-effect::3.5.7
|
||||||
|
//> using dep com.monovore::decline::2.5.0
|
||||||
|
//> using dep com.monovore::decline-effect::2.5.0
|
||||||
//> using dep com.github.scopt::scopt::4.1.0
|
//> using dep com.github.scopt::scopt::4.1.0
|
||||||
//> using test.dep org.scalatest::scalatest::3.2.19
|
//> using test.dep org.scalatest::scalatest::3.2.19
|
||||||
|
|
||||||
// these are all sensible defaults to catch annoying issues
|
// sensible defaults for warnings and compiler checks
|
||||||
//> using options -deprecation -unchecked -feature
|
//> using options -deprecation -unchecked -feature
|
||||||
//> using options -Wimplausible-patterns -Wunused:all
|
//> using options -Wimplausible-patterns -Wunused:all
|
||||||
//> using options -Yexplicit-nulls -Wsafe-init -Xkind-projector:underscores
|
//> using options -Yexplicit-nulls -Wsafe-init -Xkind-projector:underscores
|
||||||
|
|
||||||
// these will help ensure you have access to the latest parsley releases
|
// repositories for pre-release versions if needed
|
||||||
// even before they land on maven proper, or snapshot versions, if necessary.
|
//> using repositories sonatype-s01:releases
|
||||||
// just in case they cause problems, however, keep them turned off unless you
|
//> using repositories sonatype-s01:snapshots
|
||||||
// specifically need them.
|
|
||||||
// using repositories sonatype-s01:releases
|
|
||||||
// using repositories sonatype-s01:snapshots
|
|
||||||
|
|
||||||
// these are flags used by Scala native: if you aren't using scala-native, then they do nothing
|
|
||||||
// lto-thin has decent linking times, and release-fast does not too much optimisation.
|
|
||||||
// using nativeLto thin
|
|
||||||
// using nativeGc commix
|
|
||||||
// using nativeMode release-fast
|
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import parsley.{Failure, Success}
|
|||||||
import scopt.OParser
|
import scopt.OParser
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
import cats.implicits._
|
||||||
|
import cats.effect.unsafe.implicits.global
|
||||||
|
|
||||||
import assemblyIR as asm
|
import assemblyIR as asm
|
||||||
|
import cats.effect.IO
|
||||||
|
import cats.effect.IOApp
|
||||||
|
|
||||||
case class CliConfig(
|
case class CliConfig(
|
||||||
file: File = new File(".")
|
file: File = new File(".")
|
||||||
@@ -36,30 +40,26 @@ val cliParser = {
|
|||||||
|
|
||||||
def frontend(
|
def frontend(
|
||||||
contents: String
|
contents: String
|
||||||
)(using stdout: PrintStream): Either[microWacc.Program, Int] = {
|
)(using stdout: PrintStream): IO[microWacc.Program] = {
|
||||||
parser.parse(contents) match {
|
IO(parser.parse(contents)).flatMap {
|
||||||
|
case Failure(msg) => IO.raiseError(new RuntimeException(msg))
|
||||||
case Success(prog) =>
|
case Success(prog) =>
|
||||||
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
|
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
|
||||||
val (names, funcs) = renamer.rename(prog)
|
given errorContent: String = contents
|
||||||
given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors)
|
|
||||||
val typedProg = typeChecker.check(prog)
|
val (names, funcs) = renamer.rename(prog)
|
||||||
if (errors.result.nonEmpty) {
|
given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors)
|
||||||
given errorContent: String = contents
|
|
||||||
Right(
|
val typedProg = typeChecker.check(prog)
|
||||||
errors.result
|
|
||||||
.map { error =>
|
if (errors.result.isEmpty) IO.pure(typedProg)
|
||||||
printError(error)
|
else {
|
||||||
error match {
|
errors.result.foreach(printError)
|
||||||
case _: Error.InternalError => 201
|
IO.raiseError(new RuntimeException("Compilation failed with code: " + errors.result.view.map {
|
||||||
case _ => 200
|
case _: Error.InternalError => 201
|
||||||
}
|
case _ => 200
|
||||||
}
|
}.max))
|
||||||
.max()
|
}
|
||||||
)
|
|
||||||
} else Left(typedProg)
|
|
||||||
case Failure(msg) =>
|
|
||||||
stdout.println(msg)
|
|
||||||
Right(100)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,26 +67,27 @@ val s = "enter an integer to echo"
|
|||||||
def backend(typedProg: microWacc.Program): Chain[asm.AsmLine] =
|
def backend(typedProg: microWacc.Program): Chain[asm.AsmLine] =
|
||||||
asmGenerator.generateAsm(typedProg)
|
asmGenerator.generateAsm(typedProg)
|
||||||
|
|
||||||
|
|
||||||
def compile(filename: String, outFile: Option[File] = None)(using
|
def compile(filename: String, outFile: Option[File] = None)(using
|
||||||
stdout: PrintStream = Console.out
|
stdout: PrintStream = Console.out
|
||||||
): Int =
|
): IO[Int] =
|
||||||
frontend(os.read(os.Path(filename))) match {
|
for {
|
||||||
case Left(typedProg) =>
|
contents <- IO(os.read(os.Path(filename)))
|
||||||
val asmFile = outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s"))
|
typedProg <- frontend(contents)
|
||||||
val asm = backend(typedProg)
|
_ <- IO {
|
||||||
writer.writeTo(asm, PrintStream(asmFile))
|
writer.writeTo(
|
||||||
0
|
backend(typedProg),
|
||||||
case Right(exitCode) => exitCode
|
PrintStream(outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s")))
|
||||||
}
|
|
||||||
|
|
||||||
def main(args: Array[String]): Unit =
|
|
||||||
OParser.parse(cliParser, args, CliConfig()) match {
|
|
||||||
case Some(config) =>
|
|
||||||
System.exit(
|
|
||||||
compile(
|
|
||||||
config.file.getAbsolutePath,
|
|
||||||
outFile = Some(File(".", config.file.getName.stripSuffix(".wacc") + ".s"))
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
case None =>
|
|
||||||
}
|
}
|
||||||
|
} yield 0
|
||||||
|
|
||||||
|
object Main extends IOApp.Simple {
|
||||||
|
override def run: IO[Unit] =
|
||||||
|
OParser.parse(cliParser, sys.env.getOrElse("WACC_ARGS", "").split(" "), CliConfig()).traverse_ { config =>
|
||||||
|
compile(
|
||||||
|
config.file.getAbsolutePath,
|
||||||
|
outFile = Some(File(".", config.file.getName.stripSuffix(".wacc") + ".s"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.io.File
|
|||||||
import sys.process._
|
import sys.process._
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
|
import cats.effect.unsafe.implicits.global
|
||||||
|
|
||||||
class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
||||||
val files =
|
val files =
|
||||||
@@ -29,7 +30,7 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
|
|||||||
given stdout: PrintStream = PrintStream(File(baseFilename + ".out"))
|
given stdout: PrintStream = PrintStream(File(baseFilename + ".out"))
|
||||||
|
|
||||||
s"$filename" should "be compiled with correct result" in {
|
s"$filename" should "be compiled with correct result" in {
|
||||||
val result = compile(filename)
|
val result = compile(filename).unsafeRunSync()
|
||||||
assert(expectedResult.contains(result))
|
assert(expectedResult.contains(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user