139 lines
4.3 KiB
Python
139 lines
4.3 KiB
Python
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()
|