class TestResolve(unittest.TestCase): #{{{ def setUp(self): pr_num=Typez(kind='prim', node=ast.Num()) pr_str=Typez(kind='prim', node=ast.Str()) self.scope=Scope(is_root=True) self.scope.update({'xxx':pr_str}) scope1=Scope(parent=self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1=Typez(kind='obj', scope=scope1) scope2=Scope(parent=self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2=Typez(kind='obj', scope=scope2) self.type2=scope2 scope12=Scope(parent=self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12=Typez(kind='obj', scope=scope12) self.type3=Typez(kind='multi', scope=Scope(parent=self.scope)) self.type3.multi=[self.type12, self.type1] self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12, 'type3': self.type3}) def test_resolve_type1_in_scope(self): res=self.scope.resolve('type1', 'straight') self.assertEqual(res, self.type1) def test_resolve_in_type(self): res=self.type1.resolve('a', 'straight') self.assertEqual(res.kind,'prim') self.assertIsInstance(res.node, ast.Num) self.assertEqual(self.scope.resolve('c', 'straight').value, 'None') def test_resolve_multi(self): res=self.type3.resolve('a', 'straight') self.assertEqual(res.kind,'multi') self.assertEqual(len(res.multi),2) prim=[val_type for _type in res.multi for key,val_type in _type.scope.items() if _type.kind=='prim'] self.assertEqual(len(prim),1) def test_resolve_cascade(self): self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade') res1=self.type1.scope.resolve('xxx','cascade') res2=self.scope.resolve('xxx','straight') self.assertEqual(res1,res2) def test_resolve_class(self): num=self.type1.resolve('a', 'straight') self.assertRaises(Exception, num, '__add__','cascade') self.assertRaises(Exception, num, '__add__','straight') add=num.resolve('__add__', 'class') self.assertIsInstance(add, Typez) self.assertEqual(add.kind, 'func') self.assertIsInstance(add.node, ast.FunctionDef)
class TestResolve(InferTestCase): #{{{ def setUp(self): num_class = Typez(kind = 'class') num_class.scope['__add__'] = Typez(kind = 'func') pr_num = Typez(kind = 'pr_num', __class__ = num_class ) pr_str = Typez(kind = 'pr_str') self.scope = Scope(is_root = True) self.scope.update({'xxx':pr_str}) scope1 = Scope(parent = self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1 = Typez(kind = 'obj', scope = scope1) scope2 = Scope(parent = self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2 = Typez(kind = 'obj', scope = scope2) self.type2 = scope2 scope12 = Scope(parent = self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12 = Typez(kind = 'obj', scope = scope12) self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12}) def test_resolve_type1_in_scope(self): res = self.scope.resolve('type1', 'straight') self.assertEqual(res, self.type1) def test_resolve_in_type(self): res = self.type1.resolve('a', 'straight') self.assertEqual(res.kind,'pr_num') self.assertEqual(self.scope.resolve('c'), None) def test_resolve_cascade(self): self.assertRaises(Exception, self.type1.resolve, 'xxx','cascade') res1 = self.type1.scope.resolve('xxx','cascade') res2 = self.scope.resolve('xxx','straight') self.assertEqual(res1,res2) def test_resolve_class(self): num = self.type1.resolve('a', 'straight') self.assertRaises(Exception, num.resolve, '__add__', 'cascade') add = num.resolve('__add__', 'straight') self.assertEqual(add, None) add = num.resolve('__add__', 'class') self.assertIsInstance(add, Typez) self.assertEqual(add.kind, 'func')
def exec_Call(self, node, scope): #first let's find out which function should be called. This should be easy when doing func() #call, but it can be tricky when using constructs such as 'a.b.c.func()' self_type=None #covers func() case if isinstance(node.func,ast.Name): logger.debug("? exec_Call "+node.func.id +" "+str(node)) call_type=scope.resolve(node.func.id,'cascade') #covers a.b.c.func() case elif isinstance(node.func, ast.Attribute): logger.debug("? exec_Call "+node.func.attr +" "+str(node)) call_type=self.eval_code(node.func, scope) if typez.is_none(call_type): self.warn(node.func, message='nonexistent_attribute', symbol=node.func.attr) return typez.none_type #whether we are dealing with function or with a method should be already resolved by #exec_Attribute if hasattr(call_type, 'is_method'): if call_type.is_method: self_type=self.eval_code(node.func.value, scope) else: raise Exception('should not get here') #now we know what to invoke. Now we must distinguist whether it is func/method call or 'new' #statement. #Call-ing function or method if call_type.kind=='func': args=[self.eval_code(arg,scope) for arg in node.args] if self_type: args=[self_type]+args return self._exec_fun(call_type, args, call_type.scope) #Call-ing as a 'new' statement if call_type.kind=='class': args=[self.eval_code(arg,scope) for arg in node.args] new=Typez(kind='obj', scope=Scope(parent=call_type.scope)) args=[new]+args new.scope['__class__']=call_type constructor=call_type.resolve('__init__', 'straight') new.obj=self._exec_fun(constructor, args, new.scope) return new raise Exception('calling node must be either function or class')
def exec_Call(self, node, scope): #first let's find out which function should be called. This should be easy when doing func() #call, but it can be tricky when using constructs such as 'a.b.c.func()' #covers func() case if isinstance(node.func, ast.Name): logger.debug("? exec_Call "+node.func.id +" "+str(node)) call_type = scope.resolve(node.func.id,'cascade') if call_type is None: call_type = any_type #covers a.b.c.func() case elif isinstance(node.func, ast.Attribute): logger.debug("? exec_Call "+node.func.attr +" "+str(node)) call_type = self.eval_code(node.func, scope) if call_type.kind == 'any': return any_type else: raise Exception('should not get here') #now we know what to invoke. Now we must distinguish whether it is func/method call or 'new' #statement. #TODO: dorobit spustanie 'any' kind #Call-ing function or method if call_type.kind == 'func': args = [self.eval_code(arg, scope) for arg in node.args] if call_type.is_method: args = [call_type.self_obj]+args return self._exec_fun(call_type, args, call_type.scope, node=node) #Call-ing as a 'new' statement if call_type.kind == 'class': args = [self.eval_code(arg,scope) for arg in node.args] new = Typez(kind = 'obj', parent_scope = scope) args = [new]+args new.scope['__class__'] = call_type constructor = call_type.resolve('__init__', 'class') if constructor: new.obj = self._exec_fun(constructor, args, new.scope, node=node) return new self.warn(node, message = 'nonexistent_function', symbol = node.func.id)
def setUp(self): num_class = Typez(kind = 'class') num_class.scope['__add__'] = Typez(kind = 'func') pr_num = Typez(kind = 'pr_num', __class__ = num_class ) pr_str = Typez(kind = 'pr_str') self.scope = Scope(is_root = True) self.scope.update({'xxx':pr_str}) scope1 = Scope(parent = self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1 = Typez(kind = 'obj', scope = scope1) scope2 = Scope(parent = self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2 = Typez(kind = 'obj', scope = scope2) self.type2 = scope2 scope12 = Scope(parent = self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12 = Typez(kind = 'obj', scope = scope12) self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12})
def setUp(self): pr_num=Typez(kind='prim', node=ast.Num()) pr_str=Typez(kind='prim', node=ast.Str()) self.scope=Scope(is_root=True) self.scope.update({'xxx':pr_str}) scope1=Scope(parent=self.scope) scope1.update({'a': pr_num, 'b': pr_str}) self.type1=Typez(kind='obj', scope=scope1) scope2=Scope(parent=self.scope) scope2.update({'c': pr_num, 'd': pr_str}) self.type2=Typez(kind='obj', scope=scope2) self.type2=scope2 scope12=Scope(parent=self.scope) scope12.update({'a':self.type1, 'b': self.type2}) self.type12=Typez(kind='obj', scope=scope12) self.type3=Typez(kind='multi', scope=Scope(parent=self.scope)) self.type3.multi=[self.type12, self.type1] self.scope.update({'type1':self.type1, 'type2': self.type2, 'type12': self.type12, 'type3': self.type3})
def exec_List(self, node, scope): res = Typez(kind = 'obj', node = node, klass_name = 'inf_list') for item in node.elts: item_val = self.eval_code(item, scope) append = res.resolve('append', 'class') self._exec_fun(append, item_val, scope, node=node)