Exemple #1
0
def _build_table_record_item(value):
    item = None
    if value is None:
        item = nodes.Primitive()
        item.type = nodes.Primitive.T_NIL
    elif value is True:
        item = nodes.Primitive()
        item.type = nodes.Primitive.T_TRUE
    elif value is False:
        item = nodes.Primitive()
        item.type = nodes.Primitive.T_FALSE
    elif isinstance(value, int):
        item = nodes.Constant()
        item.value = value
        item.type = nodes.Constant.T_INTEGER
    elif isinstance(value, float):
        item = nodes.Constant()
        item.value = value
        item.type = nodes.Constant.T_FLOAT
    elif isinstance(value, str):
        item = nodes.Constant()
        item.value = value
        item.type = nodes.Constant.T_STRING

    return item
Exemple #2
0
def _fill_massive_refs(info, simple, massive, iterators):
    ref = info.references[1]
    holder = _get_holder(ref.path)

    src = info.assignment.expressions.contents[0]

    assert isinstance(src, (nodes.FunctionCall,
                            nodes.Vararg,
                            nodes.Primitive))
    if isinstance(holder, nodes.Assignment):
        dst = holder.destinations.contents[0]

        assert len(info.references) == 2
        orig = info.references[0].identifier

        assignment = ref.path[-3]

        assert isinstance(assignment, nodes.Assignment)

        massive.append((orig, info.assignment, assignment, dst))
    elif isinstance(holder, nodes.IteratorWarp):
        assert len(info.references) == 2
        iterators.append((info.assignment, src, holder))
    elif isinstance(src, nodes.Primitive) and src.type == src.T_NIL:
        assert len(info.references) == 2

        # Create a new primitive, so it won't mess with the
        # writer's ignore list
        src = nodes.Primitive()
        src.type = nodes.Primitive.T_NIL

        simple.append((info, ref, src))
Exemple #3
0
def _build_primitive(state, value):
    node = nodes.Primitive()

    if value is True or value == T_TRUE:
        node.type = nodes.Primitive.T_TRUE
    elif value is False or value == T_FALSE:
        node.type = nodes.Primitive.T_FALSE
    else:
        assert value is None or value == T_NIL

        node.type = nodes.Primitive.T_NIL

    return node
Exemple #4
0
def insert_table_record(constructor, key, value):
    array = constructor.array.contents
    records = constructor.records.contents

    if isinstance(key, nodes.MULTRES):
        assert len(records) == 0 or\
            isinstance(records[-1], nodes.TableRecord)

        records.append(value)
        return

    while isinstance(key, nodes.Constant) and\
            key.type == key.T_INTEGER and\
            key.value >= 0:
        index = key.value

        if index == 1 and len(array) == 0:
            record = nodes.ArrayRecord()
            record.value = nodes.Primitive()
            record.value.type = nodes.Primitive.T_NIL

            array.append(record)

        if (index > len(array)):
            break

        record = nodes.ArrayRecord()
        record.value = value

        if len(array) == 0 or index == len(array):
            array.append(record)
        else:
            array[index] = record

        return

    record = nodes.TableRecord()
    record.key = key
    record.value = value

    if len(records) == 0:
        records.append(record)
        return

    last = records[-1]

    if isinstance(last, (nodes.FunctionCall, nodes.Vararg)):
        records.insert(-1, record)
    else:
        records.append(record)
