diff --git a/src/main/wacc/Main.scala b/src/main/wacc/Main.scala index 8bf7d3b..71a65bb 100644 --- a/src/main/wacc/Main.scala +++ b/src/main/wacc/Main.scala @@ -40,26 +40,29 @@ val cliParser = { def frontend( contents: String -)(using stdout: PrintStream): IO[microWacc.Program] = { - IO(parser.parse(contents)).flatMap { - case Failure(msg) => IO.raiseError(new RuntimeException(msg)) +)(using stdout: PrintStream): IO[Either[Int, microWacc.Program]] = { + IO(parser.parse(contents)).map { + case Failure(msg) => + stdout.println(msg) + Left(100) // Syntax error + case Success(prog) => - given errors: mutable.Builder[Error, List[Error]] = List.newBuilder - given errorContent: String = contents + 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 (names, funcs) = renamer.rename(prog) + given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors) - val typedProg = typeChecker.check(prog) + 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)) - } + if (errors.result.isEmpty) Right(typedProg) + else { + errors.result.foreach(printError) + Left(errors.result.view.map { + case _: Error.InternalError => 201 + case _ => 200 + }.max) + } } } @@ -72,15 +75,19 @@ def compile(filename: String, outFile: Option[File] = None)(using stdout: PrintStream = Console.out ): 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"))) - ) - } -} yield 0 + contents <- IO(os.read(os.Path(filename))) + result <- frontend(contents) + exitCode <- result match { + case Left(code) => IO.pure(code) // Return error code + case Right(typedProg) => + IO { + writer.writeTo( + backend(typedProg), + PrintStream(outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s"))) + ) + }.as(0) // Compilation succeeded + } + } yield exitCode object Main extends IOApp.Simple { override def run: IO[Unit] =