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 + -
显示快捷键?