Browse Source
Hack assembler definitions are now in separate module. This will be handy when I implement VM compilermaster
4 changed files with 187 additions and 145 deletions
@ -0,0 +1,62 @@ |
|||||||
|
|
||||||
|
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" ) |
||||||
@ -1,26 +0,0 @@ |
|||||||
name: hackasm |
|
||||||
version: 0.1.0.0 |
|
||||||
-- synopsis: |
|
||||||
-- description: |
|
||||||
homepage: https://github.com/githubuser/hackasm#readme |
|
||||||
license: BSD3 |
|
||||||
license-file: LICENSE |
|
||||||
author: Author name here |
|
||||||
maintainer: example@example.com |
|
||||||
copyright: 2021 Author name here |
|
||||||
category: Web |
|
||||||
build-type: Simple |
|
||||||
cabal-version: >=1.10 |
|
||||||
extra-source-files: README.md |
|
||||||
|
|
||||||
executable hackasm |
|
||||||
hs-source-dirs: src |
|
||||||
main-is: Main.hs |
|
||||||
default-language: Haskell2010 |
|
||||||
build-depends: base >= 4.7 && < 5 |
|
||||||
, text |
|
||||||
, megaparsec |
|
||||||
, optparse-applicative |
|
||||||
, containers |
|
||||||
, bytestring |
|
||||||
, binary |
|
||||||
@ -0,0 +1,37 @@ |
|||||||
|
name: nand2tetris |
||||||
|
version: 0.1.0.0 |
||||||
|
-- synopsis: |
||||||
|
-- description: |
||||||
|
homepage: https://c.asakul.ru/asakul/nand2tetris |
||||||
|
license: BSD3 |
||||||
|
license-file: LICENSE |
||||||
|
author: Denis Tereshkin |
||||||
|
maintainer: denis@kasan.ws |
||||||
|
copyright: 2021 Denis Tereshkin |
||||||
|
category: Web |
||||||
|
build-type: Simple |
||||||
|
cabal-version: >=1.10 |
||||||
|
extra-source-files: README.md |
||||||
|
|
||||||
|
executable hackasm |
||||||
|
hs-source-dirs: app |
||||||
|
main-is: HackAsm.hs |
||||||
|
default-language: Haskell2010 |
||||||
|
build-depends: base >= 4.7 && < 5 |
||||||
|
, nand2tetris |
||||||
|
, text |
||||||
|
, megaparsec |
||||||
|
, optparse-applicative |
||||||
|
, containers |
||||||
|
, bytestring |
||||||
|
|
||||||
|
library |
||||||
|
hs-source-dirs: src |
||||||
|
default-language: Haskell2010 |
||||||
|
exposed-modules: Nand2Tetris.Hack |
||||||
|
build-depends: base >= 4.7 && < 5 |
||||||
|
, text |
||||||
|
, megaparsec |
||||||
|
, containers |
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in new issue