# (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, d, 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() + "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"