summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuchen Pei <me@ypei.me>2018-01-02 19:14:29 +0100
committerYuchen Pei <me@ypei.me>2018-01-02 19:14:29 +0100
commit98111ae037b165ca8deb2d0b73d3194a1e71d45c (patch)
tree646b12ad2e8fd8242fd743248b8506efc23b5c7a
parent381e730b9b4f07eec97865ed94cff4c189c39ad1 (diff)
almost done with project 07 part 2
-rw-r--r--projects/07/VMTranslator.hs26
1 files changed, 26 insertions, 0 deletions
diff --git a/projects/07/VMTranslator.hs b/projects/07/VMTranslator.hs
index 289c0d4..a1f93e6 100644
--- a/projects/07/VMTranslator.hs
+++ b/projects/07/VMTranslator.hs
@@ -15,6 +15,32 @@ parse' op [] n
f "or" = '|'; f "neg" = '-'; f "not" = '!'
parse' "push" ["constant", x] _ = "@" ++ x ++ "\nD=A\n" ++ push "D"
+parse' cmd [seg, x] _ | seg `elem` ["local", "argument", "this", "that"] =
+ case cmd of
+ | "push" -> getAddr seg x ++ push "D"
+ | "pop" -> getAddr seg x ++ "@R13\nM=D\n" ++ pop "M" ++ "@R13\nA=M\nM=D\n"
+
+parse' cmd [seg, x] _ | seg `elem` ["pointer", "temp"] =
+ case cmd of
+ | "push" -> getAddr' seg x ++ "D=M\n" ++ push "D"
+ | "pop" -> pop "M" ++ getAddr' seg x ++ "M=D\n"
+
+parse' cmd ["static", x] _ =
+ case cmd of
+ | "push" -> getAddr'' x ++ "D=M\n" ++ push "D"
+ | "pop" -> pop "M" ++ getAddr'' x ++ "M=D\n"
+
+getAddr seg x = "@" ++ seg2Lab seg ++ "\nD=M\n@" ++ x ++ "\nA=D+M\nD=M\n"
+
+getAddr' seg x = "@" ++ show (read x + (if seg == "pointer" then 3 else 5)) ++ "\n"
+
+getAddr'' x = "@" ++ filename ++ "." ++ x ++ "\n"
+
+seg2Lab seg = case seg of
+ | "local" -> "LCL"
+ | "argument" -> "ARG"
+ | "this" -> "THIS"
+ | "that" -> "THAT"
push :: [Char] -> [Char]
push xs = "@SP\nA=M\nM=" ++ xs ++ "\n@SP\nM=M+1\n"