From 90261fb45d990cdf2e6c9d05529b0e2297f444ad Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 13:50:07 +0200 Subject: [PATCH 1/8] Create extra test `.vm` scripts --- nand2tetris/projects/7/Mytests/testPush.vm | 9 +++++++++ nand2tetris/projects/7/Mytests/testStatic.vm | 6 ++++++ 2 files changed, 15 insertions(+) create mode 100644 nand2tetris/projects/7/Mytests/testPush.vm create mode 100644 nand2tetris/projects/7/Mytests/testStatic.vm diff --git a/nand2tetris/projects/7/Mytests/testPush.vm b/nand2tetris/projects/7/Mytests/testPush.vm new file mode 100644 index 0000000..753a3e5 --- /dev/null +++ b/nand2tetris/projects/7/Mytests/testPush.vm @@ -0,0 +1,9 @@ + + +push constant 2 +push local 3 +push argument 4 +push this 0 +push that 0 +push pointer 0 +push static 5 \ No newline at end of file diff --git a/nand2tetris/projects/7/Mytests/testStatic.vm b/nand2tetris/projects/7/Mytests/testStatic.vm new file mode 100644 index 0000000..a14dda1 --- /dev/null +++ b/nand2tetris/projects/7/Mytests/testStatic.vm @@ -0,0 +1,6 @@ +// Testing static + +push static 5 +push static 6 + +add From ebb1fa0885cc75329fcf6aa8e99fe3571ee2e8fc Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 13:52:00 +0200 Subject: [PATCH 2/8] Archive previous .asm versions --- .../src/utils/asm/{ => Archive}/add.asm | 0 .../utils/asm/{ => Archive}/popSegment.asm | 0 .../utils/asm/{ => Archive}/pushConstant.asm | 2 +- .../src/utils/asm/Archive/pushSegment.asm | 36 +++++++++++++++++++ .../pushStatic.asm} | 17 ++++++--- .../VMTranslator/src/utils/asm/pushStatic.asm | 2 -- 6 files changed, 49 insertions(+), 8 deletions(-) rename nand2tetris/projects/7/VMTranslator/src/utils/asm/{ => Archive}/add.asm (100%) rename nand2tetris/projects/7/VMTranslator/src/utils/asm/{ => Archive}/popSegment.asm (100%) rename nand2tetris/projects/7/VMTranslator/src/utils/asm/{ => Archive}/pushConstant.asm (86%) create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushSegment.asm rename nand2tetris/projects/7/VMTranslator/src/utils/asm/{pushSegment.asm => Archive/pushStatic.asm} (53%) delete mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/pushStatic.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/add.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/add.asm similarity index 100% rename from nand2tetris/projects/7/VMTranslator/src/utils/asm/add.asm rename to nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/add.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/popSegment.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/popSegment.asm similarity index 100% rename from nand2tetris/projects/7/VMTranslator/src/utils/asm/popSegment.asm rename to nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/popSegment.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushConstant.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushConstant.asm similarity index 86% rename from nand2tetris/projects/7/VMTranslator/src/utils/asm/pushConstant.asm rename to nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushConstant.asm index a1eda4a..c048c09 100644 --- a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushConstant.asm +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushConstant.asm @@ -1,4 +1,4 @@ -// ---- push {segment} {index} ---- +// ---- push constant {index} ---- // addr = segment + i, *SP = *addr, SP++ diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushSegment.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushSegment.asm new file mode 100644 index 0000000..0bd9542 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushSegment.asm @@ -0,0 +1,36 @@ +// ---- push {segment} {index} ---- + +// addr = segment + i, *SP = *addr, SP++ + +// If segment is constant: +// addr <- i +// If segment is static: +// addr <- i +// Else: +// addr <- segmentPointer + i + + +// i or file.i +@{index} + + +// if segment not in ["constant", "static"]: +// D = A +// @{segmentPointer} +// A = D + A + +// if segment == "constant": +// D = A +// else: +// D = RAM[addr] +// D = M + + +// RAM[SP] = RAM[addr] +@SP +A = M +M = D + +// SP++ +@SP +M = M + 1 \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushSegment.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushStatic.asm similarity index 53% rename from nand2tetris/projects/7/VMTranslator/src/utils/asm/pushSegment.asm rename to nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushStatic.asm index 7caa1a2..aa8501d 100644 --- a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushSegment.asm +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/Archive/pushStatic.asm @@ -1,6 +1,13 @@ -// ---- push {segment} {index} ---- +// ---- push static {index} ---- -// addr = segment + i, *SP = *addr, SP++ +// addr = Foo.i, *SP = *addr, SP++ + +@{index} +D = A + +@{segmentPointer} +A = D + A +D = A // addr <- SegmentPointer + i @@ -8,9 +15,9 @@ D = A // Not used if segment is 'constant' -@{segmentPointer} -A = D + M -D = M +// @{segmentPointer} +// A = D + M +// D = M // RAM[SP] = RAM[addr] @SP diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushStatic.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushStatic.asm deleted file mode 100644 index e446c63..0000000 --- a/nand2tetris/projects/7/VMTranslator/src/utils/asm/pushStatic.asm +++ /dev/null @@ -1,2 +0,0 @@ -// push static i - From c4fb87a14496f11c985bc030f0a36ccaa5387a14 Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 14:06:33 +0200 Subject: [PATCH 3/8] Create `.asm` elements --- .../7/VMTranslator/src/utils/asm/D_eq_i.asm | 6 ++++++ .../src/utils/asm/D_eq_segmentPointer_p_i.asm | 5 +++++ .../src/utils/asm/RAM_D_eq_RAM_SP.asm | 15 +++++++++++++++ .../7/VMTranslator/src/utils/asm/RAM_SP_eq_D.asm | 5 +++++ .../7/VMTranslator/src/utils/asm/SPmm.asm | 3 +++ .../7/VMTranslator/src/utils/asm/SPpp.asm | 3 +++ 6 files changed, 37 insertions(+) create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_i.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_D_eq_RAM_SP.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_SP_eq_D.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/SPmm.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/SPpp.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_i.asm new file mode 100644 index 0000000..0e58833 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_i.asm @@ -0,0 +1,6 @@ +// addr <- i + +// D = addr + +@{index} +D = A \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm new file mode 100644 index 0000000..18217dc --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm @@ -0,0 +1,5 @@ +// addr <- segmentPointer + i +@{index} +D = A +@{segmentPointer} +D = D + A // D = segment + i \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_D_eq_RAM_SP.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_D_eq_RAM_SP.asm new file mode 100644 index 0000000..6c68d3f --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_D_eq_RAM_SP.asm @@ -0,0 +1,15 @@ +// RAM[D] <- RAM[SP] +// Store D in R13 +// i.e. *R13 = D + + +@R13 +M = D +// D = RAM[SP] +@SP +A = M +D = M +// *R13 +@R13 +A = M +M = D \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_SP_eq_D.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_SP_eq_D.asm new file mode 100644 index 0000000..cfd692d --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_SP_eq_D.asm @@ -0,0 +1,5 @@ +// RAM[SP] = D + +@SP +A = M +M = D \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPmm.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPmm.asm new file mode 100644 index 0000000..d3ac680 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPmm.asm @@ -0,0 +1,3 @@ +// SP-- +@SP +M = M - 1 \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPpp.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPpp.asm new file mode 100644 index 0000000..9bf79cb --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/SPpp.asm @@ -0,0 +1,3 @@ +// SP++ +@SP +M = M + 1 \ No newline at end of file From 1746c04ca7a64172d9e45d4bf00beb3d54a061c7 Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 16:36:55 +0200 Subject: [PATCH 4/8] Update codewriter --- .../VMTranslator/src/codewriter/codewriter.py | 82 +++++++++++++------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py index 0d983fb..48cff1a 100644 --- a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py +++ b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py @@ -1,5 +1,5 @@ -import sys +import os # import importlib # sys.path.append("C:/Users/Bruger/OneDrive/Dokumenter/GitHub/BuildComputer/nand2tetris/projects/7/VMTranslator") @@ -60,53 +60,85 @@ def writeArithmetic(self, command : str) -> None: - def writePushPop(self, command : str, segment : str, index : int): + def writePushPop(self, command : str, segment : str, index : int, filename : str = ""): """ Arguments ---- command : ('C_PUSH' or 'C_POP') segment : constant, local etc. index : pointer number in the segment + filename: Name of file - used for push/pop static i Function ---- Writes to the output file the assembly code that implements the given command, where command is either C_PUSH or C_POP. + + If push/pop static i from filename.vm, convert to push/pop filename.i """ segmentPointer = None ## Initialize - passed to self.processCommands but not always used. + lines = [] ## Initialize lines. ## First handle 'pointer' logic translation to THIS/THAT if segment == "pointer": + if index not in [0, 1]: + raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}") segment = ["this", "that"][index] ## e.g. 'push pointer 0' means 'push this' index = 0 ## Silently 'push THIS' means 'push THIS 0' + + elif segment == "temp" and (not 0 <= index < 7): + raise ValueError(f"'temp' segment only valid for index values 0 to 7. Input: {index}.") + + elif segment == "static": + if filename == "": + raise ValueError(f"No filename supplied for push/pop static.") + file = os.path.splitext(os.path.basename(filename))[0] + index = file + "." + str(index) + print(index) + + elif segment in dicts.segment.keys(): + ## Used in some of the .asm templates. + ## Contains Hack name convention for segments, e.g. local is "LCL" + segmentPointer = dicts.segment[segment] + # elif segment == "temp": + # ... + # elif segment == "pointer": ## Handled above + # ... + + + if segment != "static": + lines.extend([ + f"@{index}", + "D = A" + ]) + if command == "C_PUSH": + # if segment == "constant": + # asm_location = "pushConstant.asm" + # else: + # asm_location = "pushSegment.asm" + + if segment != "constant": + # RAM[SP] = index + # SP++ + lines.extend(self.processCommands(parser, segment = segment, segmentPointer = segmentPointer, index = index)) + asm_location = "pushSegment.asm" + + elif command == "C_POP": + asm_location = "popSegment.asm" if segment == "constant": - asm_location = "pushConstant.asm" - elif segment in ["local", "argument", "this", "that", "temp"]: - ## Used in some of the .asm templates. - ## Contains Hack name convention for segments, e.g. local is "LCL" - segmentPointer = dicts.segment[segment] - asm_location = "pushSegment.asm" - elif segment == "static": - asm_location = "pushStatic.asm" - # elif segment == "temp": - # ... - # elif segment == "pointer": ## Handled above - # ... - # elif command == "C_POP": - # ... + raise ValueError("Cannot pop constant.") + + else: raise KeyError(f"Unexpected command '{command}' in writePushPop (should be 'C_PUSH' or 'C_POP')") - lines = [] ## Initialize lines. - with open(f"src/utils/asm/{asm_location}", 'r') as asm: - parser = self.Parser(asm) - - lines = self.processCommands(parser, segment = segment, segmentPointer = segmentPointer, index = index) - return lines + return self.processAsm(segment, index, segmentPointer, lines, asm_location) + + def processCommands(self, parser, **kwargs): """ @@ -135,6 +167,10 @@ def processCommands(self, parser, **kwargs): return lines - + def processAsm(self, segment : str, index : str|int, segmentPointer, lines, asm_location): + with open(f"src/utils/asm/{asm_location}", 'r') as asm: + parser = self.Parser(asm) + lines = self.processCommands(parser, segment = segment, segmentPointer = segmentPointer, index = index) + return lines \ No newline at end of file From e75baede1da1f9a8b80319de205b4436c1e5d0ab Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 17:22:07 +0200 Subject: [PATCH 5/8] Push commands fixed --- .../VMTranslator/src/codewriter/codewriter.py | 48 ++++++++----------- ..._i.asm => D_eq_RAM_segmentPointer_p_i.asm} | 4 +- 2 files changed, 23 insertions(+), 29 deletions(-) rename nand2tetris/projects/7/VMTranslator/src/utils/asm/{D_eq_segmentPointer_p_i.asm => D_eq_RAM_segmentPointer_p_i.asm} (65%) diff --git a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py index 48cff1a..9089f23 100644 --- a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py +++ b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py @@ -57,8 +57,6 @@ def writeArithmetic(self, command : str) -> None: return lines - - def writePushPop(self, command : str, segment : str, index : int, filename : str = ""): """ @@ -85,7 +83,6 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}") segment = ["this", "that"][index] ## e.g. 'push pointer 0' means 'push this' index = 0 ## Silently 'push THIS' means 'push THIS 0' - elif segment == "temp" and (not 0 <= index < 7): raise ValueError(f"'temp' segment only valid for index values 0 to 7. Input: {index}.") @@ -94,8 +91,6 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str raise ValueError(f"No filename supplied for push/pop static.") file = os.path.splitext(os.path.basename(filename))[0] index = file + "." + str(index) - print(index) - elif segment in dicts.segment.keys(): ## Used in some of the .asm templates. ## Contains Hack name convention for segments, e.g. local is "LCL" @@ -105,30 +100,27 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str # elif segment == "pointer": ## Handled above # ... - - if segment != "static": - lines.extend([ - f"@{index}", - "D = A" - ]) - - if command == "C_PUSH": - # if segment == "constant": - # asm_location = "pushConstant.asm" - # else: - # asm_location = "pushSegment.asm" - - if segment != "constant": - # RAM[SP] = index - # SP++ - lines.extend(self.processCommands(parser, segment = segment, segmentPointer = segmentPointer, index = index)) - asm_location = "pushSegment.asm" + if segment in ["constant", "static"]: + # D <- index + lines.extend(self.processAsm("D_eq_i.asm", index = index)) + elif segment in dicts.segment.keys(): # local, argument, this, that, temp + # addr <- segmentPointer + index + # D <- RAM[addr] + lines.extend(self.processAsm("D_eq_RAM_segmentPointer_p_i.asm",index = index, segmentPointer = segmentPointer)) + else: + raise ValueError(f"Segment = '{segment}' not handled.") + ## RAM[SP] <- D + ## SP++ + lines.extend(self.processAsm("RAM_SP_eq_D.asm")) + lines.extend(self.processAsm("SPpp.asm")) + elif command == "C_POP": - asm_location = "popSegment.asm" if segment == "constant": raise ValueError("Cannot pop constant.") + elif segment in dicts.segment.keys(): + ... else: @@ -136,7 +128,7 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str - return self.processAsm(segment, index, segmentPointer, lines, asm_location) + return lines @@ -167,10 +159,10 @@ def processCommands(self, parser, **kwargs): return lines - def processAsm(self, segment : str, index : str|int, segmentPointer, lines, asm_location): - with open(f"src/utils/asm/{asm_location}", 'r') as asm: + def processAsm(self, asm_file : str, **kwargs): + with open(f"src/utils/asm/{asm_file}", 'r') as asm: parser = self.Parser(asm) - lines = self.processCommands(parser, segment = segment, segmentPointer = segmentPointer, index = index) + lines = self.processCommands(parser, **kwargs) return lines \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm similarity index 65% rename from nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm rename to nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm index 18217dc..4b64500 100644 --- a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm @@ -2,4 +2,6 @@ @{index} D = A @{segmentPointer} -D = D + A // D = segment + i \ No newline at end of file +A = D + A +// D <- RAM[addr] +D = M \ No newline at end of file From 42d6cd1191a4673a8e698a604b83570febc47ca2 Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 22:18:54 +0200 Subject: [PATCH 6/8] Pop command work --- .../VMTranslator/src/codewriter/codewriter.py | 64 +++++++++++++------ .../VMTranslator/src/utils/asm/D_eq_RAM_i.asm | 4 ++ .../utils/asm/D_eq_RAM_segmentPointer_p_i.asm | 1 + .../src/utils/asm/D_eq_segmentPointer_p_i.asm | 7 ++ .../7/VMTranslator/src/utils/asm/R13_eq_D.asm | 3 + .../src/utils/asm/RAM_R13_eq_RAM_SP.asm | 11 ++++ 6 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_i.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/R13_eq_D.asm create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_R13_eq_RAM_SP.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py index 9089f23..b6d69e7 100644 --- a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py +++ b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py @@ -77,50 +77,76 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str segmentPointer = None ## Initialize - passed to self.processCommands but not always used. lines = [] ## Initialize lines. - ## First handle 'pointer' logic translation to THIS/THAT + ## Raise errors: + + ## Wrong command + if command not in ["C_PUSH", "C_POP"]: + raise ValueError(f"command: '{command}' not allowed for writePushPop. Only takes 'C_PUSH' or 'C_POP'.") + ## First handle 'pointer' logic translation to THIS/THAT + ## Also handle temp out of bounds. + ## Also raise error if trying to pop constant if segment == "pointer": if index not in [0, 1]: - raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}") + raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}.") segment = ["this", "that"][index] ## e.g. 'push pointer 0' means 'push this' index = 0 ## Silently 'push THIS' means 'push THIS 0' + + elif segment == "temp" and (not 0 <= index < 7): raise ValueError(f"'temp' segment only valid for index values 0 to 7. Input: {index}.") - - elif segment == "static": + elif command == "C_POP" and segment == "constant": + raise ValueError("Cannot pop constant.") + + ## New if-block + if segment == "static": if filename == "": raise ValueError(f"No filename supplied for push/pop static.") file = os.path.splitext(os.path.basename(filename))[0] index = file + "." + str(index) + + if command == "C_PUSH": + # addr <- filename.index + # D <- RAM[addr] + lines.extend(self.processAsm("D_eq_RAM_i.asm", index = index)) + else: # command == "C_POP" + # addr <- filename.index + lines.extend(self.processAsm("D_eq_i.asm", index = index)) + + elif segment == "constant": + # D <- addr + lines.extend(self.processAsm("D_eq_i.asm", index = index)) + elif segment in dicts.segment.keys(): ## Used in some of the .asm templates. ## Contains Hack name convention for segments, e.g. local is "LCL" segmentPointer = dicts.segment[segment] - # elif segment == "temp": - # ... - # elif segment == "pointer": ## Handled above - # ... - if command == "C_PUSH": - if segment in ["constant", "static"]: - # D <- index - lines.extend(self.processAsm("D_eq_i.asm", index = index)) - elif segment in dicts.segment.keys(): # local, argument, this, that, temp + if command == "C_PUSH": # addr <- segmentPointer + index # D <- RAM[addr] lines.extend(self.processAsm("D_eq_RAM_segmentPointer_p_i.asm",index = index, segmentPointer = segmentPointer)) - else: - raise ValueError(f"Segment = '{segment}' not handled.") + else: #command == "C_POP": + # D <- addr + lines.extend(self.processAsm("D_eq_segmentPointer_p_i.asm", index = index, segmentPointer = segmentPointer)) + else: + raise ValueError(f"Segment = '{segment}' not handled.") + + if command == "C_PUSH": ## RAM[SP] <- D ## SP++ lines.extend(self.processAsm("RAM_SP_eq_D.asm")) lines.extend(self.processAsm("SPpp.asm")) - - elif command == "C_POP": if segment == "constant": raise ValueError("Cannot pop constant.") - elif segment in dicts.segment.keys(): - ... + + ## SP-- + # R13 <- D # R13_eq_D.asm + # RAM[R13] <- RAM[SP] # RAM_R13_eq_RAM_SP.asm + lines.extend(self.processAsm("SPmm.asm")) + lines.extend(self.processAsm("R13_eq_D.asm")) + lines.extend(self.processAsm("RAM_R13_eq_RAM_SP.asm")) + else: diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_i.asm new file mode 100644 index 0000000..1598659 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_i.asm @@ -0,0 +1,4 @@ +// addr <- i +@{index} +// D <- RAM[addr] +D = M \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm index 4b64500..6a9518c 100644 --- a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer_p_i.asm @@ -2,6 +2,7 @@ @{index} D = A @{segmentPointer} +A = M A = D + A // D <- RAM[addr] D = M \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm new file mode 100644 index 0000000..5d92df0 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer_p_i.asm @@ -0,0 +1,7 @@ +// addr <- segmentPointer + i +@{index} +D = A +@{segmentPointer} +// D <- addr +A = M +D = D + A diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/R13_eq_D.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/R13_eq_D.asm new file mode 100644 index 0000000..3c4eac3 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/R13_eq_D.asm @@ -0,0 +1,3 @@ +// R13 <- D +@R13 +M = D \ No newline at end of file diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_R13_eq_RAM_SP.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_R13_eq_RAM_SP.asm new file mode 100644 index 0000000..ad65028 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/RAM_R13_eq_RAM_SP.asm @@ -0,0 +1,11 @@ +// RAM[R13] <- RAM[SP] + +// D = RAM[SP] +@SP +A = M +D = M + +// RAM[13] <- D +@R13 +A = M +M = D \ No newline at end of file From 2ea980adc3e120768f1d7284484c3892c3cc32b6 Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sat, 18 May 2024 23:42:50 +0200 Subject: [PATCH 7/8] Passes BasicTest --- .../VMTranslator/src/codewriter/codewriter.py | 27 ++++++++++++++----- .../src/utils/asm/D_eq_segmentPointer.asm | 4 +++ 2 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py index b6d69e7..a04b1c9 100644 --- a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py +++ b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py @@ -85,14 +85,8 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str ## First handle 'pointer' logic translation to THIS/THAT ## Also handle temp out of bounds. ## Also raise error if trying to pop constant - if segment == "pointer": - if index not in [0, 1]: - raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}.") - segment = ["this", "that"][index] ## e.g. 'push pointer 0' means 'push this' - index = 0 ## Silently 'push THIS' means 'push THIS 0' - - elif segment == "temp" and (not 0 <= index < 7): + if segment == "temp" and (not 0 <= index < 7): raise ValueError(f"'temp' segment only valid for index values 0 to 7. Input: {index}.") elif command == "C_POP" and segment == "constant": raise ValueError("Cannot pop constant.") @@ -116,6 +110,25 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str # D <- addr lines.extend(self.processAsm("D_eq_i.asm", index = index)) + elif segment == "temp": + # addr <- 5 + index + # D <- addr + index += dicts.segment[segment] + + if command == "C_PUSH": + lines.extend(self.processAsm("D_eq_RAM_i.asm", index = index)) + else: # command == "C_POP" + lines.extend(self.processAsm("D_eq_i.asm", index = index)) + + elif segment == "pointer": + if index not in [0, 1]: + raise ValueError(f"push/pop pointer only valid for value 0 or 1. Input: {index}.") + segment = ["this", "that"][index] ## e.g. 'push pointer 0' means 'push this' + segmentPointer = dicts.segment[segment] + index = 0 ## Silently 'push THIS' means 'push THIS 0' + + lines.extend(self.processAsm("D_eq_segmentPointer.asm", segmentPointer = segmentPointer)) + elif segment in dicts.segment.keys(): ## Used in some of the .asm templates. ## Contains Hack name convention for segments, e.g. local is "LCL" diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer.asm new file mode 100644 index 0000000..b872787 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_segmentPointer.asm @@ -0,0 +1,4 @@ +// addr <- segmentPointer +@{segmentPointer} +// D <- addr +D = A \ No newline at end of file From 3cc56edecd30049285f5707e01dcc421dfb9d753 Mon Sep 17 00:00:00 2001 From: ATherkel Date: Sun, 19 May 2024 11:54:42 +0200 Subject: [PATCH 8/8] Passes PointerTest --- .../projects/7/VMTranslator/src/codewriter/codewriter.py | 5 ++++- .../7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer.asm | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer.asm diff --git a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py index a04b1c9..c901d81 100644 --- a/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py +++ b/nand2tetris/projects/7/VMTranslator/src/codewriter/codewriter.py @@ -127,7 +127,10 @@ def writePushPop(self, command : str, segment : str, index : int, filename : str segmentPointer = dicts.segment[segment] index = 0 ## Silently 'push THIS' means 'push THIS 0' - lines.extend(self.processAsm("D_eq_segmentPointer.asm", segmentPointer = segmentPointer)) + if command == "C_PUSH": + lines.extend(self.processAsm("D_eq_RAM_segmentPointer.asm", segmentPointer = segmentPointer)) + else: # command == "C_POP" + lines.extend(self.processAsm("D_eq_segmentPointer.asm", segmentPointer = segmentPointer)) elif segment in dicts.segment.keys(): ## Used in some of the .asm templates. diff --git a/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer.asm b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer.asm new file mode 100644 index 0000000..3f1e048 --- /dev/null +++ b/nand2tetris/projects/7/VMTranslator/src/utils/asm/D_eq_RAM_segmentPointer.asm @@ -0,0 +1,4 @@ +// addr <- segmentPointer +@{segmentPointer} +// D <- RAM[addr] +D = M \ No newline at end of file