basinterp.py revision 4479
14479Sbinkertn@umich.edu# This file provides the runtime support for running a basic program 24479Sbinkertn@umich.edu# Assumes the program has been parsed using basparse.py 34479Sbinkertn@umich.edu 44479Sbinkertn@umich.eduimport sys 54479Sbinkertn@umich.eduimport math 64479Sbinkertn@umich.eduimport random 74479Sbinkertn@umich.edu 84479Sbinkertn@umich.educlass BasicInterpreter: 94479Sbinkertn@umich.edu 104479Sbinkertn@umich.edu # Initialize the interpreter. prog is a dictionary 114479Sbinkertn@umich.edu # containing (line,statement) mappings 124479Sbinkertn@umich.edu def __init__(self,prog): 134479Sbinkertn@umich.edu self.prog = prog 144479Sbinkertn@umich.edu 154479Sbinkertn@umich.edu self.functions = { # Built-in function table 164479Sbinkertn@umich.edu 'SIN' : lambda z: math.sin(self.eval(z)), 174479Sbinkertn@umich.edu 'COS' : lambda z: math.cos(self.eval(z)), 184479Sbinkertn@umich.edu 'TAN' : lambda z: math.tan(self.eval(z)), 194479Sbinkertn@umich.edu 'ATN' : lambda z: math.atan(self.eval(z)), 204479Sbinkertn@umich.edu 'EXP' : lambda z: math.exp(self.eval(z)), 214479Sbinkertn@umich.edu 'ABS' : lambda z: abs(self.eval(z)), 224479Sbinkertn@umich.edu 'LOG' : lambda z: math.log(self.eval(z)), 234479Sbinkertn@umich.edu 'SQR' : lambda z: math.sqrt(self.eval(z)), 244479Sbinkertn@umich.edu 'INT' : lambda z: int(self.eval(z)), 254479Sbinkertn@umich.edu 'RND' : lambda z: random.random() 264479Sbinkertn@umich.edu } 274479Sbinkertn@umich.edu 284479Sbinkertn@umich.edu # Collect all data statements 294479Sbinkertn@umich.edu def collect_data(self): 304479Sbinkertn@umich.edu self.data = [] 314479Sbinkertn@umich.edu for lineno in self.stat: 324479Sbinkertn@umich.edu if self.prog[lineno][0] == 'DATA': 334479Sbinkertn@umich.edu self.data = self.data + self.prog[lineno][1] 344479Sbinkertn@umich.edu self.dc = 0 # Initialize the data counter 354479Sbinkertn@umich.edu 364479Sbinkertn@umich.edu # Check for end statements 374479Sbinkertn@umich.edu def check_end(self): 384479Sbinkertn@umich.edu has_end = 0 394479Sbinkertn@umich.edu for lineno in self.stat: 404479Sbinkertn@umich.edu if self.prog[lineno][0] == 'END' and not has_end: 414479Sbinkertn@umich.edu has_end = lineno 424479Sbinkertn@umich.edu if not has_end: 434479Sbinkertn@umich.edu print "NO END INSTRUCTION" 444479Sbinkertn@umich.edu self.error = 1 454479Sbinkertn@umich.edu if has_end != lineno: 464479Sbinkertn@umich.edu print "END IS NOT LAST" 474479Sbinkertn@umich.edu self.error = 1 484479Sbinkertn@umich.edu 494479Sbinkertn@umich.edu # Check loops 504479Sbinkertn@umich.edu def check_loops(self): 514479Sbinkertn@umich.edu for pc in range(len(self.stat)): 524479Sbinkertn@umich.edu lineno = self.stat[pc] 534479Sbinkertn@umich.edu if self.prog[lineno][0] == 'FOR': 544479Sbinkertn@umich.edu forinst = self.prog[lineno] 554479Sbinkertn@umich.edu loopvar = forinst[1] 564479Sbinkertn@umich.edu for i in range(pc+1,len(self.stat)): 574479Sbinkertn@umich.edu if self.prog[self.stat[i]][0] == 'NEXT': 584479Sbinkertn@umich.edu nextvar = self.prog[self.stat[i]][1] 594479Sbinkertn@umich.edu if nextvar != loopvar: continue 604479Sbinkertn@umich.edu self.loopend[pc] = i 614479Sbinkertn@umich.edu break 624479Sbinkertn@umich.edu else: 634479Sbinkertn@umich.edu print "FOR WITHOUT NEXT AT LINE" % self.stat[pc] 644479Sbinkertn@umich.edu self.error = 1 654479Sbinkertn@umich.edu 664479Sbinkertn@umich.edu # Evaluate an expression 674479Sbinkertn@umich.edu def eval(self,expr): 684479Sbinkertn@umich.edu etype = expr[0] 694479Sbinkertn@umich.edu if etype == 'NUM': return expr[1] 704479Sbinkertn@umich.edu elif etype == 'GROUP': return self.eval(expr[1]) 714479Sbinkertn@umich.edu elif etype == 'UNARY': 724479Sbinkertn@umich.edu if expr[1] == '-': return -self.eval(expr[2]) 734479Sbinkertn@umich.edu elif etype == 'BINOP': 744479Sbinkertn@umich.edu if expr[1] == '+': return self.eval(expr[2])+self.eval(expr[3]) 754479Sbinkertn@umich.edu elif expr[1] == '-': return self.eval(expr[2])-self.eval(expr[3]) 764479Sbinkertn@umich.edu elif expr[1] == '*': return self.eval(expr[2])*self.eval(expr[3]) 774479Sbinkertn@umich.edu elif expr[1] == '/': return float(self.eval(expr[2]))/self.eval(expr[3]) 784479Sbinkertn@umich.edu elif expr[1] == '^': return abs(self.eval(expr[2]))**self.eval(expr[3]) 794479Sbinkertn@umich.edu elif etype == 'VAR': 804479Sbinkertn@umich.edu var,dim1,dim2 = expr[1] 814479Sbinkertn@umich.edu if not dim1 and not dim2: 824479Sbinkertn@umich.edu if self.vars.has_key(var): 834479Sbinkertn@umich.edu return self.vars[var] 844479Sbinkertn@umich.edu else: 854479Sbinkertn@umich.edu print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc] 864479Sbinkertn@umich.edu raise RuntimeError 874479Sbinkertn@umich.edu # May be a list lookup or a function evaluation 884479Sbinkertn@umich.edu if dim1 and not dim2: 894479Sbinkertn@umich.edu if self.functions.has_key(var): 904479Sbinkertn@umich.edu # A function 914479Sbinkertn@umich.edu return self.functions[var](dim1) 924479Sbinkertn@umich.edu else: 934479Sbinkertn@umich.edu # A list evaluation 944479Sbinkertn@umich.edu if self.lists.has_key(var): 954479Sbinkertn@umich.edu dim1val = self.eval(dim1) 964479Sbinkertn@umich.edu if dim1val < 1 or dim1val > len(self.lists[var]): 974479Sbinkertn@umich.edu print "LIST INDEX OUT OF BOUNDS AT LINE", self.stat[self.pc] 984479Sbinkertn@umich.edu raise RuntimeError 994479Sbinkertn@umich.edu return self.lists[var][dim1val-1] 1004479Sbinkertn@umich.edu if dim1 and dim2: 1014479Sbinkertn@umich.edu if self.tables.has_key(var): 1024479Sbinkertn@umich.edu dim1val = self.eval(dim1) 1034479Sbinkertn@umich.edu dim2val = self.eval(dim2) 1044479Sbinkertn@umich.edu if dim1val < 1 or dim1val > len(self.tables[var]) or dim2val < 1 or dim2val > len(self.tables[var][0]): 1054479Sbinkertn@umich.edu print "TABLE INDEX OUT OUT BOUNDS AT LINE", self.stat[self.pc] 1064479Sbinkertn@umich.edu raise RuntimeError 1074479Sbinkertn@umich.edu return self.tables[var][dim1val-1][dim2val-1] 1084479Sbinkertn@umich.edu print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc] 1094479Sbinkertn@umich.edu raise RuntimeError 1104479Sbinkertn@umich.edu 1114479Sbinkertn@umich.edu # Evaluate a relational expression 1124479Sbinkertn@umich.edu def releval(self,expr): 1134479Sbinkertn@umich.edu etype = expr[1] 1144479Sbinkertn@umich.edu lhs = self.eval(expr[2]) 1154479Sbinkertn@umich.edu rhs = self.eval(expr[3]) 1164479Sbinkertn@umich.edu if etype == '<': 1174479Sbinkertn@umich.edu if lhs < rhs: return 1 1184479Sbinkertn@umich.edu else: return 0 1194479Sbinkertn@umich.edu 1204479Sbinkertn@umich.edu elif etype == '<=': 1214479Sbinkertn@umich.edu if lhs <= rhs: return 1 1224479Sbinkertn@umich.edu else: return 0 1234479Sbinkertn@umich.edu 1244479Sbinkertn@umich.edu elif etype == '>': 1254479Sbinkertn@umich.edu if lhs > rhs: return 1 1264479Sbinkertn@umich.edu else: return 0 1274479Sbinkertn@umich.edu 1284479Sbinkertn@umich.edu elif etype == '>=': 1294479Sbinkertn@umich.edu if lhs >= rhs: return 1 1304479Sbinkertn@umich.edu else: return 0 1314479Sbinkertn@umich.edu 1324479Sbinkertn@umich.edu elif etype == '=': 1334479Sbinkertn@umich.edu if lhs == rhs: return 1 1344479Sbinkertn@umich.edu else: return 0 1354479Sbinkertn@umich.edu 1364479Sbinkertn@umich.edu elif etype == '<>': 1374479Sbinkertn@umich.edu if lhs != rhs: return 1 1384479Sbinkertn@umich.edu else: return 0 1394479Sbinkertn@umich.edu 1404479Sbinkertn@umich.edu # Assignment 1414479Sbinkertn@umich.edu def assign(self,target,value): 1424479Sbinkertn@umich.edu var, dim1, dim2 = target 1434479Sbinkertn@umich.edu if not dim1 and not dim2: 1444479Sbinkertn@umich.edu self.vars[var] = self.eval(value) 1454479Sbinkertn@umich.edu elif dim1 and not dim2: 1464479Sbinkertn@umich.edu # List assignment 1474479Sbinkertn@umich.edu dim1val = self.eval(dim1) 1484479Sbinkertn@umich.edu if not self.lists.has_key(var): 1494479Sbinkertn@umich.edu self.lists[var] = [0]*10 1504479Sbinkertn@umich.edu 1514479Sbinkertn@umich.edu if dim1val > len(self.lists[var]): 1524479Sbinkertn@umich.edu print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc] 1534479Sbinkertn@umich.edu raise RuntimeError 1544479Sbinkertn@umich.edu self.lists[var][dim1val-1] = self.eval(value) 1554479Sbinkertn@umich.edu elif dim1 and dim2: 1564479Sbinkertn@umich.edu dim1val = self.eval(dim1) 1574479Sbinkertn@umich.edu dim2val = self.eval(dim2) 1584479Sbinkertn@umich.edu if not self.tables.has_key(var): 1594479Sbinkertn@umich.edu temp = [0]*10 1604479Sbinkertn@umich.edu v = [] 1614479Sbinkertn@umich.edu for i in range(10): v.append(temp[:]) 1624479Sbinkertn@umich.edu self.tables[var] = v 1634479Sbinkertn@umich.edu # Variable already exists 1644479Sbinkertn@umich.edu if dim1val > len(self.tables[var]) or dim2val > len(self.tables[var][0]): 1654479Sbinkertn@umich.edu print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc] 1664479Sbinkertn@umich.edu raise RuntimeError 1674479Sbinkertn@umich.edu self.tables[var][dim1val-1][dim2val-1] = self.eval(value) 1684479Sbinkertn@umich.edu 1694479Sbinkertn@umich.edu # Change the current line number 1704479Sbinkertn@umich.edu def goto(self,linenum): 1714479Sbinkertn@umich.edu if not self.prog.has_key(linenum): 1724479Sbinkertn@umich.edu print "UNDEFINED LINE NUMBER %d AT LINE %d" % (linenum, self.stat[self.pc]) 1734479Sbinkertn@umich.edu raise RuntimeError 1744479Sbinkertn@umich.edu self.pc = self.stat.index(linenum) 1754479Sbinkertn@umich.edu 1764479Sbinkertn@umich.edu # Run it 1774479Sbinkertn@umich.edu def run(self): 1784479Sbinkertn@umich.edu self.vars = { } # All variables 1794479Sbinkertn@umich.edu self.lists = { } # List variables 1804479Sbinkertn@umich.edu self.tables = { } # Tables 1814479Sbinkertn@umich.edu self.loops = [ ] # Currently active loops 1824479Sbinkertn@umich.edu self.loopend= { } # Mapping saying where loops end 1834479Sbinkertn@umich.edu self.gosub = None # Gosub return point (if any) 1844479Sbinkertn@umich.edu self.error = 0 # Indicates program error 1854479Sbinkertn@umich.edu 1864479Sbinkertn@umich.edu self.stat = self.prog.keys() # Ordered list of all line numbers 1874479Sbinkertn@umich.edu self.stat.sort() 1884479Sbinkertn@umich.edu self.pc = 0 # Current program counter 1894479Sbinkertn@umich.edu 1904479Sbinkertn@umich.edu # Processing prior to running 1914479Sbinkertn@umich.edu 1924479Sbinkertn@umich.edu self.collect_data() # Collect all of the data statements 1934479Sbinkertn@umich.edu self.check_end() 1944479Sbinkertn@umich.edu self.check_loops() 1954479Sbinkertn@umich.edu 1964479Sbinkertn@umich.edu if self.error: raise RuntimeError 1974479Sbinkertn@umich.edu 1984479Sbinkertn@umich.edu while 1: 1994479Sbinkertn@umich.edu line = self.stat[self.pc] 2004479Sbinkertn@umich.edu instr = self.prog[line] 2014479Sbinkertn@umich.edu 2024479Sbinkertn@umich.edu op = instr[0] 2034479Sbinkertn@umich.edu 2044479Sbinkertn@umich.edu # END and STOP statements 2054479Sbinkertn@umich.edu if op == 'END' or op == 'STOP': 2064479Sbinkertn@umich.edu break # We're done 2074479Sbinkertn@umich.edu 2084479Sbinkertn@umich.edu # GOTO statement 2094479Sbinkertn@umich.edu elif op == 'GOTO': 2104479Sbinkertn@umich.edu newline = instr[1] 2114479Sbinkertn@umich.edu self.goto(newline) 2124479Sbinkertn@umich.edu continue 2134479Sbinkertn@umich.edu 2144479Sbinkertn@umich.edu # PRINT statement 2154479Sbinkertn@umich.edu elif op == 'PRINT': 2164479Sbinkertn@umich.edu plist = instr[1] 2174479Sbinkertn@umich.edu out = "" 2184479Sbinkertn@umich.edu for label,val in plist: 2194479Sbinkertn@umich.edu if out: 2204479Sbinkertn@umich.edu out += ' '*(15 - (len(out) % 15)) 2214479Sbinkertn@umich.edu out += label 2224479Sbinkertn@umich.edu if val: 2234479Sbinkertn@umich.edu if label: out += " " 2244479Sbinkertn@umich.edu eval = self.eval(val) 2254479Sbinkertn@umich.edu out += str(eval) 2264479Sbinkertn@umich.edu sys.stdout.write(out) 2274479Sbinkertn@umich.edu end = instr[2] 2284479Sbinkertn@umich.edu if not (end == ',' or end == ';'): 2294479Sbinkertn@umich.edu sys.stdout.write("\n") 2304479Sbinkertn@umich.edu if end == ',': sys.stdout.write(" "*(15-(len(out) % 15))) 2314479Sbinkertn@umich.edu if end == ';': sys.stdout.write(" "*(3-(len(out) % 3))) 2324479Sbinkertn@umich.edu 2334479Sbinkertn@umich.edu # LET statement 2344479Sbinkertn@umich.edu elif op == 'LET': 2354479Sbinkertn@umich.edu target = instr[1] 2364479Sbinkertn@umich.edu value = instr[2] 2374479Sbinkertn@umich.edu self.assign(target,value) 2384479Sbinkertn@umich.edu 2394479Sbinkertn@umich.edu # READ statement 2404479Sbinkertn@umich.edu elif op == 'READ': 2414479Sbinkertn@umich.edu for target in instr[1]: 2424479Sbinkertn@umich.edu if self.dc < len(self.data): 2434479Sbinkertn@umich.edu value = ('NUM',self.data[self.dc]) 2444479Sbinkertn@umich.edu self.assign(target,value) 2454479Sbinkertn@umich.edu self.dc += 1 2464479Sbinkertn@umich.edu else: 2474479Sbinkertn@umich.edu # No more data. Program ends 2484479Sbinkertn@umich.edu return 2494479Sbinkertn@umich.edu elif op == 'IF': 2504479Sbinkertn@umich.edu relop = instr[1] 2514479Sbinkertn@umich.edu newline = instr[2] 2524479Sbinkertn@umich.edu if (self.releval(relop)): 2534479Sbinkertn@umich.edu self.goto(newline) 2544479Sbinkertn@umich.edu continue 2554479Sbinkertn@umich.edu 2564479Sbinkertn@umich.edu elif op == 'FOR': 2574479Sbinkertn@umich.edu loopvar = instr[1] 2584479Sbinkertn@umich.edu initval = instr[2] 2594479Sbinkertn@umich.edu finval = instr[3] 2604479Sbinkertn@umich.edu stepval = instr[4] 2614479Sbinkertn@umich.edu 2624479Sbinkertn@umich.edu # Check to see if this is a new loop 2634479Sbinkertn@umich.edu if not self.loops or self.loops[-1][0] != self.pc: 2644479Sbinkertn@umich.edu # Looks like a new loop. Make the initial assignment 2654479Sbinkertn@umich.edu newvalue = initval 2664479Sbinkertn@umich.edu self.assign((loopvar,None,None),initval) 2674479Sbinkertn@umich.edu if not stepval: stepval = ('NUM',1) 2684479Sbinkertn@umich.edu stepval = self.eval(stepval) # Evaluate step here 2694479Sbinkertn@umich.edu self.loops.append((self.pc,stepval)) 2704479Sbinkertn@umich.edu else: 2714479Sbinkertn@umich.edu # It's a repeat of the previous loop 2724479Sbinkertn@umich.edu # Update the value of the loop variable according to the step 2734479Sbinkertn@umich.edu stepval = ('NUM',self.loops[-1][1]) 2744479Sbinkertn@umich.edu newvalue = ('BINOP','+',('VAR',(loopvar,None,None)),stepval) 2754479Sbinkertn@umich.edu 2764479Sbinkertn@umich.edu if self.loops[-1][1] < 0: relop = '>=' 2774479Sbinkertn@umich.edu else: relop = '<=' 2784479Sbinkertn@umich.edu if not self.releval(('RELOP',relop,newvalue,finval)): 2794479Sbinkertn@umich.edu # Loop is done. Jump to the NEXT 2804479Sbinkertn@umich.edu self.pc = self.loopend[self.pc] 2814479Sbinkertn@umich.edu self.loops.pop() 2824479Sbinkertn@umich.edu else: 2834479Sbinkertn@umich.edu self.assign((loopvar,None,None),newvalue) 2844479Sbinkertn@umich.edu 2854479Sbinkertn@umich.edu elif op == 'NEXT': 2864479Sbinkertn@umich.edu if not self.loops: 2874479Sbinkertn@umich.edu print "NEXT WITHOUT FOR AT LINE",line 2884479Sbinkertn@umich.edu return 2894479Sbinkertn@umich.edu 2904479Sbinkertn@umich.edu nextvar = instr[1] 2914479Sbinkertn@umich.edu self.pc = self.loops[-1][0] 2924479Sbinkertn@umich.edu loopinst = self.prog[self.stat[self.pc]] 2934479Sbinkertn@umich.edu forvar = loopinst[1] 2944479Sbinkertn@umich.edu if nextvar != forvar: 2954479Sbinkertn@umich.edu print "NEXT DOESN'T MATCH FOR AT LINE", line 2964479Sbinkertn@umich.edu return 2974479Sbinkertn@umich.edu continue 2984479Sbinkertn@umich.edu elif op == 'GOSUB': 2994479Sbinkertn@umich.edu newline = instr[1] 3004479Sbinkertn@umich.edu if self.gosub: 3014479Sbinkertn@umich.edu print "ALREADY IN A SUBROUTINE AT LINE", line 3024479Sbinkertn@umich.edu return 3034479Sbinkertn@umich.edu self.gosub = self.stat[self.pc] 3044479Sbinkertn@umich.edu self.goto(newline) 3054479Sbinkertn@umich.edu continue 3064479Sbinkertn@umich.edu 3074479Sbinkertn@umich.edu elif op == 'RETURN': 3084479Sbinkertn@umich.edu if not self.gosub: 3094479Sbinkertn@umich.edu print "RETURN WITHOUT A GOSUB AT LINE",line 3104479Sbinkertn@umich.edu return 3114479Sbinkertn@umich.edu self.goto(self.gosub) 3124479Sbinkertn@umich.edu self.gosub = None 3134479Sbinkertn@umich.edu 3144479Sbinkertn@umich.edu elif op == 'FUNC': 3154479Sbinkertn@umich.edu fname = instr[1] 3164479Sbinkertn@umich.edu pname = instr[2] 3174479Sbinkertn@umich.edu expr = instr[3] 3184479Sbinkertn@umich.edu def eval_func(pvalue,name=pname,self=self,expr=expr): 3194479Sbinkertn@umich.edu self.assign((pname,None,None),pvalue) 3204479Sbinkertn@umich.edu return self.eval(expr) 3214479Sbinkertn@umich.edu self.functions[fname] = eval_func 3224479Sbinkertn@umich.edu 3234479Sbinkertn@umich.edu elif op == 'DIM': 3244479Sbinkertn@umich.edu for vname,x,y in instr[1]: 3254479Sbinkertn@umich.edu if y == 0: 3264479Sbinkertn@umich.edu # Single dimension variable 3274479Sbinkertn@umich.edu self.lists[vname] = [0]*x 3284479Sbinkertn@umich.edu else: 3294479Sbinkertn@umich.edu # Double dimension variable 3304479Sbinkertn@umich.edu temp = [0]*y 3314479Sbinkertn@umich.edu v = [] 3324479Sbinkertn@umich.edu for i in range(x): 3334479Sbinkertn@umich.edu v.append(temp[:]) 3344479Sbinkertn@umich.edu self.tables[vname] = v 3354479Sbinkertn@umich.edu 3364479Sbinkertn@umich.edu self.pc += 1 3374479Sbinkertn@umich.edu 3384479Sbinkertn@umich.edu # Utility functions for program listing 3394479Sbinkertn@umich.edu def expr_str(self,expr): 3404479Sbinkertn@umich.edu etype = expr[0] 3414479Sbinkertn@umich.edu if etype == 'NUM': return str(expr[1]) 3424479Sbinkertn@umich.edu elif etype == 'GROUP': return "(%s)" % self.expr_str(expr[1]) 3434479Sbinkertn@umich.edu elif etype == 'UNARY': 3444479Sbinkertn@umich.edu if expr[1] == '-': return "-"+str(expr[2]) 3454479Sbinkertn@umich.edu elif etype == 'BINOP': 3464479Sbinkertn@umich.edu return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3])) 3474479Sbinkertn@umich.edu elif etype == 'VAR': 3484479Sbinkertn@umich.edu return self.var_str(expr[1]) 3494479Sbinkertn@umich.edu 3504479Sbinkertn@umich.edu def relexpr_str(self,expr): 3514479Sbinkertn@umich.edu return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3])) 3524479Sbinkertn@umich.edu 3534479Sbinkertn@umich.edu def var_str(self,var): 3544479Sbinkertn@umich.edu varname,dim1,dim2 = var 3554479Sbinkertn@umich.edu if not dim1 and not dim2: return varname 3564479Sbinkertn@umich.edu if dim1 and not dim2: return "%s(%s)" % (varname, self.expr_str(dim1)) 3574479Sbinkertn@umich.edu return "%s(%s,%s)" % (varname, self.expr_str(dim1),self.expr_str(dim2)) 3584479Sbinkertn@umich.edu 3594479Sbinkertn@umich.edu # Create a program listing 3604479Sbinkertn@umich.edu def list(self): 3614479Sbinkertn@umich.edu stat = self.prog.keys() # Ordered list of all line numbers 3624479Sbinkertn@umich.edu stat.sort() 3634479Sbinkertn@umich.edu for line in stat: 3644479Sbinkertn@umich.edu instr = self.prog[line] 3654479Sbinkertn@umich.edu op = instr[0] 3664479Sbinkertn@umich.edu if op in ['END','STOP','RETURN']: 3674479Sbinkertn@umich.edu print line, op 3684479Sbinkertn@umich.edu continue 3694479Sbinkertn@umich.edu elif op == 'REM': 3704479Sbinkertn@umich.edu print line, instr[1] 3714479Sbinkertn@umich.edu elif op == 'PRINT': 3724479Sbinkertn@umich.edu print line, op, 3734479Sbinkertn@umich.edu first = 1 3744479Sbinkertn@umich.edu for p in instr[1]: 3754479Sbinkertn@umich.edu if not first: print ",", 3764479Sbinkertn@umich.edu if p[0] and p[1]: print '"%s"%s' % (p[0],self.expr_str(p[1])), 3774479Sbinkertn@umich.edu elif p[1]: print self.expr_str(p[1]), 3784479Sbinkertn@umich.edu else: print '"%s"' % (p[0],), 3794479Sbinkertn@umich.edu first = 0 3804479Sbinkertn@umich.edu if instr[2]: print instr[2] 3814479Sbinkertn@umich.edu else: print 3824479Sbinkertn@umich.edu elif op == 'LET': 3834479Sbinkertn@umich.edu print line,"LET",self.var_str(instr[1]),"=",self.expr_str(instr[2]) 3844479Sbinkertn@umich.edu elif op == 'READ': 3854479Sbinkertn@umich.edu print line,"READ", 3864479Sbinkertn@umich.edu first = 1 3874479Sbinkertn@umich.edu for r in instr[1]: 3884479Sbinkertn@umich.edu if not first: print ",", 3894479Sbinkertn@umich.edu print self.var_str(r), 3904479Sbinkertn@umich.edu first = 0 3914479Sbinkertn@umich.edu print "" 3924479Sbinkertn@umich.edu elif op == 'IF': 3934479Sbinkertn@umich.edu print line,"IF %s THEN %d" % (self.relexpr_str(instr[1]),instr[2]) 3944479Sbinkertn@umich.edu elif op == 'GOTO' or op == 'GOSUB': 3954479Sbinkertn@umich.edu print line, op, instr[1] 3964479Sbinkertn@umich.edu elif op == 'FOR': 3974479Sbinkertn@umich.edu print line,"FOR %s = %s TO %s" % (instr[1],self.expr_str(instr[2]),self.expr_str(instr[3])), 3984479Sbinkertn@umich.edu if instr[4]: print "STEP %s" % (self.expr_str(instr[4])), 3994479Sbinkertn@umich.edu print 4004479Sbinkertn@umich.edu elif op == 'NEXT': 4014479Sbinkertn@umich.edu print line,"NEXT", instr[1] 4024479Sbinkertn@umich.edu elif op == 'FUNC': 4034479Sbinkertn@umich.edu print line,"DEF %s(%s) = %s" % (instr[1],instr[2],self.expr_str(instr[3])) 4044479Sbinkertn@umich.edu elif op == 'DIM': 4054479Sbinkertn@umich.edu print line,"DIM", 4064479Sbinkertn@umich.edu first = 1 4074479Sbinkertn@umich.edu for vname,x,y in instr[1]: 4084479Sbinkertn@umich.edu if not first: print ",", 4094479Sbinkertn@umich.edu first = 0 4104479Sbinkertn@umich.edu if y == 0: 4114479Sbinkertn@umich.edu print "%s(%d)" % (vname,x), 4124479Sbinkertn@umich.edu else: 4134479Sbinkertn@umich.edu print "%s(%d,%d)" % (vname,x,y), 4144479Sbinkertn@umich.edu 4154479Sbinkertn@umich.edu print 4164479Sbinkertn@umich.edu elif op == 'DATA': 4174479Sbinkertn@umich.edu print line,"DATA", 4184479Sbinkertn@umich.edu first = 1 4194479Sbinkertn@umich.edu for v in instr[1]: 4204479Sbinkertn@umich.edu if not first: print ",", 4214479Sbinkertn@umich.edu first = 0 4224479Sbinkertn@umich.edu print v, 4234479Sbinkertn@umich.edu print 4244479Sbinkertn@umich.edu 4254479Sbinkertn@umich.edu # Erase the current program 4264479Sbinkertn@umich.edu def new(self): 4274479Sbinkertn@umich.edu self.prog = {} 4284479Sbinkertn@umich.edu 4294479Sbinkertn@umich.edu # Insert statements 4304479Sbinkertn@umich.edu def add_statements(self,prog): 4314479Sbinkertn@umich.edu for line,stat in prog.items(): 4324479Sbinkertn@umich.edu self.prog[line] = stat 4334479Sbinkertn@umich.edu 4344479Sbinkertn@umich.edu # Delete a statement 4354479Sbinkertn@umich.edu def del_line(self,lineno): 4364479Sbinkertn@umich.edu try: 4374479Sbinkertn@umich.edu del self.prog[lineno] 4384479Sbinkertn@umich.edu except KeyError: 4394479Sbinkertn@umich.edu pass 4404479Sbinkertn@umich.edu 441