def setUp(self): num_class = Typez(kind='classdef') num_class.scope['__add__'] = Typez(kind='funcdef') 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 exec_Call(self, node, scope): ''' This method is resposible for exectuing calls. For instance : fun(),a.b.c.fun() or A() as a constructor. ''' #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 == any_type: 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. #Call-ing function or method if call_type.kind == 'funcdef': args = [self.eval_code(arg, scope) for arg in node.args] keywords = {} for keyword in node.keywords: keywords[keyword.arg]=self.eval_code(keyword.value, scope) counter = 0 for arg_eval in args: if arg_eval is None and hasattr(node.args[counter], 'id'): self.warn(node, "NameError: Name '"+ node.args[counter].id + "' is not defined", node.args[counter].id) counter = counter + 1 if call_type.is_method: args = [call_type.self_obj]+args return self._exec_fun(call_type, args, keywords, call_type.scope, node=node) #Call-ing as a 'new' statement if call_type.kind == 'classdef': args = [self.eval_code(arg,scope) for arg in node.args] keywords = {} for keyword in node.keywords: keywords[keyword.arg]=self.eval_code(keyword.value, scope) 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, keywords, new.scope, node=node) return new if hasattr(node.func, 'id'): self.warn(node, message = 'nonexistent_function', symbol = node.func.id) return any_type
class TestResolve(InferTestCase): #{{{ def setUp(self): num_class = Typez(kind='classdef') num_class.scope['__add__'] = Typez(kind='funcdef') 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, 'funcdef')
class TestResolve(InferTestCase): #{{{ def setUp(self): num_class = Typez(kind = 'classdef') num_class.scope['__add__'] = Typez(kind = 'funcdef') 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, 'funcdef')
def _exec_Tuple_Assign(self,lhs,rhs,node,scope,evalR): ''' This method covers cases like a,b = x ''' if evalR: rhs_type = self.eval_code(rhs,scope) else: rhs_type = rhs fun_iter = rhs_type.resolve('__iter__','class') if fun_iter: isTuple = rhs_type.resolve_class(self.extern_scope['inf_tuple']) if isTuple: stop = False for index,e in enumerate(lhs.elts): if stop: self._exec_Assign(e,any_type,node,scope,evalR=False) else: key = Typez(kind='const', value = index, __class__ = self.extern_scope['num']) getItem = rhs_type.resolve('__getitem__','class') item = self._exec_fun(getItem, [rhs_type,key], {}, scope, node=node) if not item.resolve_class(self.extern_scope['PlaceHolder']): self._exec_Assign(e,item,node,scope,evalR=False) else: stop = True self._exec_Assign(e,any_type,node,scope,evalR=False) self.warn(node, 'Need more than %d values to unpack'%(index), 'tuple') if index+1<5: key = Typez(kind='const', value = index+1, __class__ = self.extern_scope['num']) getItem = rhs_type.resolve('__getitem__','class') item = self._exec_fun(getItem, [rhs_type,key], {}, scope, node=node) if not item.resolve_class(self.extern_scope['PlaceHolder']): #nerozbalili sa vsetky hodnoty co boli v tuple, malo var na lavej strane self.warn(node, 'too many values to unpack (expected %d)'%(len(lhs.elts)),'tuple') else: args = [rhs_type] iterator = self._exec_fun(fun_iter, args, {}, scope, node=node) fun_next = iterator.resolve('__next__','class') if fun_next: value = self._exec_fun(fun_next, [iterator], {}, scope, node=node) for e in lhs.elts: self._exec_Assign(e,value,node,scope,evalR=False) else: self.warn(node=node,mes="does not support __next__ method",symbol="Iterator") else: if hasattr(rhs, 'id'): self.warn(node,"object is not iterable", rhs.id) else: symbol = hrs_type.scope['__class__'].node.name self.warn(node,"object is not iterable", symbol)
class TestResolve(unittest.TestCase): #{{{ def setUp(self): pr_num = Typez(kind = 'obj', node = ast.Num(), klass_name = 'num') pr_str = Typez(kind = 'obj', node = ast.Str(), klass_name = '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,'obj') self.assertIsInstance(res.node, ast.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') self.assertIsInstance(add.node, ast.FunctionDef)
def exec_Set(self, node, scope): ''' Set in our implementation only holds info about one object - representant. This can be handful for numerous reasons: adding something in neverending while cycle would cause overflow in symbolic execution if we stored full set. Another advantage is quickness of execution. ''' new_set = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_set']) init = new_set.resolve('__init__','class') self._exec_fun(init, [new_set],{}, new_set.scope, node) add = new_set.resolve('add', 'class') for item in node.elts: item_val = self.eval_code(item, scope) if item_val is not None: self._exec_fun(add, [new_set, item_val], {}, scope, node=node) return new_set
def exec_Slice(self,node,scope): ''' This method proceeds all the slicing in our implementation. The mock object inf_slice is created. ''' new_slice = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_slice']) init = new_slice.resolve('__init__','class') args=[new_slice] if node.upper is not None: args.append(self.eval_code(node.upper, scope)) if node.lower is not None: args.append(self.eval_code(node.lower, scope)) if node.step is not None: args.append(self.eval_code(node.step, scope)) self._exec_fun(init, args,{}, new_slice.scope, node) return new_slice
def exec_Name(self, node, scope): ''' Method that proceeds all occurences of name. For instance : x=5 (x is a name) There are two cases: name is a constant (None, True, False) or name is a variable that has to be resolved. ''' if node.id == 'None': return Typez(kind = 'const', node = node, value = 'None') if node.id == 'True': return Typez(kind = 'const', node = node, value = True, __class__ = self.extern_scope['bool']) if node.id == 'False': return Typez(kind = 'const', node = node, value = False, __class__ = self.extern_scope['bool']) res = scope.resolve(node.id, 'cascade') if res is None and isinstance(node.ctx,ast.Load): self.warn(node, "NameError: Name '"+ node.id + "' is not defined", node.id) return any_type return res
def exec_FunctionDef(self, node, scope): ''' This method executes the definition of function. In this case, just the name of function is stored. If the docstring is included inside of definition, it is stored in within the corresponding Typez under attribute docstring. ''' scope[node.name] = Typez(kind='funcdef', node = node, scope = scope) if isinstance(node.body[0],ast.Expr) and isinstance(node.body[0].value,ast.Str): scope[node.name].docstring = node.body[0].value.s
def exec_List(self, node, scope): ''' List in our implementation only holds info about one object - representant. This can be handful for numerous reasons: apending something in neverending while cycle would cause overflow in symbolic execution if we stored full list. Another advantage is quickness of execution. ''' new_list = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_list']) init = new_list.resolve('__init__','class') self._exec_fun(init, [new_list],{}, new_list.scope, node) append = new_list.resolve('append', 'class') for item in node.elts: if append: item_val = self.eval_code(item, scope) if item_val is None and hasattr(item, "id"): # self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id) item_val = any_type self._exec_fun(append, [new_list, item_val], {}, scope, node=node) return new_list
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 exec_Dict(self, node, scope): ''' Dictionary in our implementation only holds info only about two objects: key and value. Reasons are the same like in exec_List. ''' new_dict = Typez(kind = 'obj', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_dict']) init = new_dict.resolve('__init__','class') self._exec_fun(init, [new_dict],{}, new_dict.scope, node) setItem = new_dict.resolve('__setitem__', 'class') #self.nondet=False for i,item in enumerate(node.values): item_val = self.eval_code(item, scope) if item_val is None and hasattr(item, "id"): #self.warn(node, "NameError: Name '"+ item.id + "' is not defined", item.id) item_val = any_type key_val = self.eval_code(node.keys[i],scope) if key_val is None and hasattr(node.keys[i], "id"): #self.warn(node, "NameError: Name '"+ node.keys[i].id + "' is not defined", node.keys[i].id) key_val = any_type args = [new_dict, key_val, item_val] self._exec_fun(setItem, args, {}, scope, node=node) return new_dict
def setUp(self): num_class = Typez(kind = 'classdef') num_class.scope['__add__'] = Typez(kind = 'funcdef') 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 exec_Tuple(self, node, scope): ''' Tuple in our implementation is of size 5. That should be enough for executing almost all operations between tuples (pairs, triples, adding them together). This can be handful for numerous reasons: adding something in neverending while cycle would cause overflow in symbolic execution if we stored full tuple. Another advantage is quickness of execution. ''' new_tuple = Typez(kind = 'object', node = node, parent_scope = scope, __class__ = self.extern_scope['inf_tuple']) init = new_tuple.resolve('__init__','class') self._exec_fun(init, [new_tuple],{}, new_tuple.scope, node) set_item = new_tuple.resolve('inf__setitem__', 'class') i=0 for item in node.elts: item_val = self.eval_code(item, scope) if item_val is None: item_val = any_type else: #check whether item_val is a PlaceHolder by adding two tuples together if not item_val.resolve_class(self.extern_scope['PlaceHolder']): index = Typez(kind='const', value = i, __class__ = self.extern_scope['num']) self._exec_fun(set_item, [new_tuple, index, item_val], {}, scope, node=node) i+=1 return new_tuple
def exec_ClassDef(self, node, scope): ''' Method that executes the definition of class. Bases are stored in Typez object and furthermore 'object' is added to bases. Every node inside node.body is recursively executed. ''' class_scope = Scope(parent = scope) scope[node.name] = Typez(kind='classdef', node = node, scope = class_scope) #docstrings if isinstance(node.body[0],ast.Expr) and isinstance(node.body[0].value,ast.Str): scope[node.name].docstring = node.body[0].value.s for _node in node.body: self.eval_code(_node, class_scope) bases = [self.eval_code(base, scope) for base in node.bases] obj = self.extern_scope['object'] bases.append(obj) class_scope['__bases__'] = bases
def setUp(self): pr_num = Typez(kind = 'obj', node = ast.Num(), klass_name = 'num') pr_str = Typez(kind = 'obj', node = ast.Str(), klass_name = '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 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)
def _exec_fun(self, fun_type, args, keywords, scope, create_scope = True, node = None): """ executes function with given args in the given scope. When create_scope is True, it creates new scope for the function executing with parameter scope as its parent. Otherwise, it executes function in the given scope. """ #if we dont know the fun_type, return any_type if fun_type.kind=='any': return any_type from random import randint if fun_type == self.extern_scope['inf_hasattr']: a=args[0] b=args[1] if b.value is not None: res = a.resolve(b.value) if res is None: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) self.nondet=True bit = randint(0,1) if bit: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) if fun_type == self.extern_scope['inf_random']: self.nondet=True bit = randint(0,1) if bit: return Typez(kind='const', value = 1, __class__ = self.extern_scope['num']) else: return Typez(kind='const', value = 0, __class__ = self.extern_scope['num']) if fun_type == self.extern_scope['inf_equal']: a=args[0] b=args[1] if a.value is not None and b.value is not None: left = a.value right = b.value if isinstance(a.value, bool): if a.value: left = 1 else: left = 0 if isinstance(b.value, bool): if b.value: right = 1 else: right = 0 if left==right: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) else: self.nondet=True bit = randint(0,1) if bit: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) if fun_type == self.extern_scope['inf_is']: #we truly determine only if the statement is in form - smth is None if is_none(args[1]): if is_none(args[0]): return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) else: self.nondet=True bit = randint(0,1) if bit: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) if fun_type == self.extern_scope['isinstance']: if isinstance(args[0],Typez) and isinstance(args[1],Typez): instance = args[0] clazz = args[1] res = instance.resolve_class(clazz) if not res is None: return Typez(kind='const', value = True, __class__ = self.extern_scope['bool']) else: return Typez(kind='const', value = False, __class__ = self.extern_scope['bool']) else: self.warn(node, symbol = 'isinstance error', message = 'isinstance bad arguments') if fun_type == self.extern_scope['inf_setattr']: attr = args[1] if isinstance(attr, Typez) and isinstance(attr.value, str): attr = attr.value if isinstance(attr, str): args[0].scope[attr] = args[2] if create_scope: fun_scope = Scope(parent = scope) else: fun_scope = scope def_args = fun_type.node.args.args def_default_args = fun_type.node.args.defaults def_args_names = [arg.arg for arg in def_args] count_given_args = len(args)+len(keywords) if count_given_args > len(def_args) or count_given_args+len(def_default_args)< len(def_args): symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id')) self.warn(node, symbol = symbol, message = 'bad number of arguments (%d given, %d expected)'%(len(args), len(def_args))) for keyword in keywords: if not keyword in def_args_names: symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id')) self.warn(node, symbol = symbol, message = 'unexpected keyword argument %s'%(keyword)) for i,arg in enumerate(def_args): if i<len(args): if arg.arg in keywords: symbol = not_none(safe_resolve(node, 'func.attr'), safe_resolve(node, 'func.id')) self.warn(node, symbol = symbol, message = 'multiple arguments for keyword argument %s'%(arg.arg)) fun_scope[arg.arg] = args[i] else: found=False for j,key in enumerate(keywords): if key==arg.arg: found=True fun_scope[arg.arg]=keywords[key] if not found: lengthFromEnd = len(def_args)-i if len(def_default_args) >= lengthFromEnd: fun_scope[arg.arg]=self.eval_code(def_default_args[-lengthFromEnd],scope) else: fun_scope[arg.arg] = any_type try: for _node in fun_type.node.body: self.eval_code(_node, fun_scope) except ReturnException as e: res=e.res if isinstance(res, Typez) and "__class__" in res.scope and (res.scope["__class__"] == self.extern_scope['ProblemException']): error = res.scope["error"] message = res.scope["message"] #symbol = res.scope["symbol"] symbol = None for key,val in scope.items(): if val==error: symbol = key #when error is caused by constant, symbol is its type if symbol is None: if hasattr(error.scope['__class__'].node, 'name'): symbol = error.scope['__class__'].node.name else: #default symbol symbol = 'Type error' if is_none(message): #default message because it is very often used message_value = "unsupported operand type" else: message_value = message.value self.warn(node, message_value, symbol) return any_type if isinstance(res, Typez) and "__class__" in res.scope and (res.scope["__class__"] == self.extern_scope['TypeContainer']): gen_type=res.scope["T"] result = Typez(kind='const',__class__ = gen_type) return result return res if fun_type.kind == 'classdef': return args[0]
def exec_Num(self, node, scope): ''' This method proceeds code like : 1,55, etc. ''' return Typez(kind='const', node = node, value = node.n, __class__ = self.extern_scope['num'])
def exec_Str(self, node, scope): '''' This method proceeds code like : 'some_string_in_input_code' ''' return Typez(kind='const', node = node, value = node.s, __class__ = self.extern_scope['str'])