示例#1
0
文件: unwarper.py 项目: zyc9494/ljd
def _unwarp_breaks(start, blocks, next_block):
	blocks_set = set([start] + blocks)

	ends = _gather_possible_ends(next_block)

	breaks = set()

	patched = []

	for i, block in enumerate(blocks):
		warp = block.warp

		if not isinstance(warp, nodes.UnconditionalWarp):
			patched.append(block)
			continue

		target = _get_target(warp)

		if target in blocks_set:
			patched.append(block)
			continue

		assert target in ends, "GOTO statements are not supported"

		if block.warpins_count != 0:
			new_block = _create_next_block(block)
			new_block.warpins_count = block.warpins_count
			_set_flow_to(block, new_block)

			patched.append(block)
			patched.append(new_block)

			block = new_block
		else:
			patched.append(block)

		block.contents.append(nodes.Break())

		if i + 1 == len(blocks):
			_set_end(block)
		else:
			_set_flow_to(block, blocks[i + 1])

		breaks.add(block)

	blocks[:] = patched

	if len(breaks) == 0:
		return

	breaks_stack = []
	warpsout = []
	pending_break = None

	for i, block in enumerate(reversed(blocks)):
		if block in breaks:
			pending_break = None

			if block.warpins_count == 0:
				breaks_stack.append((BREAK_ONE_USE, block))
			else:
				breaks_stack.append((BREAK_INFINITE, block))

			continue

		warp = block.warp

		if not isinstance(warp, nodes.ConditionalWarp):
			if _is_flow(warp):
				pending_break = None

			continue

		target = _get_target(warp)

		if target in blocks_set:
			continue

		assert target in ends, "GOTO statements are not supported"

		if pending_break is None:
			assert len(breaks_stack) > 0

			top_break = breaks_stack[-1]

			_set_target(warp, top_break[1])

			if top_break[0] == BREAK_ONE_USE:
				pending_break = breaks_stack.pop()

				warpsout = []
			else:
				warpsout.append(block)
		else:
			_set_target(warp, pending_break[1])
			warpsout.append(block)

		if len(block.contents) > 0:
			pending_break = None

	while len(breaks_stack) > 0 and breaks_stack[-1][0] == BREAK_INFINITE:
		breaks_stack.pop()

	# And pray for the best...
	while len(warpsout) > 0 and len(breaks_stack) > 0:
		_set_target(warpsout.pop().warp, breaks_stack.pop()[1])
示例#2
0
文件: unwarper.py 项目: zyc9494/ljd
def _unwarp_loop(start, end, body):
	if len(body) > 0:
		last = body[-1]
	else:
		last = start

	if isinstance(start.warp, nodes.IteratorWarp):
		assert isinstance(last.warp, nodes.UnconditionalWarp)
		assert last.warp.target == start

		loop = nodes.IteratorFor()
		loop.statements.contents = body
		loop.identifiers = start.warp.variables
		loop.expressions = start.warp.controls
		loop._addr = body[0].first_address

		_set_flow_to(start, body[0])

	elif isinstance(start.warp, nodes.NumericLoopWarp):
		assert isinstance(last.warp, nodes.UnconditionalWarp)
		assert last.warp.target == start

		loop = nodes.NumericFor()
		loop.statements.contents = body
		loop.variable = start.warp.index
		loop.expressions = start.warp.controls
		loop._addr = body[0].first_address
		_set_flow_to(start, body[0])

	# While (including "while true" and "repeat until false" which will be
	# while true)
	elif isinstance(last.warp, nodes.UnconditionalWarp):
		assert last.warp.target == start

		# while true
		if _is_flow(start.warp):
			loop = nodes.While()
			loop.expression = nodes.Primitive()
			loop.expression.type = nodes.Primitive.T_TRUE

			loop.statements.contents = body
		else:
			# There shouldn't be many problems similar to ifs, as
			# we are processing loops in the order from innermost
			# to outermost
			for i, block in enumerate(body):
				assert len(block.contents) == 0

				if _is_flow(block.warp):
					break

			assert i < len(body)

			expression = [start] + body[:i]
			body = body[i:]

			# Sometimes expression may decide to jump to the
			# outer loop start instead
			_fix_expression(expression, start, end)

			true = body[0]
			false = end

			expression = _compile_expression(expression, None,
								true, false)

			# If something jumps to the start (instead of the end)
			# - that's a nested if
			loop = nodes.While()
			loop.expression = expression
			loop.statements.contents = body

		_fix_nested_ifs(body, start)

		_set_flow_to(start, body[0])

	# Repeat until
	else:
		assert isinstance(last.warp, nodes.ConditionalWarp)
		assert last.warp.false_target == start

		i = len(body) - 1

		while i >= 0:
			block = body[i]
			warp = block.warp

			if _is_flow(warp):
				i += 1
				break

			if len(block.contents) != 0:
				break

			i -= 1

		expression = body[i:]
		body = body[:i + 1]

		assert len(expression) > 0

		first = expression[0]
		if _is_jump(first.warp):
			# Don't append to the body - it already has it
			expression.pop(0)
			body[-1].contents.append(nodes.Break())

		false = body[0]
		# Don't use end as it could be broken by a previous
		# repeat until pass
		true = expression[-1].warp.true_target

		loop = nodes.RepeatUntil()
		loop.expression = _compile_expression(expression, None,
								true, false)

		start_copy = copy.copy(start)
		start.contents = []

		if len(body) > 1:
			_set_flow_to(start_copy, body[1])
		else:
			_set_end(start_copy)

		_set_flow_to(start, start_copy)

		body[0] = start_copy

		loop.statements.contents = body

	return loop