First implementation of the compiler
This commit is contained in:
339
Project-02-03/vistram/tram.py
Normal file
339
Project-02-03/vistram/tram.py
Normal file
@@ -0,0 +1,339 @@
|
||||
# (c) Stephan Diehl, University of Trier, Germany, 2025
|
||||
|
||||
class TRAM:
|
||||
def __init__(self, prog):
|
||||
self.set_label_addresses(prog)
|
||||
self.program=prog+[halt()]
|
||||
self.print_prog(self.program)
|
||||
self.pc = 0
|
||||
self.stack = []
|
||||
self.top = -1
|
||||
self.pp = 0 #-1
|
||||
self.fp = 0 #-1
|
||||
|
||||
def start(self):
|
||||
while self.pc>=0:
|
||||
self.print_instruction(self.program[self.pc])
|
||||
self.program[self.pc].execute(self)
|
||||
print(self.stack)
|
||||
|
||||
def set_label_addresses(self,code):
|
||||
pos = 0
|
||||
for instr in code:
|
||||
for label in instr.assigned_labels:
|
||||
label.address = pos
|
||||
pos = pos + 1
|
||||
|
||||
def pop(self):
|
||||
del self.stack[self.top]
|
||||
self.top = self.top - 1
|
||||
|
||||
def push(self,v):
|
||||
self.stack.append(v)
|
||||
self.top = self.top + 1
|
||||
|
||||
def spp(self,d,pp,fp):
|
||||
if (d==0):
|
||||
return pp
|
||||
else:
|
||||
return self.spp(d-1,self.stack[self.fp+3],self.stack[self.fp+4])
|
||||
|
||||
def sfp(self, d, pp, fp):
|
||||
if (d==0):
|
||||
return fp
|
||||
else:
|
||||
return self.sfp(d-1, self.stack[self.fp+3], self.stack[self.fp+4])
|
||||
|
||||
def print_prog(self,prog):
|
||||
pos=0
|
||||
for instr in prog:
|
||||
print(str(pos)+": ",end="")
|
||||
pos=pos+1
|
||||
self.print_instruction(instr)
|
||||
|
||||
def print_instruction(self, instr):
|
||||
print(type(instr).__name__, end = "")
|
||||
for attr in vars(instr).keys():
|
||||
value=getattr(instr,attr)
|
||||
if isinstance(value,list): continue
|
||||
if isinstance(value,Label):
|
||||
value="#"+str(value.address)
|
||||
else:
|
||||
value=str(value)
|
||||
print(" "+value,end="")
|
||||
print()
|
||||
|
||||
#################
|
||||
|
||||
class Label:
|
||||
count=0
|
||||
address=-1
|
||||
|
||||
def __init__(self,address=-1,text=""):
|
||||
Label.count+=1
|
||||
self.id=Label.count
|
||||
self.address=address
|
||||
if text=="":
|
||||
self.text=f"L{Label.count}"
|
||||
else:
|
||||
self.text=text
|
||||
|
||||
def toString(self): return self.text
|
||||
|
||||
|
||||
##################
|
||||
|
||||
class Instruction:
|
||||
|
||||
def __init__(self,assigned_label=None):
|
||||
self.assigned_labels = []
|
||||
if not assigned_label is None:
|
||||
if isinstance(assigned_label,Label):
|
||||
self.assigned_labels+=[assigned_label]
|
||||
else:
|
||||
self.assigned_labels+=assigned_label
|
||||
|
||||
def toString(self):
|
||||
s=self.toStringx()
|
||||
#print(s)
|
||||
return(s)
|
||||
|
||||
def toStringx(self):
|
||||
if (len(self.assigned_labels)==0):
|
||||
return " "
|
||||
else:
|
||||
return ','.join( [ label.toString()
|
||||
for label in self.assigned_labels] )+": "
|
||||
|
||||
class halt(Instruction):
|
||||
def __init__(self,assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.pc=-1
|
||||
|
||||
def toString(self): return super().toString()+"HALT"
|
||||
|
||||
class nop(Instruction):
|
||||
def __init__(self,assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString()+"NOP"
|
||||
|
||||
class pop(Instruction):
|
||||
def __init__(self,assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString()+"POP"
|
||||
|
||||
class const(Instruction):
|
||||
def __init__(self, k, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.k=k
|
||||
|
||||
def execute(self,tram):
|
||||
tram.push(self.k)
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString()+"CONST "+str(self.k)
|
||||
|
||||
class store(Instruction):
|
||||
def __init__(self, k, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.k=k
|
||||
self.d=d
|
||||
|
||||
def execute(self,tram):
|
||||
tram.stack[tram.spp(self.d,tram.pp,tram.fp)+self.k]=tram.stack[tram.top]
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self):
|
||||
return super().toString()+"STORE "+str(self.k)+" "+str(self.d)
|
||||
|
||||
class load(Instruction):
|
||||
def __init__(self, k, d, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.k=k
|
||||
self.d=d
|
||||
|
||||
def execute(self,tram):
|
||||
tram.push(tram.stack[tram.spp(self.d,tram.pp,tram.fp)+self.k])
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self):
|
||||
return super().toString()+"LOAD "+str(self.k)+" "+str(self.d)
|
||||
|
||||
class add(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.stack[tram.top-1]=tram.stack[tram.top-1]+tram.stack[tram.top]
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString()+"ADD"
|
||||
|
||||
|
||||
|
||||
class sub(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.stack[tram.top-1]=tram.stack[tram.top-1]-tram.stack[tram.top]
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "SUB"
|
||||
|
||||
class mul(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.stack[tram.top-1]=tram.stack[tram.top-1]*tram.stack[tram.top]
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "MUL"
|
||||
|
||||
class div(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
tram.stack[tram.top-1]=tram.stack[tram.top-1]/tram.stack[tram.top]
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "DIV"
|
||||
|
||||
class lt(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
if tram.stack[tram.top-1]<tram.stack[tram.top]:
|
||||
tram.stack[tram.top-1]=1
|
||||
else:
|
||||
tram.stack[tram.top-1]=0
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "LT"
|
||||
|
||||
class gt(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
if tram.stack[tram.top-1]>tram.stack[tram.top]:
|
||||
tram.stack[tram.top-1]=1
|
||||
else:
|
||||
tram.stack[tram.top-1]=0
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "GT"
|
||||
|
||||
class eq(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
if tram.stack[tram.top-1]==tram.stack[tram.top]:
|
||||
tram.stack[tram.top-1]=1
|
||||
else:
|
||||
tram.stack[tram.top-1]=0
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "EQ"
|
||||
|
||||
class neq(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
if tram.stack[tram.top-1]!=tram.stack[tram.top]:
|
||||
tram.stack[tram.top-1]=1
|
||||
else:
|
||||
tram.stack[tram.top-1]=0
|
||||
tram.pop()
|
||||
tram.pc=tram.pc+1
|
||||
|
||||
def toString(self): return super().toString() + "NEQ"
|
||||
|
||||
class goto(Instruction):
|
||||
def __init__(self, label, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.label=label
|
||||
|
||||
def execute(self,tram):
|
||||
tram.pc=self.label.address
|
||||
|
||||
def toString(self):
|
||||
return super().toString() + "GOTO "+self.label.toString()
|
||||
|
||||
class ifzero(Instruction):
|
||||
def __init__(self, label, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.label=label
|
||||
|
||||
def execute(self,tram):
|
||||
if tram.stack[tram.top]==0:
|
||||
tram.pc=self.label.address
|
||||
else:
|
||||
tram.pc=tram.pc+1
|
||||
tram.pop()
|
||||
|
||||
def toString(self):
|
||||
return super().toString() + "IFZERO "+self.label.toString()
|
||||
|
||||
class invoke(Instruction):
|
||||
def __init__(self,n,label,d, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
self.n=n
|
||||
self.label=label
|
||||
self.d=d
|
||||
|
||||
def execute(self,tram):
|
||||
tmp_top=tram.top
|
||||
tram.push(tram.pc+1)
|
||||
tram.push(tram.pp)
|
||||
tram.push(tram.fp)
|
||||
tram.push(tram.spp(self.d,tram.pp,tram.fp))
|
||||
tram.push(tram.sfp(self.d,tram.pp,tram.fp))
|
||||
tram.pp=tmp_top-self.n+1
|
||||
tram.fp=tmp_top+1
|
||||
tram.pc=self.label.address
|
||||
|
||||
def toString(self):
|
||||
return super().toString() \
|
||||
+ "INVOKE "+str(self.n)+" "+self.label.toString()+" "+str(self.d)
|
||||
|
||||
class ireturn(Instruction):
|
||||
def __init__(self, assigned_label=None):
|
||||
super().__init__(assigned_label=assigned_label)
|
||||
|
||||
def execute(self,tram):
|
||||
res=tram.stack[tram.top]
|
||||
tram.top=tram.pp
|
||||
tram.pc=tram.stack[tram.fp]
|
||||
tram.pp=tram.stack[tram.fp+1]
|
||||
tram.fp=tram.stack[tram.fp+2]
|
||||
del tram.stack[tram.top:]
|
||||
tram.top=tram.top-1
|
||||
tram.push(res)
|
||||
|
||||
def toString(self): return super().toString() + "RETURN"
|
||||
|
||||
Reference in New Issue
Block a user