2024-09-04 21:50:13 +02:00
|
|
|
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)
|
2024-10-22 01:21:02 +02:00
|
|
|
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.
|
2024-11-24 13:05:11 +01:00
|
|
|
-- 6 - Register allocation error.
|
2024-09-04 21:50:13 +02:00
|
|
|
|
|
|
|
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 =
|
2024-11-24 13:05:11 +01:00
|
|
|
let makeObject = elfObject output . riscv32Elf . generateRiscV
|
|
|
|
in either (printAndExit 6) makeObject
|
|
|
|
$ allocate riscVConfiguration
|
|
|
|
$ glue symbolTable program
|
2024-10-31 22:19:48 +01:00
|
|
|
printAndExit :: Show b => forall a. Int -> b -> IO a
|
|
|
|
printAndExit failureCode e = print e >> exitWith (ExitFailure failureCode)
|