def visitSLambda(self, n):
     # Creat New Label
     label_name = 'Q' + generate_name("SLambda")
     
     # Recurse on code body
     slambdas = []
     (code, rslambdas) = self.dispatch(n.code, False)
     slambdas += rslambdas
     # Setup fvs list
     fvs_n = generate_name("fvs")
     fvs = []
     # Setup each free variable
     stmts = []
     cnt = 0
     for var in n.free_vars:
         fvs += [Name(var)]
         stmt = make_assign(var, Subscript(Name(fvs_n),
                                           [InjectFrom(INT_t, Const(cnt))]))
         stmts += [stmt]
         cnt += 1
     # Setup list of stmts
     stmts += code.nodes
     # Setup params, appending fvs
     params = []
     params += [fvs_n]
     params += n.params
     #Create SLambdaLabel
     label = SLambdaLabel(label_name, len(params))
     # Create new closed slambda
     slambdas += [SLambda(params, StmtList(stmts), label_name)]
     # Return Call and list of SLambdas
     return (InjectFrom(BIG_t, CallCREATECLOSURE([label, List(fvs)])), slambdas)
 def explicateBinary(self, lhsexpr, rhsexpr, smallFunc, smallType, bigFunc, bigType):
     lhsname = generate_name('let_binexp_lhs')
     rhsname = generate_name('let_binexp_rhs')
     lhsvar = Name(lhsname)
     rhsvar = Name(rhsname)
     t = mono_Let(lhsvar,
                  self.dispatch(lhsexpr),
                  mono_Let(rhsvar,
                           self.dispatch(rhsexpr),
                           # Small-Small Case
                           IfExp(And([Or([mono_IsTag(BOOL_t, lhsvar),
                                          mono_IsTag(INT_t, lhsvar)]),
                                      Or([mono_IsTag(BOOL_t, rhsvar),
                                          mono_IsTag(INT_t, rhsvar)])]),
                                 mono_InjectFrom(smallType,
                                                 smallFunc((self.projectType(lhsvar),
                                                            self.projectType(rhsvar)))),
                                 # Big-Big Case
                                 IfExp(And([mono_IsTag(BIG_t, lhsvar),
                                            mono_IsTag(BIG_t, rhsvar)]),
                                       mono_InjectFrom(bigType,
                                                       bigFunc([self.projectType(lhsvar),
                                                                self.projectType(rhsvar)])),
                                       # Mixed Case
                                       # TODO: Add mixed case logic
                                       CallTERROR([])))))
     return t
 def visitCallFunc(self, n, target):
     instrList = []
     args = []
     for arg in n.args:
         if isinstance(arg, SLambdaLabel):
             name = generate_name("instrsel_SLamdaLabel")
             numargs = 0
             temp = VarLLVM(LocalLLVM(name), DEFAULTTYPE)
             arg_types = LLVMFuncPtrType(DEFAULTTYPE, DEFAULTTYPE, arg.numargs)
             value = VarLLVM(GlobalLLVM(arg.name),arg_types)
             instrList += [ptrtointLLVM(temp, value, DEFAULTTYPE)]
             args += [temp]
         elif isinstance(arg, String):
             stringArray = LLVMArray(len(arg.string) + 1, I8)
             actualString = LLVMString(stringArray, arg.string)
             tmp = VarLLVM(GlobalLLVM(generate_name("stringName")), stringArray)
             stringDeclare = declareLLVMString(tmp, actualString)
             self.stringsInstr += [stringDeclare]
             placeholder = VarLLVM(LocalLLVM(generate_name("cast")), PI8)
             cast = getelementptrLLVM(placeholder, tmp, [DEFAULTZERO, DEFAULTZERO])
             instrList += [cast]
             args += [placeholder]
         else:
             args += [self.dispatch(arg)]
     instrList += [callLLVM(DEFAULTTYPE, GlobalLLVM(n.node.name), args, target)]
     return instrList
 def explicateBinary(self, lhsexpr, rhsexpr,
                     smallFunc, smallType,
                     bigFunc, bigType,
                     mixedDefault, op=None):
     lhsname = generate_name('let_binexp_lhs')
     rhsname = generate_name('let_binexp_rhs')
     lhsvar = Name(lhsname)
     rhsvar = Name(rhsname)
     t = Let(lhsvar,
             self.dispatch(lhsexpr),
             Let(rhsvar,
                 self.dispatch(rhsexpr),
                 # Small-Small Case
                 IfExp(And([Or([IsTag(BOOL_t, lhsvar),
                                IsTag(INT_t, lhsvar)]),
                            Or([IsTag(BOOL_t, rhsvar),
                                IsTag(INT_t, rhsvar)])]),
                       InjectFrom(smallType,  
                                  (smallFunc((self.projectType(lhsvar),
                                             self.projectType(rhsvar))))
                                  if op==None else 
                                  (smallFunc(op,
                                             (self.projectType(lhsvar),
                                              self.projectType(rhsvar))))),
                       # Big-Big Case
                       IfExp(And([IsTag(BIG_t, lhsvar),
                                  IsTag(BIG_t, rhsvar)]),
                             InjectFrom(bigType,
                                        bigFunc([self.projectType(lhsvar),
                                                 self.projectType(rhsvar)])),
                             # Mixed Case
                             mixedDefault))))
     return t
 def visitmono_IntUnarySub(self, n, needs_to_be_simple):
     (expr,ss) = self.dispatch(n.expr, True)
     if needs_to_be_simple:
         tmp = generate_name('usubtmp')
         return (Name(tmp), ss + [make_assign(tmp, mono_IntUnarySub(expr))])
     else:
         return (mono_IntUnarySub(expr), ss)
 def visitLambda(self, n, renaming):
     new_renaming = copy.deepcopy(renaming)
     local_vars = n.args
     for v in local_vars:
         new_renaming[v] = generate_name(v)        
     return Lambda([new_renaming[x] for x in n.args],
                   self.dispatch(n.expr, new_renaming))
 def visitLet(self, n, renaming):
     new_renaming = copy.deepcopy(renaming)
     new_renaming[n.var] = generate_name(n.var.name)
     var  = self.dispatch(n.var, new_renaming)
     rhs  = self.dispatch(n.rhs, renaming)
     body = self.dispatch(n.body, new_renaming)
     return Let(var, rhs, body)
