Browse Source

vmcompiler: fix static label generation

Apparently, static memaccess' take number as argument, which should
be converted to static label which is visible within one *.vm file,
but not from outside
master
Denis Tereshkin 4 years ago
parent
commit
51e465ee9c
  1. 4
      app/VMCompiler.hs
  2. 1
      nand2tetris.cabal
  3. 28
      src/Nand2Tetris/VM.hs

4
app/VMCompiler.hs

@ -3,6 +3,7 @@
module Main (main) where module Main (main) where
import Control.Monad (forM, forM_) import Control.Monad (forM, forM_)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO import qualified Data.Text.IO as TIO
import Nand2Tetris.Hack (AsmLine (..), HackInstruction (..), import Nand2Tetris.Hack (AsmLine (..), HackInstruction (..),
canonicalRepresentation) canonicalRepresentation)
@ -13,6 +14,7 @@ import Options.Applicative (argument, execParser, fullDesc, header,
help, helper, info, long, metavar, help, helper, info, long, metavar,
progDesc, short, some, str, strOption, progDesc, short, some, str, strOption,
(<**>)) (<**>))
import System.FilePath (takeBaseName)
import System.IO (IOMode (WriteMode), hPutStrLn, withFile) import System.IO (IOMode (WriteMode), hPutStrLn, withFile)
import Text.Megaparsec (runParser) import Text.Megaparsec (runParser)
import Text.Megaparsec.Error (ParseErrorBundle, import Text.Megaparsec.Error (ParseErrorBundle,
@ -31,7 +33,7 @@ main = do
options <- execParser opts options <- execParser opts
parsed <- mconcat <$> forM (inputFiles options) (\fname -> do parsed <- mconcat <$> forM (inputFiles options) (\fname -> do
txt <- TIO.readFile fname txt <- TIO.readFile fname
let result = runParser parseInstructions fname txt let result = runParser (parseInstructions (T.pack . takeBaseName $ fname)) fname txt
case result of case result of
Left err -> putStrLn (errorBundlePretty err) >> return [] Left err -> putStrLn (errorBundlePretty err) >> return []
Right p -> return p) Right p -> return p)

1
nand2tetris.cabal

@ -36,6 +36,7 @@ executable vmcompiler
, optparse-applicative , optparse-applicative
, containers , containers
, bytestring , bytestring
, filepath
library library
hs-source-dirs: src hs-source-dirs: src

28
src/Nand2Tetris/VM.hs

@ -123,15 +123,15 @@ instrAnnotation (VMFunction FReturn) = "return"
type Parser = Parsec Error T.Text type Parser = Parsec Error T.Text
parseInstructions :: Parser [VMInstruction] parseInstructions :: T.Text -> Parser [VMInstruction]
parseInstructions = many (sp *> parseInstruction <* sp) <* eof parseInstructions modName = many (sp *> parseInstruction modName <* sp) <* eof
where where
sp :: Parser () sp :: Parser ()
sp = L.space space1 (skipLineComment "//") empty sp = L.space space1 (skipLineComment "//") empty
parseInstruction :: Parser VMInstruction parseInstruction :: T.Text -> Parser VMInstruction
parseInstruction = parseInstruction modName =
try parseMemAccess <|> try (parseMemAccess modName) <|>
try parseArithmetic <|> try parseArithmetic <|>
try parseBranching <|> try parseBranching <|>
parseFunction parseFunction
@ -151,23 +151,23 @@ parseInstruction =
string "if-goto" *> space1 *> (BIfGoto <$> parseId) string "if-goto" *> space1 *> (BIfGoto <$> parseId)
] ]
parseMemAccess :: Parser VMInstruction parseMemAccess :: T.Text -> Parser VMInstruction
parseMemAccess = VMMemAccess <$> parseMemAccess modName = VMMemAccess <$>
parseAccessType <*> parseAccessType <*>
parseSegment parseSegment modName
parseAccessType :: Parser AccessType parseAccessType :: Parser AccessType
parseAccessType = try (string "push" >> space1 $> ACPush) <|> parseAccessType = try (string "push" >> space1 $> ACPush) <|>
(string "pop" >> space1 $> ACPop) (string "pop" >> space1 $> ACPop)
parseSegment :: Parser Segment parseSegment :: T.Text -> Parser Segment
parseSegment = parseSegment modName =
choice [ parseSegmentInt "local" SLocal, choice [ parseSegmentInt "local" SLocal,
parseSegmentInt "argument" SArgument, parseSegmentInt "argument" SArgument,
parseSegmentInt "this" SThis, parseSegmentInt "this" SThis,
parseSegmentInt "that" SThat, parseSegmentInt "that" SThat,
parseSegmentInt "constant" SConstant, parseSegmentInt "constant" SConstant,
(string "static" *> space1) *> (SStatic <$> (try parseId <|> parseStaticOffset)), (string "static" *> space1) *> (SStatic <$> (try parseId <|> parseStaticOffset modName)),
parseSegmentInt "pointer" SPointer, parseSegmentInt "pointer" SPointer,
parseSegmentInt "temp" STemp parseSegmentInt "temp" STemp
] ]
@ -179,10 +179,10 @@ parseInstruction =
hs <- many (alphaNumChar <|> char '.' <|> char '_') hs <- many (alphaNumChar <|> char '.' <|> char '_')
return $ T.pack (h : hs) return $ T.pack (h : hs)
parseStaticOffset :: Parser T.Text parseStaticOffset :: T.Text -> Parser T.Text
parseStaticOffset = do parseStaticOffset modName = do
h <- L.decimal h <- L.decimal
return $ "STATIC_" <> (T.pack . show) h return $ modName <> "." <> (T.pack . show) h
parseSegmentInt :: T.Text -> (Int -> Segment) -> Parser Segment parseSegmentInt :: T.Text -> (Int -> Segment) -> Parser Segment
parseSegmentInt sname f = try $ do parseSegmentInt sname f = try $ do

Loading…
Cancel
Save