/usr/share/GvRng/stepper.py is in gvrng 4.4-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | '''
Stepper.step steps through one instruction of a GvR program
at a time, and then it calls back into your world
object to actually do MOVE(), TURNLEFT(), etc.
Read TESTstepper.py to grok this.
'''
import translate,sys
class OutOfInstructionsException(Exception):
def __str__(self): return 'Out of instructions'
class InfiniteLoopException(Exception):
pass
class StackFrame:
def __init__(self, block):
self.whichStatement = -1
self.block = block
def nextLineOfCode(self, world):
self.whichStatement += 1
if self.whichStatement < len(self.block.statements):
return self.block.statements[self.whichStatement]
def currLine(obj):
curr = obj.block.statements[obj.whichStatement]
if getBlockFrame(curr):
return ''
else:
lnum = str(curr.line+1).rjust(3)
stat = str(curr.statement)
return ' '+lnum+' '+stat+'\n'
def atEndOfBlock(obj):
return obj.whichStatement >= len(obj.block.statements)
def atNewBlock(obj):
return obj.whichStatement == 0
def checkCondition(obj, world):
methodInWorldClass = getattr(world, obj.condition.statement)
return methodInWorldClass()
def getBlockFrame(block):
blockFrames = {
'DoLoop': DoLoop,
'WhileLoop': WhileLoop,
'IfStatement': IfStatement
}
return blockFrames.get(block.__class__.__name__,None)
class DoLoop:
def __init__(self, doLoop):
self.whichLoop = 0
self.whichStatement = -1
self.block = doLoop.block
self.iterations = int(doLoop.iterator)
def nextLineOfCode(self, world):
self.whichStatement += 1
if atEndOfBlock(self):
self.whichStatement = 0
self.whichLoop += 1
if self.whichLoop < self.iterations:
return self.block.statements[self.whichStatement]
class WhileLoop:
def __init__(self, whileLoop):
self.whichStatement = -1
self.block = whileLoop.block
self.whileLoop = whileLoop
def nextLineOfCode(self, world):
self.whichStatement += 1
if atEndOfBlock(self):
self.whichStatement = 0
if atNewBlock(self):
if not checkCondition(self.whileLoop, world): return
return self.block.statements[self.whichStatement]
class IfStatement:
def __init__(self, ifStatement):
self.whichStatement = -1
self.ifStatement = ifStatement
self.conditionalBlocks = [ifStatement] + ifStatement.elifs
self.block = None
def nextLineOfCode(self, world):
self.whichStatement += 1
if atNewBlock(self):
for conditionalBlock in self.conditionalBlocks:
if checkCondition(conditionalBlock, world):
self.block = conditionalBlock.block
break
if not self.block:
if self.ifStatement.elseObj:
self.block = self.ifStatement.elseObj
else:
return
if atEndOfBlock(self):
return
return self.block.statements[self.whichStatement]
class Stepper:
def __init__(self, gvr, world, debugger=None):
tree = translate.gvrToSyntaxTree(gvr)
self.world = world
self.stack = [StackFrame(tree.block)]
self.funcs = {}
for func in tree.functions:
self.funcs[func.name] = func
self.debugger = debugger
self.infinite_count = 0
def step(self):
self.infinite_count +=1
if self.infinite_count > 9586:
v = self.infinite_count
self.infinite_count = 0
raise InfiniteLoopException,v
lineOfCode = self.nextLineOfCode()
blockFrame = getBlockFrame(lineOfCode)
if blockFrame:
self.enterBlock(blockFrame(lineOfCode))
return
command = lineOfCode.statement
if self.funcs.has_key(command):
self.enterUserDefinedMethod(command)
return
if self.debugger:
self.debugger.setLine(lineOfCode.line)
if lineOfCode.__class__.__name__ == 'Cheat':
self.world.cheat(lineOfCode.statement)
else:
self.doPrimitive(command)
def doPrimitive(self, command):
methodInWorldClass = getattr(self.world, command.upper())
methodInWorldClass()
def enterBlock(self, stackFrame):
self.stack.append(stackFrame)
self.step()
def enterUserDefinedMethod(self, command):
self.enterBlock(StackFrame(self.funcs[command].block))
def stackTrace(self):
trace = 'Line Statement\n'
for frame in self.stack:
trace += currLine(frame)
return trace
def nextLineOfCode(self):
if len(self.stack):
lineOfCode = self.stack[-1].nextLineOfCode(self.world)
if lineOfCode:
return lineOfCode
else:
self.stack.pop()
return self.nextLineOfCode()
else: raise OutOfInstructionsException
|