def specializeCallFunc(self, n):
    if isinstance(n.node, Name) and n.node.name in RESERVED_NAMES:
        return CallFunc(self.dispatch(n.node), map(self.dispatch, n.args))
    ftemp = generate_name('func')
    def gen_arg(args, vals):
        if args:
            temp = generate_name('arg')
            return Let(Name(temp), self.dispatch(args[0]), gen_arg(args[1:], 
                                                                   vals + [Name(temp)]))
        else:
            objtemp = generate_name('obj')
            initemp = generate_name('ini')
            discardtemp = generate_name('discard')
            return IfExp(CallISCLASS([Name(ftemp)]),
                         Let(Name(objtemp), CallCREATEOBJECT([Name(ftemp)]),
                             IfExp(CallHASATTR([Name(ftemp), String('__init__')]),
                                   Let(Name(discardtemp),
                                       CallFunc(CallGETFUNCTION([GetAttr(Name(ftemp), '__init__')]), 
                                                [Name(objtemp)]+vals),
                                       Name(objtemp)),
                                   Name(objtemp))),
                         IfExp(CallISBOUNDMETHOD([Name(ftemp)]),
                               CallFunc(CallGETFUNCTION([Name(ftemp)]), 
                                        [CallGETRECEIVER([Name(ftemp)])]+vals),
                               IfExp(CallISUNBOUNDMETHOD([Name(ftemp)]),
                                     CallFunc(CallGETFUNCTION([Name(ftemp)]), vals),
                                     CallFunc(Name(ftemp), vals))))
    return Let(Name(ftemp), self.dispatch(n.node), gen_arg(n.args, []))
 def visitSubscriptAssign(self, n):
     name = generate_name('sub')
     return Discard(Let(Name(name), 
                        self.dispatch(n.value),
                        CallSETSUB([self.dispatch(n.target),
                                    self.dispatch(n.subs[0]),
                                    Name(name)])))
 def visitIntCmp(self, n, needs_to_be_simple):
     (left, ss1) = self.dispatch(n.left, True)
     (right, ss2) = self.dispatch(n.right, True)
     if needs_to_be_simple:
         tmp = generate_name('intequaltmp')
         return (Name(tmp), ss1 + ss2 + [make_assign(tmp, IntCmp(n.op, (left, right)))])
     else:
         return (IntCmp(n.op, (left, right)), ss1 + ss2)
 def visitFunction(self, n, renaming):
     new_renaming = copy.deepcopy(renaming)
     local_vars = FindLocalsVisitor().preorder(n.code) | set(n.args)
     for v in local_vars:
         new_renaming[v] = generate_name(v)
     return Function(renaming[n.name],
                     [new_renaming[x] for x in n.args],
                     self.dispatch(n.code, new_renaming))
 def visitmono_IntNotEqual(self, n, needs_to_be_simple):
     (left, ss1) = self.dispatch(n.left, True)
     (right, ss2) = self.dispatch(n.right, True)
     if needs_to_be_simple:
         tmp = generate_name('intnotequaltmp')
         return (Name(tmp), ss1 + ss2 + [make_assign(tmp, mono_IntNotEqual((left, right)))])
     else:
         return (mono_IntNotEqual((left, right)), ss1 + ss2)
 def visitClass(self, n, scope):
     classtemp = generate_name(n.name + '_temp')
     bases = map(self.dispatch, n.bases)
     stmts = [VarAssign(classtemp, 
                        CallCREATECLASS([List(bases)]))]
     stmts += DeclassifyVisitor(classtemp, self).preorder(n.code, scope).nodes
     stmts += [VarAssign(n.name, Name(classtemp))]
     return stmts
