summaryrefslogtreecommitdiff
path: root/projects/06/Assembler.hs
diff options
context:
space:
mode:
authorYuchen Pei <me@ypei.me>2017-12-20 15:41:29 +0100
committerYuchen Pei <me@ypei.me>2017-12-20 15:41:29 +0100
commite91518a763157acad4ed3542ac16a46223038c87 (patch)
tree0b068673be90d4797400eebe3ebb0682f6e02568 /projects/06/Assembler.hs
parent4e2796decd37f5b07a1be0da08aaa6f5b28142b5 (diff)
finished Project 6
Diffstat (limited to 'projects/06/Assembler.hs')
-rw-r--r--projects/06/Assembler.hs35
1 files changed, 23 insertions, 12 deletions
diff --git a/projects/06/Assembler.hs b/projects/06/Assembler.hs
index 3583121..fb69f07 100644
--- a/projects/06/Assembler.hs
+++ b/projects/06/Assembler.hs
@@ -3,14 +3,15 @@ import Data.Char (intToDigit)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.List.Split (splitOn, splitOneOf)
+import System.Environment (getArgs)
parseLine :: Map [Char] [Char] -> [Char] -> [Char]
parseLine table (x:xs)
- | x == '@' && (head xs `elem` ['0'..'9']) = (int2Bin16 $ read xs) ++ "\n"
- | x == '@' = table Map.! xs ++ "\n"
- | '=' `elem` (x:xs) && ';' `elem` (x:xs) = let [dest, comp, jump] = splitOneOf "=;" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ (parseJump jump) ++ "\n"
- | '=' `elem` (x:xs) = let [dest, comp] = splitOn "=" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ "000" ++ "\n"
- | ';' `elem` (x:xs) = let [comp, jump] = splitOn ";" (x:xs) in "111" ++ (parseComp comp) ++ "000" ++ (parseJump jump) ++ "\n"
+ | x == '@' && (head xs `elem` ['0'..'9']) = (int2Bin16 $ read xs)
+ | x == '@' = table Map.! xs
+ | '=' `elem` (x:xs) && ';' `elem` (x:xs) = let [dest, comp, jump] = splitOneOf "=;" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ (parseJump jump)
+ | '=' `elem` (x:xs) = let [dest, comp] = splitOn "=" (x:xs) in "111" ++ (parseComp comp) ++ (parseDest dest) ++ "000"
+ | ';' `elem` (x:xs) = let [comp, jump] = splitOn ";" (x:xs) in "111" ++ (parseComp comp) ++ "000" ++ (parseJump jump)
parseComp xs = case xs of
"0" -> "0101010"
@@ -71,25 +72,35 @@ initTable = Map.fromList $ (\(x, y) -> (x, int2Bin16 y)) <$> ("SP", 0):("LCL", 1
where rs = zipWith (,) ((\x -> 'R':(show x)) <$> [0..15]) [0..15]
stripJunk :: [Char] -> [[Char]]
-stripJunk xs = filter (not . null) $ (filter (not . (flip elem " \t")) . head . (splitOn "//")) <$> splitOn "\n" xs
+stripJunk xs = filter (not . null) $ (filter (not . (flip elem " \t")) . head . (splitOn "//")) <$> lines (replCrWithNl xs)
stripLabels :: [[Char]] -> [[Char]]
stripLabels = filter (not . (elem '('))
+addLabels :: [[Char]] -> Int -> Map [Char] [Char] -> Map [Char] [Char]
+addLabels [] _ table = table
+addLabels ((hd:tl):rest) addr table
+ | hd == '(' = addLabels rest addr (Map.insert (init tl) (int2Bin16 addr) table)
+ | otherwise = addLabels rest (addr + 1) table
+
addSyms :: [[Char]] -> Int -> Int -> Map [Char] [Char] -> Map [Char] [Char]
addSyms [] _ _ table = table
addSyms ((hd:tl):rest) addr vaddr table
| hd == '(' = addSyms rest addr vaddr (Map.insert (init tl) (int2Bin16 addr) table)
- | hd == '@' && tl `Map.notMember` table = addSyms rest (addr + 1) (vaddr + 1) (Map.insert tl (int2Bin16 vaddr) table)
+ | hd == '@' && head tl `notElem` ['0'..'9'] && tl `Map.notMember` table = addSyms rest (addr + 1) (vaddr + 1) (Map.insert tl (int2Bin16 vaddr) table)
| otherwise = addSyms rest (addr + 1) vaddr table
parseCode :: [Char] -> [Char]
-parseCode code = mconcat $ parseLine (addSyms codeWithoutJunk 0 16 initTable) <$> codeWithoutLabels
+parseCode code = unlines $ parseLine (addSyms codeWithoutLabels 0 16 (addLabels codeWithoutJunk 0 initTable)) <$> codeWithoutLabels
where codeWithoutJunk = stripJunk code
codeWithoutLabels = stripLabels codeWithoutJunk
-code0 = "// This file is part of www.nand2tetris.org\n// and the book \"The Elements of Computing Systems\"\n// by Nisan and Schocken, MIT Press.\n// File name: projects/06/add/Add.asm\n\n// Computes R0 = 2 + 3 (R0 refers to RAM[0])\n\n@2\nD=A\n@3\nD=D+A\n@0\nM=D"
+replCrWithNl = fmap cr2nl
+ where cr2nl '\r' = '\n'
+ cr2nl c = c
---main = do
- --code <- getContents
- --putStr $ parseCode code
+main = do
+ args <- getArgs
+ let filename = head args
+ code <- readFile $ filename
+ writeFile (head (splitOn "." filename) ++ ".hack") (parseCode code)