feat: functional single-threaded imports
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user