WIP : Add THEN to disambigute from "and"

This commit is contained in:
rocky
2016-12-27 04:57:58 -05:00
parent 0ff0c97a95
commit 6c546fe6e1
5 changed files with 130 additions and 38 deletions

View File

@@ -101,10 +101,10 @@ class Scanner2(scan.Scanner):
Token = self.Token # shortcut
n = self.setup_code(co)
codelen = self.setup_code(co)
self.build_lines_data(co, n)
self.build_prev_op(n)
self.build_lines_data(co, codelen)
self.build_prev_op(codelen)
free, names, varnames = self.unmangle_code_names(co, classname)
self.names = names
@@ -113,7 +113,7 @@ class Scanner2(scan.Scanner):
# turn 'LOAD_GLOBAL' to 'LOAD_ASSERT'.
# 'LOAD_ASSERT' is used in assert statements.
self.load_asserts = set()
for i in self.op_range(0, n):
for i in self.op_range(0, codelen):
# We need to detect the difference between:
# raise AssertionError
# and
@@ -138,7 +138,7 @@ class Scanner2(scan.Scanner):
last_stmt = self.next_stmt[0]
i = self.next_stmt[last_stmt]
replace = {}
while i < n-1:
while i < codelen - 1:
if self.lines[last_stmt].next > i:
# Distinguish "print ..." from "print ...,"
if self.code[last_stmt] == self.opc.PRINT_ITEM:
@@ -150,7 +150,7 @@ class Scanner2(scan.Scanner):
i = self.next_stmt[i]
extended_arg = 0
for offset in self.op_range(0, n):
for offset in self.op_range(0, codelen):
if offset in jump_targets:
jump_idx = 0
# We want to process COME_FROMs to the same offset to be in *descending*
@@ -176,6 +176,7 @@ class Scanner2(scan.Scanner):
offset="%s_%d" % (offset, jump_idx),
has_arg = True))
jump_idx += 1
pass
op = self.code[offset]
op_name = self.opc.opname[op]
@@ -675,6 +676,8 @@ class Scanner2(scan.Scanner):
self.fixed_jumps[offset] = rtarget
return
jump_if_offset = offset
start = offset+3
pre = self.prev
@@ -827,20 +830,86 @@ class Scanner2(scan.Scanner):
jump_target = self.get_target(next_offset, next_op)
if jump_target in self.setup_loops:
self.structs.append({'type': 'while-loop',
'start': start - 3,
'start': jump_if_offset,
'end': jump_target})
self.fixed_jumps[start-3] = jump_target
self.fixed_jumps[jump_if_offset] = jump_target
return
end = self.restrict_to_parent(if_end, parent)
self.structs.append({'type': 'if-then',
'start': start-3,
'end': pre_rtarget})
if_then_maybe = None
if 2.2 <= self.version <= 2.6:
# Take the JUMP_IF target. In an "if/then", it will be
# a POP_TOP instruction and the instruction before it
# will be a JUMP_FORWARD to just after the POP_TOP.
# For example:
# Good:
# 3 JUMP_IF_FALSE 33 'to 39'
# ..
# 36 JUMP_FORWARD 1 'to 40'
# 39 POP_TOP
# 40 ...
# example:
# BAD (is an "and"):
# 28 JUMP_IF_FALSE 4 'to 35'
# ...
# 32 JUMP_ABSOLUTE 40 'to 40' # should be 36 or there should
# # be a COME_FROM at the pop top
# # before 40 to 35
# 35 POP_TOP
# 36 ...
# 39 POP_TOP
# 39_0 COME_FROM 3
# 40 ...
if self.opc.opname[code[jump_if_offset]].startswith('JUMP_IF'):
jump_if_target = code[jump_if_offset+1]
if self.opc.opname[code[jump_if_target + jump_if_offset + 3]] == 'POP_TOP':
jump_inst = jump_if_target + jump_if_offset
jump_offset = code[jump_inst+1]
jump_op = self.opc.opname[code[jump_inst]]
if (jump_op == 'JUMP_FORWARD' and jump_offset == 1):
self.structs.append({'type': 'if-then',
'start': start-3,
'end': pre_rtarget})
self.thens[start] = end
elif jump_op == 'JUMP_ABSOLUTE':
if_then_maybe = {'type': 'if-then',
'start': start-3,
'end': pre_rtarget}
elif self.version == 2.7:
self.structs.append({'type': 'if-then',
'start': start-3,
'end': pre_rtarget})
self.not_continue.add(pre_rtarget)
if rtarget < end:
# We have an "else" block of some kind.
# Is it associated with "if_then_maybe" seen above?
# These will be linked in this funny way:
# 198 JUMP_IF_FALSE 18 'to 219'
# 201 POP_TOP
# ...
# 216 JUMP_ABSOLUTE 256 'to 256'
# 219 POP_TOP
# ...
# 252 JUMP_FORWARD 1 'to 256'
# 255 POP_TOP
# 256
if if_then_maybe and jump_op == 'JUMP_ABSOLUTE':
jump_target = self.get_target(jump_inst, code[jump_inst])
if self.opc.opname[code[end]] == 'JUMP_FORWARD':
end_target = self.get_target(end, code[end])
if jump_target == end_target:
self.structs.append(if_then_maybe)
self.thens[start] = end
self.structs.append({'type': 'else',
'start': rtarget,
'end': end})
@@ -849,6 +918,7 @@ class Scanner2(scan.Scanner):
self.structs.append({'type': 'if-then',
'start': start,
'end': rtarget})
self.thens[start] = rtarget
if self.version == 2.7 or code[pre_rtarget+1] != self.opc.JUMP_FORWARD:
self.return_end_ifs.add(pre_rtarget)
@@ -887,6 +957,7 @@ class Scanner2(scan.Scanner):
self.return_end_ifs = set()
self.setup_loop_targets = {} # target given setup_loop offset
self.setup_loops = {} # setup_loop offset given target
self.thens = {} # JUMP_IF's that separate the 'then' part of an 'if'
targets = {}
for offset in self.op_range(0, n):