elna/src/Main.hs

54 lines
2.1 KiB
Haskell
Raw Normal View History

module Main
( main
) where
2024-07-21 16:15:17 +02:00
2024-09-05 23:18:48 +02:00
import Language.Elna.CommandLine (CommandLine(..), commandLine, execParser)
import Language.Elna.Object.ElfCoder (elfObject)
2024-10-02 22:56:15 +02:00
import Language.Elna.Backend.Allocator (allocate)
import Language.Elna.Glue (glue)
import Language.Elna.Frontend.NameAnalysis (nameAnalysis)
import Language.Elna.Frontend.Parser (programP)
import Language.Elna.Frontend.TypeAnalysis (typeAnalysis)
import Language.Elna.RiscV.CodeGenerator (generateRiscV, riscVConfiguration)
import Language.Elna.RiscV.ElfWriter (riscv32Elf)
2024-09-05 23:18:48 +02:00
import Data.Maybe (fromMaybe)
import System.FilePath (replaceExtension, takeFileName)
2024-09-08 02:08:13 +02:00
import Text.Megaparsec (runParser, errorBundlePretty)
import qualified Data.Text.IO as Text
2024-10-31 22:19:48 +01:00
import System.Exit (ExitCode(..), exitWith)
import Control.Exception (IOException, catch)
-- * Error codes
--
-- 1 - Command line parsing failed and other errors.
-- 2 - The input could not be read.
-- 3 - Parse error.
-- 4 - Name analysis error.
-- 5 - Type error.
main :: IO ()
2024-10-31 22:19:48 +01:00
main = execParser commandLine >>= withCommandLine
2024-09-05 23:18:48 +02:00
where
withCommandLine CommandLine{..} =
2024-10-31 22:19:48 +01:00
let defaultOutputName = replaceExtension (takeFileName input) "o"
outputName = fromMaybe defaultOutputName output
in catch (Text.readFile input) (printAndExit 2 :: IOException -> IO a)
>>= withParsedInput outputName
2024-09-08 02:08:13 +02:00
. runParser programP input
2024-10-31 22:19:48 +01:00
withParsedInput output (Right program)
= either (printAndExit 4) (withSymbolTable output program)
$ nameAnalysis program
withParsedInput _ (Left errorBundle)
= putStrLn (errorBundlePretty errorBundle)
>> exitWith (ExitFailure 3)
withSymbolTable output program symbolTable
| Just typeError <- typeAnalysis symbolTable program =
printAndExit 5 typeError
| otherwise =
let instructions = generateRiscV
$ allocate riscVConfiguration
$ glue symbolTable program
in elfObject output $ riscv32Elf instructions
printAndExit :: Show b => forall a. Int -> b -> IO a
printAndExit failureCode e = print e >> exitWith (ExitFailure failureCode)