next_test = Label() |
next_test = Label() |
Compare(Code.DUP_TOP, [('exception match', typ)], code) |
Compare(Code.DUP_TOP, [('exception match', typ)], code) |
code( |
code( |
next_test.JUMP_IF_FALSE, Code.POP_TOP, # remove condition |
next_test.JUMP_IF_FALSE_OR_POP, # remove condition |
Code.POP_TOP, Code.POP_TOP, Code.POP_TOP, # remove exc info |
Code.POP_TOP, Code.POP_TOP, Code.POP_TOP, # remove exc info |
handler |
handler |
) |
) |
return cond, then, else_ |
return cond, then, else_ |
else_clause = Label() |
else_clause = Label() |
end_if = Label() |
end_if = Label() |
code(cond, else_clause.JUMP_IF_FALSE, Code.POP_TOP, then) |
code(cond, else_clause.JUMP_IF_FALSE_OR_POP, then) |
if code.stack_size is not None: |
if code.stack_size is not None: |
end_if.JUMP_FORWARD(code) |
end_if.JUMP_FORWARD(code) |
code(else_clause, Code.POP_TOP, else_, end_if) |
code(else_clause, Code.POP_TOP, else_, end_if) |
code.DUP_TOP() |
code.DUP_TOP() |
code.ROT_THREE() |
code.ROT_THREE() |
code.COMPARE_OP(op) |
code.COMPARE_OP(op) |
fail.JUMP_IF_FALSE(code) |
fail.JUMP_IF_FALSE_OR_POP(code) |
code.POP_TOP() |
|
op, arg = ops[-1] |
op, arg = ops[-1] |
code(arg) |
code(arg) |
code.COMPARE_OP(op) |
code.COMPARE_OP(op) |
|
|
|
|
|
|
|
|
nodetype() |
nodetype() |
def And(values, code=None): |
def And(values, code=None): |
if code is None: |
if code is None: |
if const_value(value): |
if const_value(value): |
continue # true constants can be skipped |
continue # true constants can be skipped |
except NotAConstant: # but non-constants require code |
except NotAConstant: # but non-constants require code |
code(value, end.JUMP_IF_FALSE, Code.POP_TOP) |
code(value, end.JUMP_IF_FALSE_OR_POP) |
else: # and false constants end the chain right away |
else: # and false constants end the chain right away |
return code(value, end) |
return code(value, end) |
code(values[-1], end) |
code(values[-1], end) |
if not const_value(value): |
if not const_value(value): |
continue # false constants can be skipped |
continue # false constants can be skipped |
except NotAConstant: # but non-constants require code |
except NotAConstant: # but non-constants require code |
code(value, end.JUMP_IF_TRUE, Code.POP_TOP) |
code(value, end.JUMP_IF_TRUE_OR_POP) |
else: # and true constants end the chain right away |
else: # and true constants end the chain right away |
return code(value, end) |
return code(value, end) |
code(values[-1], end) |
code(values[-1], end) |
self.stack_size += 2 |
self.stack_size += 2 |
else: |
else: |
old_level = self.stack_size |
old_level = self.stack_size |
|
self.stack_size -= (op in (JUMP_IF_TRUE_OR_POP, JUMP_IF_FALSE_OR_POP)) |
posn = self.here() |
posn = self.here() |
|
|
if arg is not None: |
if arg is not None: |
self.stackchange((2,1)) |
self.stackchange((2,1)) |
self.emit_arg(COMPARE_OP, compares[op]) |
self.emit_arg(COMPARE_OP, compares[op]) |
|
|
|
|
def setup_block(self, op): |
def setup_block(self, op): |
jmp = self.jump(op) |
jmp = self.jump(op) |
self.blocks.append((op,self.stack_size,jmp)) |
self.blocks.append((op,self.stack_size,jmp)) |
self.POP_TOP() |
self.POP_TOP() |
return lbl |
return lbl |
globals()['JUMP_IF_TRUE_OR_POP'] = -1 |
globals()['JUMP_IF_TRUE_OR_POP'] = -1 |
else: |
|
pass # XXX implement branching stack effects for JUMP_IF_TRUE_OR_POP |
|
|
|
if 'JUMP_IF_FALSE_OR_POP' not in opcode: |
if 'JUMP_IF_FALSE_OR_POP' not in opcode: |
def JUMP_IF_FALSE_OR_POP(self, address=None): |
def JUMP_IF_FALSE_OR_POP(self, address=None): |
self.POP_TOP() |
self.POP_TOP() |
return lbl |
return lbl |
globals()['JUMP_IF_FALSE_OR_POP'] = -1 |
globals()['JUMP_IF_FALSE_OR_POP'] = -1 |
else: |
|
pass # XXX implement branching stack effects for JUMP_IF_FALSE_OR_POP |
|
|
|
if 'JUMP_IF_TRUE' not in opcode: |
if 'JUMP_IF_TRUE' not in opcode: |
def JUMP_IF_TRUE(self, address=None): |
def JUMP_IF_TRUE(self, address=None): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def assert_loop(self): |
def assert_loop(self): |
for why,level,fwd in self.blocks: |
for why,level,fwd in self.blocks: |
if why==SETUP_LOOP: |
if why==SETUP_LOOP: |
s, op, arg, jump, end = instructions[i+1] |
s, op, arg, jump, end = instructions[i+1] |
print ['JUMP_IF_FALSE', 'JUMP_IF_TRUE'][op==POP_JUMP_IF_TRUE].ljust(15), |
print ['JUMP_IF_FALSE', 'JUMP_IF_TRUE'][op==POP_JUMP_IF_TRUE].ljust(15), |
i+=1 |
i+=1 |
|
elif op in (JUMP_IF_TRUE_OR_POP, JUMP_IF_FALSE_OR_POP): |
|
print opname[op][:-7].ljust(15), |
else: |
else: |
print opname[op].ljust(15), |
print opname[op].ljust(15), |
if jump is not None: |
if jump is not None: |
if op in argtype: |
if op in argtype: |
print '(%s)' % (locals()[argtype[op]][arg]), |
print '(%s)' % (locals()[argtype[op]][arg]), |
print |
print |
|
if op in (JUMP_IF_TRUE_OR_POP, JUMP_IF_FALSE_OR_POP): |
|
print ' ', ''.ljust(7), 'POP_TOP' |
i+=1 |
i+=1 |
|
|
|
|
|
|
|
|
|
|
class _se: |
class _se: |
"""Quick way of defining static stack effects of opcodes""" |
"""Quick way of defining static stack effects of opcodes""" |
POP_TOP = END_FINALLY = POP_JUMP_IF_FALSE = POP_JUMP_IF_TRUE = 1,0 |
POP_TOP = END_FINALLY = POP_JUMP_IF_FALSE = POP_JUMP_IF_TRUE = 1,0 |
ROT_THREE = 3,3 |
ROT_THREE = 3,3 |
ROT_FOUR = 4,4 |
ROT_FOUR = 4,4 |
DUP_TOP = 1,2 |
DUP_TOP = 1,2 |
|
|
UNARY_POSITIVE = UNARY_NEGATIVE = UNARY_NOT = UNARY_CONVERT = \ |
UNARY_POSITIVE = UNARY_NEGATIVE = UNARY_NOT = UNARY_CONVERT = \ |
UNARY_INVERT = GET_ITER = LOAD_ATTR = IMPORT_FROM = 1,1 |
UNARY_INVERT = GET_ITER = LOAD_ATTR = IMPORT_FROM = 1,1 |
|
|
LOAD_CLOSURE = LOAD_DEREF = IMPORT_NAME = BUILD_MAP = 0,1 |
LOAD_CLOSURE = LOAD_DEREF = IMPORT_NAME = BUILD_MAP = 0,1 |
|
|
EXEC_STMT = BUILD_CLASS = 3,0 |
EXEC_STMT = BUILD_CLASS = 3,0 |
JUMP_IF_TRUE = JUMP_IF_FALSE = 1,1 |
JUMP_IF_TRUE = JUMP_IF_FALSE = \ |
|
JUMP_IF_TRUE_OR_POP = JUMP_IF_FALSE_OR_POP = 1,1 |
|
|
if sys.version>="2.5": |
if sys.version>="2.5": |
_se.YIELD_VALUE = 1, 1 |
_se.YIELD_VALUE = 1, 1 |