|
|
|
|
@ -21,7 +21,8 @@ import Text.Megaparsec (runParser)
@@ -21,7 +21,8 @@ import Text.Megaparsec (runParser)
|
|
|
|
|
spec :: Spec |
|
|
|
|
spec = do |
|
|
|
|
describe "parseInstruction" parseInstructionSpec |
|
|
|
|
describe "compileInstruction" compileInstructionSpec |
|
|
|
|
describe "compile push instruction" compilePushInstructionSpec |
|
|
|
|
describe "compile pop instruction" compilePopInstructionSpec |
|
|
|
|
|
|
|
|
|
parseInstructionSpec :: Spec |
|
|
|
|
parseInstructionSpec = do |
|
|
|
|
@ -85,8 +86,8 @@ parseInstructionSpec = do
@@ -85,8 +86,8 @@ parseInstructionSpec = do
|
|
|
|
|
where |
|
|
|
|
doParse = runParser parseInstruction "" |
|
|
|
|
|
|
|
|
|
compileInstructionSpec :: Spec |
|
|
|
|
compileInstructionSpec = do |
|
|
|
|
compilePushInstructionSpec :: Spec |
|
|
|
|
compilePushInstructionSpec = do |
|
|
|
|
it "Compiles push argument 42" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPush (SArgument 42)) |
|
|
|
|
head compiled `shouldBe` (Comment "push argument 42") |
|
|
|
|
@ -172,3 +173,79 @@ compileInstructionSpec = do
@@ -172,3 +173,79 @@ compileInstructionSpec = do
|
|
|
|
|
Code (C [RegM] (SReg RegD) JNone) ] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
compilePopInstructionSpec :: Spec |
|
|
|
|
compilePopInstructionSpec = do |
|
|
|
|
it "pop argument 42" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SArgument 42)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop argument 42") |
|
|
|
|
tail compiled `shouldBe` popValue "ARG" 42 |
|
|
|
|
|
|
|
|
|
it "pop local 42" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SLocal 42)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop local 42") |
|
|
|
|
tail compiled `shouldBe` popValue "LCL" 42 |
|
|
|
|
|
|
|
|
|
it "pop this 42" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SThis 42)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop this 42") |
|
|
|
|
tail compiled `shouldBe` popValue "THIS" 42 |
|
|
|
|
|
|
|
|
|
it "pop that 42" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SThat 42)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop that 42") |
|
|
|
|
tail compiled `shouldBe` popValue "THAT" 42 |
|
|
|
|
|
|
|
|
|
it "pop static Foo.1" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SStatic "Foo.1")) |
|
|
|
|
head compiled `shouldBe` (Comment "pop static Foo.1") |
|
|
|
|
tail compiled `shouldBe` popLabelValue "Foo.1" |
|
|
|
|
|
|
|
|
|
it "pop pointer 0" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SPointer 0)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop pointer 0") |
|
|
|
|
tail compiled `shouldBe` popLabelValue "THIS" |
|
|
|
|
|
|
|
|
|
it "pop pointer 1" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (SPointer 1)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop pointer 1") |
|
|
|
|
tail compiled `shouldBe` popLabelValue "THAT" |
|
|
|
|
|
|
|
|
|
it "pop temp 1" $ do |
|
|
|
|
let compiled = compileInstruction (VMMemAccess ACPop (STemp 1)) |
|
|
|
|
head compiled `shouldBe` (Comment "pop temp 1") |
|
|
|
|
tail compiled `shouldBe` popRam (5 + 1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
where |
|
|
|
|
popValue reg value = [ |
|
|
|
|
Code (A (Label "SP")), |
|
|
|
|
Code (C [RegM] (SRegMinus1 RegM) JNone), |
|
|
|
|
|
|
|
|
|
Code (A (Imm value)), |
|
|
|
|
Code (C [RegD] (SReg RegA) JNone), |
|
|
|
|
Code (A (Label reg)), |
|
|
|
|
Code (C [RegA] SDPlusM JNone), |
|
|
|
|
Code (C [RegD] (SReg RegM) JNone), |
|
|
|
|
|
|
|
|
|
Code (A (Label "SP")), |
|
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
|
Code (C [RegM] (SReg RegD) JNone) |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
popLabelValue label = [ |
|
|
|
|
Code (A (Label "SP")), |
|
|
|
|
Code (C [RegM] (SRegMinus1 RegM) JNone), |
|
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
|
Code (C [RegD] (SReg RegM) JNone), |
|
|
|
|
Code (A . Label $ label), |
|
|
|
|
Code (C [RegM] (SReg RegD) JNone) ] |
|
|
|
|
|
|
|
|
|
popRam offset = [ |
|
|
|
|
Code (A (Label "SP")), |
|
|
|
|
Code (C [RegM] (SRegMinus1 RegM) JNone), |
|
|
|
|
Code (C [RegA] (SReg RegM) JNone), |
|
|
|
|
Code (C [RegD] (SReg RegM) JNone), |
|
|
|
|
Code (A . Imm $ offset), |
|
|
|
|
Code (C [RegM] (SReg RegD) JNone) ] |
|
|
|
|
|
|
|
|
|
|