def visitCallFunc(self, n, parent=None, svars=[]):
   f=self.dispatch(n.node, parent, svars)
   args = [self.dispatch(arg, parent, svars) for arg in n.args]
   #return CallFunc(f, args)
   ini = compiler_utilities.generate_name('obj_func')
   obj = compiler_utilities.generate_name('obj_inst')
   #return IfExp( CallFunc(Name('is_class'), [f]), 
   #          CallFunc(Name('create_object'), [f]), 
   #          CallFunc(f, args)
   #       )
                 
   return IfExp(
             CallFunc(Name('is_class'), [f]), 
             Let(obj, CallFunc(Name('create_object'), [f]), 
                 IfExp(CallFunc(Name('has_attr'), [f, Const('__init__')]), 
                     Let(ini, CallFunc(Name('get_function'), [CallFunc(Name('get_attr'), [f, Const('__init__')])]), 
                         Let('_', CallFunc(Name(ini), [Name(obj)]+args), Name(obj))
                     ), 
                     Name(obj)
                 )
             ), 
             IfExp(CallFunc(Name('is_bound_method'), [f]), 
                 CallFunc(CallFunc(Name('get_function'), [f]), [CallFunc(Name('get_receiver'), [f])]+args), 
                 IfExp(CallFunc(Name('is_unbound_method'), [f]), 
                     CallFunc(CallFunc(Name('get_function'), [f]), args), 
                     CallFunc(f, args)
                 )
             )
         )
 def visitIfExp(self, n, needs_to_be_simple):
     (test, test_ss) = self.dispatch(n.test, True)
     (then, then_ss) = self.dispatch(n.then, True)
     (else_, else_ss) = self.dispatch(n.else_, True)        
     tmp = generate_name('tmp')
     return (Name(tmp), test_ss + [If([(test, Stmt(then_ss + [make_assign(tmp, then)]))],
                                      Stmt(else_ss + [make_assign(tmp, else_)]))])
 def visitUnarySub(self, n, needs_to_be_simple):
     (expr,ss) = self.dispatch(n.expr, True)
     if needs_to_be_simple:
         tmp = generate_name('tmp')
         return (Name(tmp), ss + [make_assign(tmp, UnarySub(expr))])
     else:
         return (UnarySub(expr), ss)
 def visitSetSubscript(self, n, needs_to_be_simple):
     (c_result, c_ss) = self.dispatch(n.container, True)
     (k_result, k_ss) = self.dispatch(n.key, True)
     (v_result, v_ss) = self.dispatch(n.val, True)
     tmp = generate_name('tmp')
     rhs = SetSubscript(c_result, k_result, v_result)
     return (Name(tmp), c_ss + k_ss + v_ss + [make_assign(tmp, rhs)])
 def visitFunction(self, n, parent=None, svars=[]):
   if parent==None:
     return Function(n.decorators, n.name, n.argnames, n.defaults, n.flags, n.doc, self.dispatch(n.code, parent, svars))
   elif n.name in svars:
     tmp = compiler_utilities.generate_name('class_func')
     return [Function(n.decorators, tmp, n.argnames, n.defaults, n.flags, n.doc, self.dispatch(n.code, parent, svars)), \
             Discard(CallFunc(Name('set_attr'), [parent, Const(n.name), Name(tmp)]))]
 def visitAdd(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('tmp')
         return (Name(tmp), ss1 + ss2 + [make_assign(tmp, Add((left, right)))])
     else:
         return (Add((left, right)), ss1 + ss2)            
 def visitSubscript(self, n, needs_to_be_simple):
     (c_result, c_ss) = self.dispatch(n.expr, True)
     (k_result, k_ss) = self.dispatch(n.subs[0], True)
     rhs = Subscript(expr=c_result, flags=n.flags, subs=[k_result])
     if needs_to_be_simple:
         tmp = generate_name('tmp')
         return (Name(tmp), c_ss + k_ss + [make_assign(tmp, rhs)])
     else:
         return (rhs, c_ss + k_ss)            
 def visitCompare(self, n, needs_to_be_simple):
     (left,ss1) = self.dispatch(n.expr, True)
     op = n.ops[0][0]
     (right,ss2) = self.dispatch(n.ops[0][1], True)
     compare = Compare(expr=left, ops=[(op,right)])
     if needs_to_be_simple:
         tmp = generate_name('tmp')
         return (Name(tmp), ss1 + ss2 + [make_assign(tmp, compare)])
     else:
         return (compare, ss1 + ss2)            
    def visitIndirectCallFunc(self, n, needs_to_be_simple):
        (node, ss1) = self.dispatch(n.node, True)
        args_sss = [self.dispatch(arg, True) for arg in n.args]
        args = [arg for (arg,ss) in args_sss]
        ss2 = reduce(lambda a,b: a + b, [ss for (arg,ss) in args_sss], [])

        if needs_to_be_simple:
            tmp = generate_name('tmp')
            return (Name(tmp), ss1 + ss2 + [make_assign(tmp, IndirectCallFunc(node, args))])
        else:
            return (IndirectCallFunc(node, args), ss1 + ss2)
 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('tmp')
             return (Name(tmp), ss + [make_assign(tmp, CallFunc(n.node, args))])
         else:
             return (CallFunc(n.node, args), ss)
     else:
         raise Exception('flatten1: only calls to named functions allowed')
 def visitClass(self, n, parent=None, svars=[]):
   #n.name
   #n.bases
   #n.code
   cvars = DeclassifyBodyFVVisitor().preorder(n.code)
   tmp = compiler_utilities.generate_name('class_var')
   nds = self.dispatch(n.code, Name(tmp), cvars)
   if parent is None:
     nds.nodes += [Assign([AssName(n.name, 'OP_ASSIGN')], Name(tmp))]
   else:
     nds.nodes += [self.dispatch(Assign([AssName(n.name, 'OP_ASSIGN')], Name(tmp)), parent, svars)]
   rval = [Assign([AssName(tmp, 'OP_ASSIGN')], CallFunc(Name('create_class'), [List(n.bases)]))]+\
          nds.nodes
   return rval
 def visitProjectTo(self, n, needs_to_be_simple):
     (arg, ss) = self.dispatch(n.arg, True)
     tmp = generate_name('tmp')
     rhs = ProjectTo(n.typ, arg)
     return (Name(tmp), ss + [make_assign(tmp, rhs)])
 def visitGetTag(self, n, needs_to_be_simple):
     (e, ss) = self.dispatch(n.arg, True)
     tmp = generate_name('tmp')
     rhs = GetTag(e)
     return (Name(tmp), ss + [make_assign(tmp, rhs)])
Exemple #14
0
def declassify(n, class_name, class_attributes, local_variables):
	if isinstance(n, Module):
		local_in_module = FindLocalsVisitor().preorder(n.node)
		return Module(n.doc, declassify(n.node, class_name, class_attributes, local_in_module))
	elif isinstance(n, Stmt):
		ss = []
		for s in n.nodes:
			d_s = declassify(s, class_name, class_attributes, local_variables)
			ss = ss + collapseStmts(d_s)
		#ss = [declassify(s, class_name, class_attributes, local_variables) for s in n.nodes]
		return Stmt(ss)
	elif isinstance(n, Const):
		return n
	elif isinstance(n, Add):
		return Add((declassify(n.left, class_name, class_attributes, local_variables), declassify(n.right, class_name, class_attributes, local_variables)))
	elif isinstance(n, UnarySub):
		return UnarySub(declassify(n.expr, class_name, class_attributes, local_variables))	
	elif isinstance(n, IfExp):
		return IfExp(declassify(n.test, class_name, class_attributes, local_variables), declassify(n.then, class_name, class_attributes, local_variables), declassify(n.else_, class_name, class_attributes, local_variables))
	elif isinstance(n, Compare):
		return Compare(declassify(n.expr, class_name, class_attributes, local_variables), [(n.ops[0][0], declassify(n.ops[0][1], class_name, class_attributes, local_variables))])
	elif isinstance(n, Subscript):
		return Subscript(declassify(n.expr, class_name, class_attributes, local_variables), n.flags, [declassify(s, class_name, class_attributes, local_variables) for s in n.subs])
	elif isinstance(n, SetSubscript):
		return SetSubscript(declassify(n.container, class_name, class_attributes, local_variables), declassify(n.key, class_name, class_attributes, local_variables), declassify(n.val, class_name, class_attributes, local_variables))
	elif isinstance(n, Printnl):
		return Printnl([declassify(n.nodes[0], class_name, class_attributes, local_variables)], n.dest)
	elif isinstance(n, Discard):
		return Discard(declassify(n.expr, class_name, class_attributes, local_variables))
	elif isinstance(n, Return):
		return Return(declassify(n.value, class_name, class_attributes, local_variables))
	elif isinstance(n, If):
		return If([(declassify(n.tests[0][0], class_name, class_attributes, local_variables), declassify(n.tests[0][1], class_name, class_attributes, local_variables))], declassify(n.else_, class_name, class_attributes, local_variables))
	elif isinstance(n, While):
		return While(declassify(n.test, class_name, class_attributes, local_variables), declassify(n.body, class_name, class_attributes, local_variables), n.else_)
	elif isinstance(n, And):
		return And([declassify(n.nodes[0], class_name, class_attributes, local_variables), declassify(n.nodes[1], class_name, class_attributes, local_variables)])	
	elif isinstance(n, Or):
		return Or([declassify(n.nodes[0], class_name, class_attributes, local_variables), declassify(n.nodes[1], class_name, class_attributes, local_variables)])
	elif isinstance(n, Not):
		return Not(declassify(n.expr, class_name, class_attributes, local_variables))
	elif isinstance(n, Dict):
		return Dict([(declassify(k, class_name, class_attributes, local_variables), declassify(e, class_name, class_attributes, local_variables)) for (k, e) in n.items])
	elif isinstance(n, List):
		return List([declassify(e, class_name, class_attributes, local_variables) for e in n.nodes])
	#these are all going to be a little more involved...
	elif isinstance(n, Name):
		# failing class6 test...b/c register allocater can't deal with "n" if its not a 	       #local variable
		if n.name in local_variables and  class_attributes and n.name in class_attributes:
			return IfExp(CallFunc(Name('has_attr'), [Name(class_name), Const(n.name)]), CallFunc(Name('get_attr'), [Name(class_name), Const(n.name)]), n)
		elif class_attributes and n.name in class_attributes:
			return CallFunc(Name('get_attr'), [Name(class_name), Const(n.name)])
		#if its not a class name just reutrn it!
		return n
	elif isinstance(n, Assign):
		if isinstance(n.nodes[0], AssName):
			#an assname in a class means we have to set an attr!
			if class_name:
				lhs = n.nodes[0]
				return Discard(CallFunc(Name('set_attr'), [Name(class_name), Const(lhs.name), declassify(n.expr, class_name, class_attributes, local_variables)]))
			#if its not within a class constructor do the regular stuff....
			return Assign(n.nodes, declassify(n.expr, class_name, class_attributes, local_variables))
		elif isinstance(n.nodes[0], Subscript):
			lhs = n.nodes[0]
			return Assign(nodes=[Subscript(declassify(lhs.expr, class_name, class_attributes, local_variables), subs = [declassify(lhs.subs[0], class_name, class_attributes, local_variables)], flags = lhs.flags)], expr = declassify(n.expr, class_name, class_attributes, local_variables))
		elif isinstance(n.nodes[0], AssAttr):
			lhs = n.nodes[0]
			#put in support for strs then realized support already exists in Consts
			return Discard(CallFunc(Name('set_attr'), [lhs.expr, Const(lhs.attrname), declassify(n.expr, class_name, class_attributes, local_variables)]))



	elif isinstance(n, CallFunc):
		#input keeps getting screwed up...make sure our compiler ignores builitin funcs
		if (n.node in builtin_functions):
			return CallFunc(n.node, [declassify(arg, class_name, class_attributes, local_variables) for arg in a.args])


#e0(e1, e2, ...en)
#let f = e0 in
#if is_class(f) then             	...if func call is object creation
#  let o = create_object(f) in   	...create the object
#  if has_attr(f, '__init__' then	...if it has an init then create a func call for it
#    let ini = get_function(get_attr(f, '__init__')) in  
#    let _ = ini(o, a1, ...,an) in
#      o
#  else o
#else
#  if is_bound_method(f) then
#    get_function(f)(get_receiver(f), a1, ..., an)   ...if its bound need receiver as 1st arg
#  else
#    if is_unbound_method(f) then
#      get_function(f)(a1, ..., an) 
#    else
#      f(a1, ..., an)       ....this is just a reg func call!




		#for right now lets just letify teh func name...chaining together lets
		#for args is going to be hard and is techinically just an optimization!

		e0 = declassify(n.node, class_name, class_attributes, local_variables)

		#this fails for lambdas....so just use a generic string to make tmp
		#f = generate_name(n.node.name)
		f = generate_name('call_func')

		o = generate_name('object')
		t_ = generate_name('_')

		return(Let(f, e0, \
			IfExp(CallFunc(Name('is_class'),[Name(f)]),
				Let(o, CallFunc(Name('create_object'), [Name(f)]),
					IfExp(CallFunc(Name('has_attr'),[Name(f), Const('__init__')]), Let(t_, CallFunc(CallFunc(Name('get_function'), [CallFunc(Name('get_attr'), [Name(f), Const('__init__')])]), [Name(o)] + n.args), Name(o)), Name(o))), 
				IfExp(CallFunc(Name('is_bound_method'), [Name(f)]), 
					CallFunc(CallFunc(Name('get_function'), [Name(f)]),
					[CallFunc(Name('get_receiver'), [Name(f)])] + n.args),
					IfExp(CallFunc(Name('is_unbound_method'),[Name(f)]),
						CallFunc(CallFunc(Name('get_function'), [Name(f)]), n.args),
					#else just do regular!
						CallFunc(e0, n.args))))))





	elif isinstance(n, Function):
		#if its a func dec in a class create the func and call set_attr on the class
		if class_name:
			#have to sort of "letify" the func name so we can assign it to an attr of the same name
			tmp_function_name = generate_name(n.name)
			#locals = local assigns + args!
			my_locals = FindLocalsVisitor().preorder(n.code) | set(n.argnames) 
			create_function = [Function(n.decorators, tmp_function_name, n.argnames, n.defaults, n.flags, n.doc, declassify(n.code, class_name, class_attributes, my_locals))]
			call_set_attr = [Discard(CallFunc(Name('set_attr'), [Name(class_name), Const(n.name), Name(tmp_function_name)]))]
			return(Stmt(create_function + call_set_attr))

		my_locals = FindLocalsVisitor().preorder(n.code) | set(n.argnames)
		#if its not a class just do nothing...
		return Function(n.decorators, n.name, n.argnames, n.defaults, n.flags, n.doc, declassify(n.code, class_name, class_attributes, my_locals))
	elif isinstance(n, Lambda):
		#need to get locals...for Lambda just argnames!
		my_locals = set(n.argnames)
			
		#if its not a class just do nothing 
		return Lambda(n.argnames, n.defaults, n.flags, declassify(n.code, class_name, class_attributes, my_locals))
	elif isinstance(n, Class):
		# name, bases, doc, code
		#Class C:
		#	0
		#=======>
		#C = create_class()

		#need tmp class name, do stuff, then at end assign tmp to n.name
	
		#in class body:
		#replace assignments and function definitions so that they refer to attributes
		#need to pass in the class name and attributes so that in assigns/func calls
		#we can set them as attrs to the new class!
		attributes = FindLocalsVisitor().preorder(n.code) #locals = attributes
		tmp_class_name = generate_name(n.name) #can only use real class name after construction

		create_class = [Assign([AssName(tmp_class_name, 'OP_ASSIGN')], CallFunc(Name('create_class'), [List([declassify(b, class_name, class_attributes) for b in n.bases])]))]
		code = [declassify(n.code, tmp_class_name, attributes, local_variables)] 
		assign_tmp_to_class = [declassify(Assign([AssName(n.name, 'OP_ASSIGN')], Name(tmp_class_name)), class_name, class_attributes, local_variables)]
		a = Stmt(create_class + code + assign_tmp_to_class)
		return a
	elif isinstance(n, Getattr):
		# expr, attrname
		#should be translated into a call to getattr
		return CallFunc(Name('get_attr'), [declassify(n.expr, class_name, class_attributes, local_variables),Const(n.attrname)])
	else:
		print 'DECLASSIFY CANT HANDLE: ' + str(n)
		input()