feat: functional single-threaded imports

This commit is contained in:
2025-03-13 22:24:41 +00:00
parent ee54a1201c
commit 6e592e7d9b
10 changed files with 166 additions and 155 deletions

View File

@@ -71,21 +71,23 @@ val outputOpt: Opts[Option[Path]] =
def frontend(
contents: String,
file: File
): Either[NonEmptyList[Error], microWacc.Program] =
): IO[Either[NonEmptyList[Error], microWacc.Program]] =
parser.parse(contents) match {
case Failure(msg) => Left(NonEmptyList.one(Error.SyntaxError(file, msg)))
case Failure(msg) => IO.pure(Left(NonEmptyList.one(Error.SyntaxError(file, msg))))
case Success(fn) =>
val ast.PartialProgram(_, prog) = fn(file)
val partialProg = fn(file)
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)
for {
(prog, renameErrors) <- renamer.rename(partialProg)
_ = errors.addAll(renameErrors.toList)
typedProg = typeChecker.check(prog, errors)
NonEmptyList.fromList(errors.result) match {
case Some(errors) => Left(errors)
case None => Right(typedProg)
}
res = NonEmptyList.fromList(errors.result) match {
case Some(errors) => Left(errors)
case None => Right(typedProg)
}
} yield res
}
def backend(typedProg: microWacc.Program): Chain[asm.AsmLine] =
@@ -109,23 +111,25 @@ def compile(
logger.info(s"Success: ${outputPath.toAbsolutePath}")
def processProgram(contents: String, file: File, outDir: Path): IO[Int] =
frontend(contents, file) match {
case Left(errors) =>
val code = errors.map(err => err.exitCode).toList.min
given errorContent: String = contents
val errorMsg = errors.map(formatError).toIterable.mkString("\n")
for {
_ <- logAction(s"Compilation failed for $filePath\nExit code: $code")
_ <- IO.blocking(
// Explicit println since we want this to always show without logger thread info e.t.c.
println(s"Compilation failed for ${file.getCanonicalPath}:\n$errorMsg")
)
} yield code
for {
frontendResult <- frontend(contents, file)
res <- frontendResult match {
case Left(errors) =>
val code = errors.map(err => err.exitCode).toList.min
val errorMsg = errors.map(formatError).toIterable.mkString("\n")
for {
_ <- logAction(s"Compilation failed for $filePath\nExit code: $code")
_ <- IO.blocking(
// Explicit println since we want this to always show without logger thread info e.t.c.
println(s"Compilation failed for ${file.getCanonicalPath}:\n$errorMsg")
)
} yield code
case Right(typedProg) =>
val outputFile = outDir.resolve(filePath.getFileName.toString.stripSuffix(".wacc") + ".s")
writeOutputFile(typedProg, outputFile).as(SUCCESS)
}
case Right(typedProg) =>
val outputFile = outDir.resolve(filePath.getFileName.toString.stripSuffix(".wacc") + ".s")
writeOutputFile(typedProg, outputFile).as(SUCCESS)
}
} yield res
for {
contents <- readSourceFile