示例#1
0
def _num_minus(env, args):
    op = env.curr_evaling[0]  # XXX: to know the op
    retval = obtype.Token('int')
    retval.tacn = NewVar()
    env.emit(tac.assign(retval.tacn, 0))

    sll = 0
    if len(args) != 0:
        arg = args[0]
        arg = env.eval_(arg)
        if not arg.can_cast_to_type('int'):
            sll = obtype.sizeof_byshift(arg.vt)
            retval.vt = arg.vt
        env.emit(tac.assign(retval.tacn, arg.tacn))

    for arg in args[1:]:
        arg = env.eval_(arg)
        if not arg.can_cast_to_type('int'):
            print 'WARNING: op %r -- argument must be number -- %r' % (
                    op, arg)
            env.print_block()
        if sll != 0:
            tmp = NewVar()
            env.emit(tac.binary(tmp, arg.tacn, '<<', sll))
        else:
            tmp = arg.tacn
        env.emit(tac.binary(retval.tacn, retval.tacn, op.n, tmp))
    return retval
示例#2
0
def _num_sumall(env, args):
    retval = obtype.Token('int')
    retval.tacn = NewVar()
    env.emit(tac.assign(retval.tacn, 1))
    for arg in args:
        arg = env.eval_(arg)
        if not arg.can_cast_to_type('int'):
            print 'WARNING: op *, argument must be number at * -- %r' % arg
            env.print_block()
        env.emit(tac.binary(retval.tacn, retval.tacn, '*', arg.tacn))
    return retval
示例#3
0
    def setitem(self, key, value):
        if not key.symbolp():
            raise CompileTimeError, '%r is not a symbol' % key

        var = self.lookup(key)
        if not value.can_cast_to(var):  # type check: this might be good
            print 'WARNING: casting from %r to %r' % (value, var)
            self.print_block()
        var.v = value.v  # asm
        var.p = value.p  # for easy func call check
        self.emit(tac.assign(var.tacn, value.tacn))  # var := value
示例#4
0
    def eval_(self, expr):
        self.curr_evaling = expr
        if isinstance(expr, list):
            car = expr[0]
            #self.curr_evaling = expr[:2]  # to show more info
            cdr = expr[1:]
            if not isinstance(car, obtype.Token):  # error handling
                raise CompileTimeError, 'not a callable: %r' % car
            if car.symbolp():  # look parent and find that
                f = self.lookup(car)
                if 'macro' in f.__dict__:
                    return self.eval_macro(f, cdr)
                else:
                    return self.eval_func(f, cdr)

            elif car.keywordp():  # look keyword
                try:  # user-defined symbol can shadow the builtin funcs
                    f = self.lookup(car)
                    return self.eval_func(f, cdr)
                except:
                    f = self.kw[car.n]
                    return f(self, cdr)
            elif car.typep():  # type conv
                if len(cdr) != 1:
                    raise CompileTimeError, \
                        'type conversion -- too many args: %r' % cdr
                # temporary type conv. must not change the original's type
                # XXX: is it correct?
                to_ret = copy.copy(self.eval_(cdr[0]))
                to_ret.vt = car.vt
                return to_ret
            else:
                raise CompileTimeError, 'eval -- Wrong type to apply: %r' % car
        elif expr.symbolp():
            return self.lookup(expr)  # may lookup parent
        elif expr.immp():
            # attach imm to a var name
            if expr.tacn is None:
                expr.tacn = NewVar()
                self.emit(tac.assign(expr.tacn, expr.v))
            return expr
        else:
            raise CompileTimeError, 'eval -- Unknown type: %r' % expr
示例#5
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