{- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -} module Main ( main ) where import Language.Elna.Driver ( Driver(..) , IntermediateStage(..) , drive ) import Language.Elna.Object.ElfCoder (elfObject) 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) import Text.Megaparsec (runParser, errorBundlePretty) import qualified Data.Text.IO as Text 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. -- 6 - Register allocation error. main :: IO () main = drive >>= withCommandLine where withCommandLine driver@Driver{ input } = catch (Text.readFile input) (printAndExit 2 :: IOException -> IO a) >>= withParsedInput driver . runParser programP input withParsedInput driver@Driver{ intermediateStage } (Right program) | Just ParseStage <- intermediateStage = pure () | otherwise = either (printAndExit 4) (withSymbolTable driver program) $ nameAnalysis program withParsedInput _ (Left errorBundle) = putStrLn (errorBundlePretty errorBundle) >> exitWith (ExitFailure 3) withSymbolTable driver@Driver{ intermediateStage } program symbolTable | Just typeError <- typeAnalysis symbolTable program = printAndExit 5 typeError | Just ValidateStage <- intermediateStage = pure () | otherwise = either (printAndExit 6) (withTac driver) $ allocate riscVConfiguration symbolTable $ glue symbolTable program withTac Driver{ intermediateStage, output } tac | Just CodeGenStage <- intermediateStage = pure () | otherwise = elfObject output $ riscv32Elf $ generateRiscV tac printAndExit :: Show b => forall a. Int -> b -> IO a printAndExit failureCode e = print e >> exitWith (ExitFailure failureCode)