You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
2.5 KiB
62 lines
2.5 KiB
|
|
module Main (main) where |
|
|
|
import Control.Monad (forM_) |
|
import Data.Bits (testBit) |
|
import Data.Foldable (foldl', foldr) |
|
import qualified Data.Map.Strict as M |
|
import qualified Data.Text as T |
|
import qualified Data.Text.IO as TIO |
|
import Nand2Tetris.Hack (AsmLine (LineInstruction), addLabels, |
|
addVars, compile, defaultVars, |
|
hackParser) |
|
import Options.Applicative (execParser, fullDesc, header, help, |
|
helper, info, long, metavar, progDesc, |
|
short, strOption, (<**>)) |
|
import System.IO (IOMode (WriteMode), hPutStrLn, withFile) |
|
import Text.Megaparsec (runParser) |
|
import Text.Megaparsec.Error (ParseErrorBundle, |
|
ShowErrorComponent (showErrorComponent), |
|
errorBundlePretty) |
|
|
|
data Options = |
|
Options |
|
{ |
|
inputFile :: FilePath, |
|
outputFile :: FilePath |
|
} |
|
|
|
main :: IO () |
|
main = do |
|
options <- execParser opts |
|
programText <- TIO.readFile (inputFile options) |
|
let result = runParser hackParser (inputFile options) programText |
|
case result of |
|
Left err -> putStrLn $ errorBundlePretty err |
|
Right parsed -> do |
|
let labels = addLabels M.empty parsed |
|
let vars = addVars defaultVars labels parsed |
|
print vars |
|
let compiled = compile labels vars $ foldr addInstr [] parsed |
|
case compiled of |
|
Left err -> putStrLn $ "Error: " <> T.unpack err |
|
Right program -> withFile (outputFile options) WriteMode $ \h -> forM_ program (\x -> hPutStrLn h (printInstruction x)) |
|
where |
|
printInstruction w = concatMap (\x -> if testBit w x then "1" else "0") $ reverse [0..15] |
|
regVars = defaultVars |
|
addInstr (LineInstruction instr) is = instr : is |
|
addInstr _ is = is |
|
|
|
opts = info (hackAsmOptParser <**> helper) |
|
( fullDesc |
|
<> progDesc "Compiles a file with Hack assembly instructions to Hask binary code" |
|
<> header "hackasm - assembler for hack CPU (nand2tetris)" ) |
|
hackAsmOptParser = Options <$> |
|
strOption ( long "input" |
|
<> short 'i' |
|
<> metavar "FILENAME" |
|
<> help "Input file" ) <*> |
|
strOption ( long "output" |
|
<> short 'o' |
|
<> metavar "FILENAME" |
|
<> help "Output file" )
|
|
|