basinterp.py
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· Python 代码 · 共 441 行 · 第 1/2 页
PY
441 行
# This file provides the runtime support for running a basic program# Assumes the program has been parsed using basparse.pyimport sysimport mathimport randomclass BasicInterpreter: # Initialize the interpreter. prog is a dictionary # containing (line,statement) mappings def __init__(self,prog): self.prog = prog self.functions = { # Built-in function table 'SIN' : lambda z: math.sin(self.eval(z)), 'COS' : lambda z: math.cos(self.eval(z)), 'TAN' : lambda z: math.tan(self.eval(z)), 'ATN' : lambda z: math.atan(self.eval(z)), 'EXP' : lambda z: math.exp(self.eval(z)), 'ABS' : lambda z: abs(self.eval(z)), 'LOG' : lambda z: math.log(self.eval(z)), 'SQR' : lambda z: math.sqrt(self.eval(z)), 'INT' : lambda z: int(self.eval(z)), 'RND' : lambda z: random.random() } # Collect all data statements def collect_data(self): self.data = [] for lineno in self.stat: if self.prog[lineno][0] == 'DATA': self.data = self.data + self.prog[lineno][1] self.dc = 0 # Initialize the data counter # Check for end statements def check_end(self): has_end = 0 for lineno in self.stat: if self.prog[lineno][0] == 'END' and not has_end: has_end = lineno if not has_end: print "NO END INSTRUCTION" self.error = 1 if has_end != lineno: print "END IS NOT LAST" self.error = 1 # Check loops def check_loops(self): for pc in range(len(self.stat)): lineno = self.stat[pc] if self.prog[lineno][0] == 'FOR': forinst = self.prog[lineno] loopvar = forinst[1] for i in range(pc+1,len(self.stat)): if self.prog[self.stat[i]][0] == 'NEXT': nextvar = self.prog[self.stat[i]][1] if nextvar != loopvar: continue self.loopend[pc] = i break else: print "FOR WITHOUT NEXT AT LINE" % self.stat[pc] self.error = 1 # Evaluate an expression def eval(self,expr): etype = expr[0] if etype == 'NUM': return expr[1] elif etype == 'GROUP': return self.eval(expr[1]) elif etype == 'UNARY': if expr[1] == '-': return -self.eval(expr[2]) elif etype == 'BINOP': if expr[1] == '+': return self.eval(expr[2])+self.eval(expr[3]) elif expr[1] == '-': return self.eval(expr[2])-self.eval(expr[3]) elif expr[1] == '*': return self.eval(expr[2])*self.eval(expr[3]) elif expr[1] == '/': return float(self.eval(expr[2]))/self.eval(expr[3]) elif expr[1] == '^': return abs(self.eval(expr[2]))**self.eval(expr[3]) elif etype == 'VAR': var,dim1,dim2 = expr[1] if not dim1 and not dim2: if self.vars.has_key(var): return self.vars[var] else: print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc] raise RuntimeError # May be a list lookup or a function evaluation if dim1 and not dim2: if self.functions.has_key(var): # A function return self.functions[var](dim1) else: # A list evaluation if self.lists.has_key(var): dim1val = self.eval(dim1) if dim1val < 1 or dim1val > len(self.lists[var]): print "LIST INDEX OUT OF BOUNDS AT LINE", self.stat[self.pc] raise RuntimeError return self.lists[var][dim1val-1] if dim1 and dim2: if self.tables.has_key(var): dim1val = self.eval(dim1) dim2val = self.eval(dim2) if dim1val < 1 or dim1val > len(self.tables[var]) or dim2val < 1 or dim2val > len(self.tables[var][0]): print "TABLE INDEX OUT OUT BOUNDS AT LINE", self.stat[self.pc] raise RuntimeError return self.tables[var][dim1val-1][dim2val-1] print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc] raise RuntimeError # Evaluate a relational expression def releval(self,expr): etype = expr[1] lhs = self.eval(expr[2]) rhs = self.eval(expr[3]) if etype == '<': if lhs < rhs: return 1 else: return 0 elif etype == '<=': if lhs <= rhs: return 1 else: return 0 elif etype == '>': if lhs > rhs: return 1 else: return 0 elif etype == '>=': if lhs >= rhs: return 1 else: return 0 elif etype == '=': if lhs == rhs: return 1 else: return 0 elif etype == '<>': if lhs != rhs: return 1 else: return 0 # Assignment def assign(self,target,value): var, dim1, dim2 = target if not dim1 and not dim2: self.vars[var] = self.eval(value) elif dim1 and not dim2: # List assignment dim1val = self.eval(dim1) if not self.lists.has_key(var): self.lists[var] = [0]*10 if dim1val > len(self.lists[var]): print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc] raise RuntimeError self.lists[var][dim1val-1] = self.eval(value) elif dim1 and dim2: dim1val = self.eval(dim1) dim2val = self.eval(dim2) if not self.tables.has_key(var): temp = [0]*10 v = [] for i in range(10): v.append(temp[:]) self.tables[var] = v # Variable already exists if dim1val > len(self.tables[var]) or dim2val > len(self.tables[var][0]): print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc] raise RuntimeError self.tables[var][dim1val-1][dim2val-1] = self.eval(value) # Change the current line number def goto(self,linenum): if not self.prog.has_key(linenum): print "UNDEFINED LINE NUMBER %d AT LINE %d" % (linenum, self.stat[self.pc]) raise RuntimeError self.pc = self.stat.index(linenum) # Run it def run(self): self.vars = { } # All variables self.lists = { } # List variables self.tables = { } # Tables self.loops = [ ] # Currently active loops self.loopend= { } # Mapping saying where loops end self.gosub = None # Gosub return point (if any) self.error = 0 # Indicates program error self.stat = self.prog.keys() # Ordered list of all line numbers self.stat.sort() self.pc = 0 # Current program counter # Processing prior to running self.collect_data() # Collect all of the data statements self.check_end() self.check_loops() if self.error: raise RuntimeError while 1: line = self.stat[self.pc] instr = self.prog[line] op = instr[0] # END and STOP statements if op == 'END' or op == 'STOP': break # We're done # GOTO statement elif op == 'GOTO': newline = instr[1] self.goto(newline) continue # PRINT statement elif op == 'PRINT': plist = instr[1] out = "" for label,val in plist: if out: out += ' '*(15 - (len(out) % 15)) out += label
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?