def fixMemToMem(instrs, colors):

    regTempPrefix = "RegTmp"

    def validNode(val):
        return isinstance(val, Var86)

    def name(val):
        if isinstance(val, Var86):
            return val.name
        else:
            raise Exception("Attempting to get name of invalid argument: " + str(val))

    def addTemp(instr, tmp):
        if(isinstance(instr, Add86)):
            return [Move86(instr.value, tmp),
                    Add86(tmp, instr.target)]
        elif(isinstance(instr, Sub86)):
            return [Move86(instr.value, tmp),
                    Sub86(tmp, instr.target)]
        elif(isinstance(instr, Move86)):
            return [Move86(instr.value, tmp),
                    Move86(tmp, instr.target)]
        elif(isinstance(instr, Comp86)):
            return [Move86(instr.value, tmp),
                    Comp86(tmp, instr.target)]
        else:
            raise Exception("Cannot add temp to node: " + str(instr))
    
    fixedInstrs = []
    regOnlyVars = []

    #Loop through instructions
    for instr in instrs:
        
        # Binary read/write
        if(isinstance(instr, Add86) or
           isinstance(instr, Sub86) or
           isinstance(instr, Move86) or
           isinstance(instr, Comp86)):
            if(validNode(instr.target) and 
               validNode(instr.value)):
                # Find mem to mem operations
                if((colors[name(instr.target)] >= len(REGCOLORS)) and
                   (colors[name(instr.value)] >= len(REGCOLORS))):
                    # Add temp var
                    tmp = Var86(generate_name(regTempPrefix))
                    fixedInstrs += addTemp(instr, tmp)
                    regOnlyVars += [tmp.name]
                else:
                    fixedInstrs += [instr]
            else:
                fixedInstrs += [instr]
        else:
            fixedInstrs += [instr]

    return (fixedInstrs, regOnlyVars)
 def visitUnarySub(self, n):
     varname = generate_name('let_us_expr')
     exprvar = Name(varname)
     t = mono_Let(exprvar,
                  self.dispatch(n.expr),
                  IfExp(Or([mono_IsTag(INT_t, exprvar),
                            mono_IsTag(BOOL_t, exprvar)]),
                        mono_InjectFrom(INT_t, mono_IntUnarySub(mono_ProjectTo(INT_t, exprvar))),
                        CallTERROR([])))
     return t
 def visitIndirectCallFunc(self, n, target):
     args = []
     instrList = []
     for arg in n.args:
         args += [self.dispatch(arg)]
     arg_types = LLVMFuncPtrType(DEFAULTTYPE, DEFAULTTYPE, len(n.args))
     tmp = VarLLVM(LocalLLVM(generate_name("inttoptrConversion")), DEFAULTTYPE)
     instrList += [inttoptrLLVM(tmp, VarLLVM(LocalLLVM(n.node.name), DEFAULTTYPE), arg_types)]
     instrList += [callLLVM(DEFAULTTYPE, getArg(tmp), args, target)]
     return instrList
 def visitUnarySub(self, n):
     varname = generate_name('let_us_expr')
     exprvar = Name(varname)
     t = Let(exprvar,
             self.dispatch(n.expr),
             IfExp(IsTag(INT_t, exprvar),
                   InjectFrom(INT_t, IntUnarySub(ProjectTo(INT_t, exprvar))),
                   IfExp(IsTag(BOOL_t, exprvar),
                         InjectFrom(INT_t, IntUnarySub(ProjectTo(BOOL_t, exprvar))),
                         CallGERROR([]))))
     return t
 def visitDict(self, n, needs_to_be_simple):
     myss = []
     # Create new Dict
     (expr, ss) = self.dispatch(CallINJECTBIG([CallMAKEDICT([])]), needs_to_be_simple)
     myss += ss
     # Add each dict memeber
     for item in n.items:
         valname = generate_name('item')
         myss += self.dispatch(Discard(Let(Name(valname),
                                           item[1],
                                           CallSETSUB([expr, item[0], Name(valname)]))))   
     return (expr, myss)
 def visitCallFunc(self, n, needs_to_be_simple):
     if isinstance(n.node, Name):
         args_sss = [self.dispatch(arg, True) for arg in n.args]
         args = [arg for (arg,ss) in args_sss]
         ss = reduce(lambda a,b: a + b, [ss for (arg,ss) in args_sss], [])
         if needs_to_be_simple:
             tmp = generate_name('callfunctmp')
             return (Name(tmp), ss + [make_assign(tmp, CallFunc(n.node, args))])
         else:
             return (CallFunc(n.node, args), ss)
     else:
         raise Exception('flatten: only calls to named functions allowed')
 def gen_arg(args, vals):
     if args:
         temp = generate_name('arg')
         return Let(Name(temp), self.dispatch(args[0]), gen_arg(args[1:], 
                                                                vals + [Name(temp)]))
     else:
         objtemp = generate_name('obj')
         initemp = generate_name('ini')
         discardtemp = generate_name('discard')
         return IfExp(CallISCLASS([Name(ftemp)]),
                      Let(Name(objtemp), CallCREATEOBJECT([Name(ftemp)]),
                          IfExp(CallHASATTR([Name(ftemp), String('__init__')]),
                                Let(Name(discardtemp),
                                    CallFunc(CallGETFUNCTION([GetAttr(Name(ftemp), '__init__')]), 
                                             [Name(objtemp)]+vals),
                                    Name(objtemp)),
                                Name(objtemp))),
                      IfExp(CallISBOUNDMETHOD([Name(ftemp)]),
                            CallFunc(CallGETFUNCTION([Name(ftemp)]), 
                                     [CallGETRECEIVER([Name(ftemp)])]+vals),
                            IfExp(CallISUNBOUNDMETHOD([Name(ftemp)]),
                                  CallFunc(CallGETFUNCTION([Name(ftemp)]), vals),
                                  CallFunc(Name(ftemp), vals))))
 def visitIndirectCallFunc(self, n):
     slambdas = []
     (node, rslambdas) = self.dispatch(n.node)
     slambdas += rslambdas
     args = []
     for arg in n.args:
         (rarg, rslambdas) = self.dispatch(arg)
         args += [rarg]
         slambdas += rslambdas
     tmpname = generate_name('let_ICF')
     tmpvar = Name(tmpname)
     t = Let(tmpvar, node, IndirectCallFunc(CallGETFUNPTR([tmpvar]),
                                            ([CallGETFREEVARS([tmpvar])] + args)))
     return (t, slambdas)
 def visitIndirectCallFunc(self, n, needs_to_be_simple):
     if isinstance(n.node, CallFunc):
         args_sss = [self.dispatch(arg, True) for arg in n.args]
         args = [arg for (arg,ss) in args_sss]
         ss = reduce(lambda a,b: a + b, [ss for (arg,ss) in args_sss], [])
         (expr, sss) = self.dispatch(n.node, True)
         ss += sss
         if needs_to_be_simple:
             tmp = generate_name('indirectcallfunctmp')
             return (Name(tmp), ss + [make_assign(tmp, IndirectCallFunc(expr, args))])
         else:
             return (IndirectCallFunc(expr, args), ss)
     else:
         raise Exception('flatten: only indirectcalls to closure converted functions allowed')
 def visitmono_IfExp(self, n, needs_to_be_simple):
     (teste, testss) = self.dispatch(n.test, True)
     (thene, thenss) = self.dispatch(n.then, True)
     (elsee, elsess) = self.dispatch(n.else_, True)
     simple = mono_IfExp(teste,
                         flat_InstrSeq(thenss, thene),
                         flat_InstrSeq(elsess, elsee))
     if needs_to_be_simple:
         tmp = generate_name('ifexptmp')
         myexpr = (Name(tmp))
         myss = [make_assign(tmp, simple)]
     else:
         myexpr = simple
         myss = []
     return (myexpr, testss + myss)
 def visitWhileFlat(self, n, funcName):
     #Setup Label
     whileStartL, whileEndL = generate_while_labels()
     # Test Instructions
     testtmp = Var86(generate_name(WHILETESTTMP))
     test  = []
     test += [Label86(whileStartL)]
     test += self.dispatch(n.testss, funcName)
     test += self.dispatch(n.test, testtmp)
     test += [Comp86(x86FALSE, testtmp)]
     test += [JumpEqual86(whileEndL)]
     # Body Instructions
     body  = []
     body += self.dispatch(n.body, funcName)
     body += [Jump86(whileStartL)]
     body += [Label86(whileEndL)]
     return [Loop86(test, body)]
 def make_branches(testlist, caseLs, else_):
     if testlist:
         test, body = testlist[0]
         tmp = Var86(generate_name(IFTEMP))
         tinstrs = self.dispatch(test, tmp)
         tinstrs += [Comp86(x86FALSE, tmp)]
         tinstrs += [JumpEqual86(caseLs[0])]
         
         ninstrs = self.dispatch(body, func_name)
         ninstrs += [Jump86(endIfL)]
         
         einstrs = [Label86(caseLs[0])] + make_branches(testlist[1:], caseLs[1:], else_)
         return tinstrs + [If86(ninstrs, einstrs)]
     else:
         instrs = self.dispatch(else_, func_name)
         instrs += [Label86(endIfL)]
         return instrs
 def visitSLambda(self, n):
     lvs = n.local_vars
     self.needs_heapification = self.needs_heapification | self.nested_visitor.preorder(n.code)
     code = self.dispatch(n.code)
     new_params = []
     new_stmts = []
     for param in n.params:
         if param in self.needs_heapification:
             new_param = generate_name('heaped_at_')+param
             new_stmts.append(VarAssign(param, List([ZERO])))
             new_stmts.append(SubscriptAssign(Name(param), [ZERO], Name(new_param)))
             new_params.append(new_param)
         else:
             new_params.append(param)
     for local in lvs:
         if local in self.needs_heapification:
             new_stmts.append(VarAssign(local, List([ZERO])))
     ret = SLambda(new_params, StmtList(new_stmts + code.nodes))
     ret.free_vars = n.free_vars
     return ret
 def visitIntCmp(self, n, target):
     if(n.op == PY_EQ):
         op = ICMP_EQ
     elif(n.op == PY_NE):
         op = ICMP_NE
     elif(n.op == PY_GT):
         op = ICMP_SGT
     elif(n.op == PY_GE):
         op = ICMP_SGE
     elif(n.op == PY_LT):
         op = ICMP_SLT
     elif(n.op == PY_LE):
         op = ICMP_SLE
     else:
         raise Exception("Unknown op in IntCmp")
     left  = self.dispatch(n.left)
     right = self.dispatch(n.right)
     tmp = VarLLVM(LocalLLVM(generate_name(ICMPTEMP)), LLVMBOOLTYPE)
     instrs = []
     instrs += [icmpLLVM(tmp, op, left, right)]
     instrs += [zextLLVM(target, tmp, DEFAULTTYPE)]
     return instrs
    def OrToIfExp(self, nodes):
        if(len(nodes) < 2):
            # Error Condition
            raise Exception("expand: OR expression must have at least 2 nodes")
        
        thisnode = self.dispatch(nodes[0])
        thistmp = generate_name('or')

        if(len(nodes) == 2):
            # Exit Condition
            nextnode = self.dispatch(nodes[1])
            return Let(Name(thistmp),
                       thisnode,
                       IfExp(CallISTRUE([Name(thistmp)]),
                             Name(thistmp),
                             nextnode))
        else:
            # Recurse
            return Let(Name(thistmp),
                       thisnode,
                       IfExp(CallISTRUE([Name(thistmp)]),
                             Name(thistmp),
                             self.AndToIfExp(nodes[1:])))
 def visitDiscard(self, n):
     tmp = Var86(generate_name(DISCARDTEMP))
     return self.dispatch(n.expr, tmp)
 def visitString(self, n):
     location = '.L' + generate_name('str')
     n.location = location
     return set([(location, n.string)])