import sys try: from textual.color import Color from textual import events from textual.app import App, ComposeResult from textual.containers import Container, VerticalScroll from textual.widgets import Footer, Header, Static except: print("please install textual and rich !") def getLinesToShow(ip, lines): if ip > 1 and ip + 2 < len(lines): l= lines[ip - 2: ip + 3] l[2] = "> " + l[2] + " <" elif ip <= 1: l= lines[0: 5] l[ip] = "> " + l[ip] + " <" else: l= lines[-5:] l[ip-len(lines)] = "> " + l[ip-len(lines)] + " <" return l def update_interpreter(self): global ip global ASMLines global dataMem if "NOP" not in ASMLines[ip]: incr = 1 currLine = ASMLines[ip].split() match currLine[0]: case "ADD": dataMem[currLine[1]] = dataMem[currLine[2]] + dataMem[currLine[3]] case "MUL": dataMem[currLine[1]] = dataMem[currLine[2]] * dataMem[currLine[3]] case "SUB": dataMem[currLine[1]] = dataMem[currLine[2]] - dataMem[currLine[3]] case "DIV": dataMem[currLine[1]] = dataMem[currLine[2]] / dataMem[currLine[3]] case "COP": dataMem[currLine[1]] = dataMem[currLine[2]] case "AFC": dataMem[currLine[1]] = int(currLine[2]) case "SUP": dataMem[currLine[1]] = dataMem[currLine[2]] > dataMem[currLine[3]] case "EQ": dataMem[currLine[1]] = dataMem[currLine[2]] == dataMem[currLine[3]] case "NOT": dataMem[currLine[1]] = not dataMem[currLine[2]] case "INF": dataMem[currLine[1]] = dataMem[currLine[2]] < dataMem[currLine[3]] case "AND": dataMem[currLine[1]] = dataMem[currLine[2]] and dataMem[currLine[3]] case "OR": dataMem[currLine[1]] = dataMem[currLine[2]] and dataMem[currLine[3]] case "JMP": ip = int(currLine[1]) incr = 0 case "JMF": if not dataMem[currLine[1]]: incr = 0 ip = int(currLine[2]) print(ip) case "CAL": pass case "RET": pass case "PRI": pass case default: pass print(ASMLines[ip], ", ".join([f"{i}:{dataMem.get(i)}" for i in dataMem])) ip += incr else: cont = self.query_one("#cont", Container) cont.styles.background = Color.parse("#151E3D") code = self.query_one("#code", Static) code.update(" ") class codeLines(Static): """one line of assembly code""" def update_code(self, line) -> None: self.update(line) class registers(Static): """one line of assembly code""" def update_regs(self, line) -> None: self.update(line) class interpreter(App): """A Textual app to see your asm code run !.""" TITLE = "A Textual app to see your asm code run !." CSS_PATH = "style.css" BINDINGS = [ ("q", "quit", "Quit"), ] def compose(self) -> ComposeResult: """Compose our UI.""" yield Header() with Container(id="cont"): with VerticalScroll(id="code-view"): yield codeLines("\n".join(getLinesToShow(ip, ASMLines)),id="code", expand=True) yield registers(id="regs", expand=True) yield Footer() def on_key(self, event: events.Key) -> None: code = self.query_one("#code", Static) regs = self.query_one("#regs", Static) update_interpreter(self) global ip, ASMLines code.update_code("\n".join(getLinesToShow(ip, ASMLines))) l = [] for i in range(max([int(i)+1 for i in dataMem.keys()])): if str(i) in dataMem.keys(): l.append([i, dataMem[str(i)]]) regs.update_regs("\n".join([f"@{k[0]} : {k[1]}" for k in l])) if __name__ == "__main__": fileInput = open("asm", "r") global ASMLines ASMLines = list(map(lambda e: e.rstrip("\n"), fileInput.readlines())) fileInput.close() ASMLines.append("NOP") global dataMem dataMem = {} global ip ip = 0 interpreter().run()