Exemple #5
0
def _unwarp_expression(body, end, true, false):
	parts = []

	if true is not None:
		terminator_index = min(true.index, false.index)

		if end is not None:
			terminator_index = min(end.index, terminator_index)
	else:
		assert end is not None

		terminator_index = end.index

	terminators = set((true, false, end))

	subexpression_start = 0

	i = 0
	while i < len(body) - 1:
		block = body[i]
		warp = block.warp

		target = _get_target(warp)

		#
		# A chance for
		# (foo and (bar and y or z)) or x
		# type expressions, because the first "foo and ... )) or" part
		# will be broken by the "or z))" part in the code below.
		#
		# So we are going to intercept subexpressions by it's start
		# instead of an end, but only if we are already at the
		# subexpression start (so nothing formally changes, but creates
		# a bit more correct execution order)
		#
		if target.index < terminator_index:
			if i != subexpression_start:
				i += 1
				continue

			target_index = body.index(target)
			last_block = body[target_index - 1]

			last_block_target = _get_target(last_block.warp)

			if last_block_target.index < terminator_index:
				i += 1
				continue

			assert last_block_target in terminators

			subexpression = body[i:target_index]
		else:
			assert target in terminators

			while i < len(body) - 2:
				next_block = body[i + 1]
				next_target = _get_target(next_block.warp)

				if next_target != target:
					break

				next_inv = _is_inverted(next_block.warp, true, end)

				this_inv = _is_inverted(warp, true, end)

				# Special hack for unary expressions (x, not x)...
				if next_inv != this_inv:
					break

				block = next_block
				warp = next_block.warp
				i += 1

			subexpression = body[subexpression_start:i + 1]

		last_block = subexpression[-1]
		last_block_index = body.index(last_block)

		next_block = body[last_block_index + 1]

		operator = _get_operator(last_block, true, end)

		subexpression = _compile_subexpression(subexpression, operator,
							last_block, next_block,
							true, end)

		parts.append(subexpression)
		parts.append(operator)

		i = last_block_index + 1
		subexpression_start = i

	last = body[-1]

	if isinstance(last.warp, nodes.ConditionalWarp):
		if _is_inverted(last.warp, true, end):
			last = _invert(last.warp.condition)
		else:
			last = last.warp.condition

		parts.append(last)
	else:
		assert isinstance(last.warp, (nodes.EndWarp,
						nodes.UnconditionalWarp))

		src = _get_last_assignment_source(last)

		if src is None:
			src = nodes.Primitive()

			if last.warp.target == true:
				src.type = nodes.Primitive.T_TRUE
			else:
				src.type = nodes.Primitive.T_FALSE

		parts.append(src)

	return parts
Exemple #6
0
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
Exemple #7
0
def insert_table_record(constructor,
                        key,
                        value,
                        replace,
                        allow_duplicates=True):
    array = constructor.array.contents
    records = constructor.records.contents

    if isinstance(key, nodes.MULTRES):
        assert len(records) == 0 \
               or isinstance(records[-1], nodes.TableRecord)

        records.append(value)
        return True

    while isinstance(key, nodes.Constant) \
            and key.type == key.T_INTEGER \
            and key.value >= 0:
        index = key.value

        if index == 1 and len(array) == 0:
            record = nodes.ArrayRecord()
            record.value = nodes.Primitive()
            record.value.type = nodes.Primitive.T_NIL

            array.append(record)

        if index > len(array):
            break

        record = nodes.ArrayRecord()
        record.value = value

        if len(array) == 0 or index == len(array):
            array.append(record)
            return True
        elif replace:
            array[index] = record
            return True
        else:
            current_value = array[index].value
            if isinstance(current_value, nodes.Primitive
                          ) and current_value.type == nodes.Primitive.T_NIL:
                array[index] = record
                return True
            return False

    # Check for record duplicates
    # This isn't nearly as important as duplicate protection with arrays, since both values
    # end up in the table to the user can make sense of what happened. Nonetheless, we should still
    # reject stuff like this.
    if not allow_duplicates:
        for rec in records:
            if isinstance(rec, nodes.TableRecord):
                if is_equal(rec.key, key, strict=False):
                    return False

    record = nodes.TableRecord()
    record.key = key
    record.value = value

    if len(records) == 0:
        records.append(record)
        return True

    last = records[-1]

    if isinstance(last, (nodes.FunctionCall, nodes.Vararg)):
        records.insert(-1, record)
    else:
        records.append(record)

    return True