|
|
|
@ -12,8 +12,9 @@ import Nand2Tetris.Hack (HackInstruction (..), Imm (..), Jump (..), |
|
|
|
import Nand2Tetris.VM (AccessType (ACPop, ACPush), |
|
|
|
import Nand2Tetris.VM (AccessType (ACPop, ACPush), |
|
|
|
AnnotatedAsmLine (..), |
|
|
|
AnnotatedAsmLine (..), |
|
|
|
ArithmeticCmd (ACAdd, ACAnd, ACEq, ACGt, ACLt, ACNeg, ACNot, ACOr, ACSub), |
|
|
|
ArithmeticCmd (ACAdd, ACAnd, ACEq, ACGt, ACLt, ACNeg, ACNot, ACOr, ACSub), |
|
|
|
|
|
|
|
BranchingCmd (..), |
|
|
|
Segment (SArgument, SConstant, SLocal, SPointer, SStatic, STemp, SThat, SThis), |
|
|
|
Segment (SArgument, SConstant, SLocal, SPointer, SStatic, STemp, SThat, SThis), |
|
|
|
VMInstruction (VMArithmetic, VMMemAccess), |
|
|
|
VMInstruction (VMArithmetic, VMBranching, VMMemAccess), |
|
|
|
compileInstruction, parseInstruction, |
|
|
|
compileInstruction, parseInstruction, |
|
|
|
runCompilerDef) |
|
|
|
runCompilerDef) |
|
|
|
import Text.Megaparsec (runParser) |
|
|
|
import Text.Megaparsec (runParser) |
|
|
|
@ -25,6 +26,8 @@ spec = do |
|
|
|
describe "compile push instruction" compilePushInstructionSpec |
|
|
|
describe "compile push instruction" compilePushInstructionSpec |
|
|
|
describe "compile pop instruction" compilePopInstructionSpec |
|
|
|
describe "compile pop instruction" compilePopInstructionSpec |
|
|
|
describe "compile arithmetic instrucitons" compileArithInstructionSpec |
|
|
|
describe "compile arithmetic instrucitons" compileArithInstructionSpec |
|
|
|
|
|
|
|
describe "compile branching instrucitons" compileBranchingInstructionSpec |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parseInstructionSpec :: Spec |
|
|
|
parseInstructionSpec :: Spec |
|
|
|
parseInstructionSpec = do |
|
|
|
parseInstructionSpec = do |
|
|
|
@ -85,6 +88,14 @@ parseInstructionSpec = do |
|
|
|
it "Parses instruction: not" $ |
|
|
|
it "Parses instruction: not" $ |
|
|
|
doParse "not" `shouldBe` Right (VMArithmetic ACNot) |
|
|
|
doParse "not" `shouldBe` Right (VMArithmetic ACNot) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it "Parses instruction: label foo" $ |
|
|
|
|
|
|
|
doParse "label foo" `shouldBe` Right (VMBranching (BLabel "foo")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it "Parses instruction: goto foo" $ |
|
|
|
|
|
|
|
doParse "goto foo" `shouldBe` Right (VMBranching (BGoto "foo")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it "Parses instruction: if-goto foo" $ |
|
|
|
|
|
|
|
doParse "if-goto foo" `shouldBe` Right (VMBranching (BIfGoto "foo")) |
|
|
|
where |
|
|
|
where |
|
|
|
doParse = runParser parseInstruction "" |
|
|
|
doParse = runParser parseInstruction "" |
|
|
|
|
|
|
|
|
|
|
|
@ -228,13 +239,13 @@ compilePopInstructionSpec = do |
|
|
|
Code (C [RegD] (SReg RegA) JNone), |
|
|
|
Code (C [RegD] (SReg RegA) JNone), |
|
|
|
Code (A (Label reg)), |
|
|
|
Code (A (Label reg)), |
|
|
|
Code (C [RegD] SDPlusM JNone), |
|
|
|
Code (C [RegD] SDPlusM JNone), |
|
|
|
Code (A (Label "R15")), |
|
|
|
Code (A (Imm 15)), |
|
|
|
Code (C [RegM] (SReg RegD) JNone), |
|
|
|
Code (C [RegM] (SReg RegD) JNone), |
|
|
|
|
|
|
|
|
|
|
|
Code (A (Label "SP")), |
|
|
|
Code (A (Label "SP")), |
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
Code (C [RegD] (SReg RegM) JNone), |
|
|
|
Code (C [RegD] (SReg RegM) JNone), |
|
|
|
Code (A (Label "R15")), |
|
|
|
Code (A (Imm 15)), |
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
Code (C [RegM] (SReg RegD) JNone) |
|
|
|
Code (C [RegM] (SReg RegD) JNone) |
|
|
|
] |
|
|
|
] |
|
|
|
@ -298,3 +309,25 @@ compileArithInstructionSpec = do |
|
|
|
Code (C [RegM] (SNeg RegM) JNone) |
|
|
|
Code (C [RegM] (SNeg RegM) JNone) |
|
|
|
] |
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compileBranchingInstructionSpec :: Spec |
|
|
|
|
|
|
|
compileBranchingInstructionSpec = do |
|
|
|
|
|
|
|
it "label foo" $ do |
|
|
|
|
|
|
|
let compiled = runCompilerDef $ compileInstruction (VMBranching (BLabel "foo")) |
|
|
|
|
|
|
|
head compiled `shouldBe` (Comment "label foo") |
|
|
|
|
|
|
|
tail compiled `shouldBe` [(ALabel "foo")] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it "goto foo" $ do |
|
|
|
|
|
|
|
let compiled = runCompilerDef $ compileInstruction (VMBranching (BGoto "foo")) |
|
|
|
|
|
|
|
head compiled `shouldBe` (Comment "goto foo") |
|
|
|
|
|
|
|
tail compiled `shouldBe` [ Code (A (Label "foo")), |
|
|
|
|
|
|
|
Code (C [] S0 Jmp) |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it "if-goto foo" $ do |
|
|
|
|
|
|
|
let compiled = runCompilerDef $ compileInstruction (VMBranching (BIfGoto "foo")) |
|
|
|
|
|
|
|
head compiled `shouldBe` (Comment "if-goto foo") |
|
|
|
|
|
|
|
tail compiled `shouldBe` [ Code (A (Label "SP")), |
|
|
|
|
|
|
|
Code (C [RegA, RegM] (SRegMinus1 RegM) JNone), |
|
|
|
|
|
|
|
Code (C [] (SReg RegM) JNe) |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|