feat: introduction of logger to eliminate printstreams
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
//> 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 org.typelevel::log4cats-slf4j::2.7.0
|
||||
//> using dep org.slf4j:slf4j-simple:2.0.17
|
||||
//> using test.dep org.scalatest::scalatest::3.2.19
|
||||
//> using dep org.typelevel::cats-effect-testing-scalatest::1.6.0
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import scala.collection.mutable
|
||||
import cats.data.Chain
|
||||
import parsley.{Failure, Success}
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import cats.implicits.*
|
||||
|
||||
import cats.effect.IO
|
||||
@@ -14,6 +13,9 @@ import com.monovore.decline._
|
||||
import com.monovore.decline.effect._
|
||||
import com.monovore.decline.Argument
|
||||
|
||||
import org.typelevel.log4cats.slf4j.Slf4jLogger
|
||||
import org.typelevel.log4cats.Logger
|
||||
|
||||
import assemblyIR as asm
|
||||
|
||||
given Argument[File] = Argument.from("file") { str =>
|
||||
@@ -32,30 +34,33 @@ val cliCommand: Command[File] =
|
||||
Opts.argument[File]("file")
|
||||
}
|
||||
|
||||
given logger: Logger[IO] = Slf4jLogger.getLogger[IO]
|
||||
|
||||
def frontend(
|
||||
contents: String
|
||||
)(using stdout: PrintStream): IO[Either[Int, microWacc.Program]] = {
|
||||
IO(parser.parse(contents)).map {
|
||||
): IO[Either[Int, microWacc.Program]] = {
|
||||
IO(parser.parse(contents)).flatMap {
|
||||
case Failure(msg) =>
|
||||
stdout.println(msg)
|
||||
Left(100) // Syntax error
|
||||
logger.error(s"Syntax error: $msg").as(Left(100))
|
||||
|
||||
case Success(prog) =>
|
||||
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) Right(typedProg)
|
||||
if (errors.result.isEmpty) IO.pure(Right(typedProg))
|
||||
else {
|
||||
errors.result.foreach(printError)
|
||||
Left(errors.result.view.map {
|
||||
val exitCode = errors.result.view.map {
|
||||
case _: Error.InternalError => 201
|
||||
case _ => 200
|
||||
}.max)
|
||||
}.max
|
||||
|
||||
logger.error(s"Semantic errors:\n${errors.result.mkString("\n")}") *> IO.pure(
|
||||
Left(exitCode)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,21 +69,18 @@ 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
|
||||
): IO[Int] =
|
||||
def compile(filename: String, outFile: Option[File] = None): IO[Int] =
|
||||
for {
|
||||
contents <- IO(os.read(os.Path(filename)))
|
||||
_ <- logger.info(s"Compiling file: $filename")
|
||||
result <- frontend(contents)
|
||||
exitCode <- result.fold(
|
||||
IO.pure, // Return error code (handles Left case)
|
||||
code => logger.error(s"Compilation failed for $filename\nExit code: $code").as(code),
|
||||
typedProg =>
|
||||
IO {
|
||||
writer.writeTo(
|
||||
backend(typedProg),
|
||||
PrintStream(outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s")))
|
||||
)
|
||||
}.as(0) // Compilation succeeded
|
||||
val outputFile = outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s"))
|
||||
writer.writeTo(backend(typedProg), outputFile) *> logger
|
||||
.info(s"Compilation succeeded: $filename")
|
||||
.as(0)
|
||||
)
|
||||
} yield exitCode
|
||||
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
package wacc
|
||||
|
||||
import java.io.PrintStream
|
||||
import cats.effect.Resource
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.io.File
|
||||
import java.io.BufferedWriter
|
||||
import java.io.FileWriter
|
||||
import cats.data.Chain
|
||||
import cats.effect.IO
|
||||
|
||||
import org.typelevel.log4cats.Logger
|
||||
|
||||
object writer {
|
||||
import assemblyIR._
|
||||
|
||||
def writeTo(asmList: Chain[AsmLine], printStream: PrintStream): Unit = {
|
||||
asmList.iterator.foreach(printStream.println)
|
||||
}
|
||||
def writeTo(asmList: Chain[AsmLine], outputFile: File)(using logger: Logger[IO]): IO[Unit] =
|
||||
Resource
|
||||
.fromAutoCloseable {
|
||||
IO(BufferedWriter(FileWriter(outputFile, StandardCharsets.UTF_8)))
|
||||
}
|
||||
.use { writer =>
|
||||
IO {
|
||||
asmList.iterator.foreach(line => writer.write(line.toString + "\n"))
|
||||
writer.flush() // TODO: NECESSARY OR NOT?
|
||||
} *> logger.info(s"Wrote assembly to ${outputFile.getAbsolutePath}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.scalatest.freespec.AsyncFreeSpec
|
||||
import cats.effect.testing.scalatest.AsyncIOSpec
|
||||
import java.io.File
|
||||
import sys.process._
|
||||
import java.io.PrintStream
|
||||
import scala.io.Source
|
||||
import cats.effect.IO
|
||||
import wacc.{compile as compileWacc}
|
||||
@@ -30,7 +29,6 @@ class ParallelExamplesSpec extends AsyncFreeSpec with AsyncIOSpec with BeforeAnd
|
||||
|
||||
forEvery(files) { (filename, expectedResult) =>
|
||||
val baseFilename = filename.stripSuffix(".wacc")
|
||||
given stdout: PrintStream = PrintStream(File(baseFilename + ".out"))
|
||||
|
||||
s"$filename" - {
|
||||
"should be compiled with correct result" in {
|
||||
|
||||
Reference in New Issue
Block a user