Пример #1
0
def _while(env, args):
    if len(args) < 2:
        raise CompileTimeError, 'while -- Missing blocks %r' % args
    pred = args[0]
    codes = args[1:]

    # create some labels
    loop_start_label = NewLabel('loop_start')
    loop_next_label = NewLabel('loop_next')
    loop_end_label = NewLabel('loop_end')
    env.while_stack.append((loop_start_label, loop_end_label))

    env.emit(tac.label(loop_start_label))
    # emit code for looping
    tmp_pred = env.eval_(pred)
    if not tmp_pred.can_cast_to_type('int'):
        print 'WARNING: while -- casting %r to boolean type' % tmp_pred
        env.print_block()

    # loop labels
    env.emit(tac.cbranch(tmp_pred.tacn, loop_next_label))
    env.emit(tac.branch(loop_end_label))
    env.emit(tac.label(loop_next_label))

    ret_val = env.exec_block(codes)  # XXX: the block need to know how to jump
                                     # out of this loop! hmm... a stack?
    env.emit(tac.branch(loop_start_label))
    env.emit(tac.label(loop_end_label))
    env.while_stack.pop()  # remove while stack
    # while should not have a return value... things should be changed
    # by side effects. this is what loops are intended to do
    return obtype.Token('void')
Пример #2
0
def _cond(env, args):
    to_ret = []

    # tac preparations
    pred_labels = [NewLabel('case') for i in xrange(len(args))]
    block_labels = [NewLabel('iftrue') for i in xrange(len(args))]
    else_label = NewLabel('else')
    final_label = NewLabel('final')
    final_result = NewVar()

    # for each predicate and code block:
    for i, pred_todo in enumerate(args):
        if len(pred_todo) == 1:  # no todo?
            raise CompileTimeError, 'cond -- Missing code block '\
                    'after predicate %r' % (pred_todo)
        pred = pred_todo[0]
        codes = pred_todo[1:]

        # XXX: here i dont check whether the else is placed at the last
        if isinstance(pred, obtype.Token) and pred.symbolp() \
                and pred.n == 'else':  # is else
            env.emit(tac.label(else_label))
            ret_val = env.exec_block(codes)
            env.emit(tac.assign(final_result, ret_val.tacn))

        else:  # is predcate
            if i != 0:
                env.emit(tac.label(pred_labels[i]))  # at case i

            pred = env.eval_(pred)  # eval and emit code block
            if not pred.can_cast_to_type('int'):
                print 'WARNING: cond -- casting %r to boolean type' % pred
                env.print_block()

            env.emit(tac.cbranch(pred.tacn, block_labels[i]))  # if true
            if i == len(args) - 1:
                # is the last case. XXX: somehow dirty..
                env.emit(tac.branch(final_label))
            elif isinstance(args[i + 1][0], obtype.Token) and \
                    args[i + 1][0].n == 'else':
                env.emit(tac.branch(else_label))
            else:  # still have more cases to check
                env.emit(tac.branch(pred_labels[i + 1]))

            env.emit(tac.label(block_labels[i]))  # exec block
            ret_val = env.exec_block(codes)
            env.emit(tac.assign(final_result, ret_val.tacn))
            env.emit(tac.branch(final_label))

        to_ret.append(ret_val)

    # cond over, the final label
    env.emit(tac.label(final_label))

    if not to_ret:
        return obtype.Token('void')
    else:
        first = to_ret[0]
        first.tacn = final_result  # it's created on the fly so dont worry 
                                   # about the side effect ^ ^
        for item in to_ret:
            if not first.can_cast_to(item):
                print 'WARNING: cond -- returning different types: %r %r' % (
                        first, item)
                env.print_block()
        return first