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
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
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
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
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