diff --git a/src/main/wacc/Main.scala b/src/main/wacc/Main.scala index 750a548..c85e2db 100644 --- a/src/main/wacc/Main.scala +++ b/src/main/wacc/Main.scala @@ -18,20 +18,35 @@ import org.typelevel.log4cats.slf4j.Slf4jLogger import org.typelevel.log4cats.Logger import assemblyIR as asm +import java.nio.file.Paths -// TODO: IO correctness, --greedy, parallelisable, and probably splitting this file up +/* +TODO: + 1) IO correctness + 2) --greedy, + 3) parallelised compilation + 4) splitting the file up and nicer refactoring + 5) logging could be removed + 6) errors can be handled more gracefully probably + */ given Argument[Path] = Argument.from("path") { str => - val path = Path.of(str) - ( - Either.cond(Files.exists(path), path, s"File '${path.toAbsolutePath}' does not exist"), - Either.cond( - Files.isRegularFile(path), - path, - s"File '${path.toAbsolutePath}' must be a regular file" - ), - Either.cond(path.toString.endsWith(".wacc"), path, "File must have .wacc extension") - ).mapN((_, _, _) => path).toValidatedNel + val path = + if (str.startsWith("~")) Paths.get(System.getProperty("user.home"), str.drop(1)) // Expand ~ + else Paths.get(str).toAbsolutePath.normalize() // TODO: normalize or not? + + if (path.toString.endsWith(".wacc")) { + ( + Either.cond(Files.exists(path), path, s"File '${path.toAbsolutePath}' does not exist"), + Either.cond( + Files.isRegularFile(path), + path, + s"File '${path.toAbsolutePath}' must be a regular file" + ) + ).mapN((_, _) => path).toValidatedNel + } else { + Right(path).toValidatedNel + } } given logger: Logger[IO] = Slf4jLogger.getLogger[IO] @@ -93,6 +108,15 @@ def compile(filePath: Path, outputDir: Option[Path], log: Boolean): IO[Int] = { IO.blocking { Files.createDirectories(outDir) outDir + }.handleErrorWith { + // TODO: I think this wont occur if a user runs with privileges but this must be checked + // TODO: this will return the ugly stack trace, one could refactor compileCommand to + case _: java.nio.file.AccessDeniedException => + IO.raiseError( + new Exception( + s"Permission denied: Cannot create directory '${outDir.toAbsolutePath}'. Try choosing a different output path or run as root." + ) + ) } // TODO: path, file , the names are confusing (when Path is the type but we are working with files) @@ -123,7 +147,12 @@ val compileCommand: Opts[IO[ExitCode]] = (filesOpt, logOpt, outputOpt).mapN { (files, log, outDir) => files .traverse { file => - compile(file.toAbsolutePath, outDir, log) + compile(file.toAbsolutePath, outDir, log).handleErrorWith { err => + // TODO: probably a more elegant way of doing this + // also, -1 arbitrary + // also - this outputs two messages for some reason + logger.error(err.getMessage) // *> IO.pure(ExitCode(-1)) + } } .map { exitCodes => if (exitCodes.exists(_ != 0))