feat: introduce cats-effect and io

This commit is contained in:
Jonny
2025-02-28 15:18:24 +00:00
parent 8b3e9b8380
commit 345c652a57
3 changed files with 53 additions and 56 deletions

View File

@@ -6,8 +6,12 @@ import parsley.{Failure, Success}
import scopt.OParser
import java.io.File
import java.io.PrintStream
import cats.implicits._
import cats.effect.unsafe.implicits.global
import assemblyIR as asm
import cats.effect.IO
import cats.effect.IOApp
case class CliConfig(
file: File = new File(".")
@@ -36,30 +40,26 @@ val cliParser = {
def frontend(
contents: String
)(using stdout: PrintStream): Either[microWacc.Program, Int] = {
parser.parse(contents) match {
)(using stdout: PrintStream): IO[microWacc.Program] = {
IO(parser.parse(contents)).flatMap {
case Failure(msg) => IO.raiseError(new RuntimeException(msg))
case Success(prog) =>
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
val (names, funcs) = renamer.rename(prog)
given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors)
val typedProg = typeChecker.check(prog)
if (errors.result.nonEmpty) {
given errorContent: String = contents
Right(
errors.result
.map { error =>
printError(error)
error match {
case _: Error.InternalError => 201
case _ => 200
}
}
.max()
)
} else Left(typedProg)
case Failure(msg) =>
stdout.println(msg)
Right(100)
given errors: mutable.Builder[Error, List[Error]] = List.newBuilder
given errorContent: String = contents
val (names, funcs) = renamer.rename(prog)
given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors)
val typedProg = typeChecker.check(prog)
if (errors.result.isEmpty) IO.pure(typedProg)
else {
errors.result.foreach(printError)
IO.raiseError(new RuntimeException("Compilation failed with code: " + errors.result.view.map {
case _: Error.InternalError => 201
case _ => 200
}.max))
}
}
}
@@ -67,26 +67,27 @@ val s = "enter an integer to echo"
def backend(typedProg: microWacc.Program): Chain[asm.AsmLine] =
asmGenerator.generateAsm(typedProg)
def compile(filename: String, outFile: Option[File] = None)(using
stdout: PrintStream = Console.out
): Int =
frontend(os.read(os.Path(filename))) match {
case Left(typedProg) =>
val asmFile = outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s"))
val asm = backend(typedProg)
writer.writeTo(asm, PrintStream(asmFile))
0
case Right(exitCode) => exitCode
}
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"))
): IO[Int] =
for {
contents <- IO(os.read(os.Path(filename)))
typedProg <- frontend(contents)
_ <- IO {
writer.writeTo(
backend(typedProg),
PrintStream(outFile.getOrElse(File(filename.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"))
)
}
}

View File

@@ -7,6 +7,7 @@ import java.io.File
import sys.process._
import java.io.PrintStream
import scala.io.Source
import cats.effect.unsafe.implicits.global
class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
val files =
@@ -29,7 +30,7 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll {
given stdout: PrintStream = PrintStream(File(baseFilename + ".out"))
s"$filename" should "be compiled with correct result" in {
val result = compile(filename)
val result = compile(filename).unsafeRunSync()
assert(expectedResult.contains(result))
}