diff --git a/graph_interpreter.py b/graph_interpreter.py new file mode 100644 index 0000000..eabccfb --- /dev/null +++ b/graph_interpreter.py @@ -0,0 +1,134 @@ +import sys +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 + +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.""" + path = "./" if len(sys.argv) < 2 else sys.argv[1] + 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() diff --git a/interpreter.py b/interpreter.py new file mode 100644 index 0000000..192e619 --- /dev/null +++ b/interpreter.py @@ -0,0 +1,61 @@ +from rich.console import Console +from rich.table import Table +table = Table() + +table.add_column("Operation", justify="left", style="red", no_wrap=True) +table.add_column("Register State", justify="center", style="green") + +fileInput = open("asm", "r") +ASMLines = list(map(lambda e: e.rstrip("\n"), fileInput.readlines())) +fileInput.close() +ASMLines.append("NOP") + +dataMem = {} +ip = 0 +while ip < len(ASMLines): + 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]) + case "CAL": + pass + case "RET": + pass + case "PRI": + pass + case default: + pass + table.add_row(ASMLines[ip], ", ".join([f"{i}:{dataMem.get(i)}" for i in dataMem])) + ip += incr +console = Console() +console.print(table)