mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	 4fe72090de
			
		
	
	
		4fe72090de
		
			
		
	
	
	
	
		
			
			This is a little bit of clean-up, small fixes, and additional helpers prior to building an updated & accurate list of globals to eliminate.
		
			
				
	
	
		
			177 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import re
 | |
| 
 | |
| from . import info as _info
 | |
| from .parser._regexes import SIMPLE_TYPE
 | |
| 
 | |
| 
 | |
| _KIND = _info.KIND
 | |
| 
 | |
| 
 | |
| def match_storage(decl, expected):
 | |
|     default = _info.get_default_storage(decl)
 | |
|     #assert default
 | |
|     if expected is None:
 | |
|         expected = {default}
 | |
|     elif isinstance(expected, str):
 | |
|         expected = {expected or default}
 | |
|     elif not expected:
 | |
|         expected = _info.STORAGE
 | |
|     else:
 | |
|         expected = {v or default for v in expected}
 | |
|     storage = _info.get_effective_storage(decl, default=default)
 | |
|     return storage in expected
 | |
| 
 | |
| 
 | |
| ##################################
 | |
| # decl matchers
 | |
| 
 | |
| def is_type_decl(item):
 | |
|     return _KIND.is_type_decl(item.kind)
 | |
| 
 | |
| 
 | |
| def is_decl(item):
 | |
|     return _KIND.is_decl(item.kind)
 | |
| 
 | |
| 
 | |
| def is_pots(typespec, *,
 | |
|             _regex=re.compile(rf'^{SIMPLE_TYPE}$', re.VERBOSE),
 | |
|             ):
 | |
| 
 | |
|     if not typespec:
 | |
|         return None
 | |
|     if type(typespec) is not str:
 | |
|         _, _, _, typespec, _ = _info.get_parsed_vartype(typespec)
 | |
|     return _regex.match(typespec) is not None
 | |
| 
 | |
| 
 | |
| def is_funcptr(vartype):
 | |
|     if not vartype:
 | |
|         return None
 | |
|     _, _, _, _, abstract = _info.get_parsed_vartype(vartype)
 | |
|     return _is_funcptr(abstract)
 | |
| 
 | |
| 
 | |
| def _is_funcptr(declstr):
 | |
|     if not declstr:
 | |
|         return None
 | |
|     # XXX Support "(<name>*)(".
 | |
|     return '(*)(' in declstr.replace(' ', '')
 | |
| 
 | |
| 
 | |
| def is_forward_decl(decl):
 | |
|     if decl.kind is _KIND.TYPEDEF:
 | |
|         return False
 | |
|     elif is_type_decl(decl):
 | |
|         return not decl.data
 | |
|     elif decl.kind is _KIND.FUNCTION:
 | |
|         # XXX This doesn't work with ParsedItem.
 | |
|         return decl.signature.isforward
 | |
|     elif decl.kind is _KIND.VARIABLE:
 | |
|         # No var decls are considered forward (or all are...).
 | |
|         return False
 | |
|     else:
 | |
|         raise NotImplementedError(decl)
 | |
| 
 | |
| 
 | |
| def can_have_symbol(decl):
 | |
|     return decl.kind in (_KIND.VARIABLE, _KIND.FUNCTION)
 | |
| 
 | |
| 
 | |
| def has_external_symbol(decl):
 | |
|     if not can_have_symbol(decl):
 | |
|         return False
 | |
|     if _info.get_effective_storage(decl) != 'extern':
 | |
|         return False
 | |
|     if decl.kind is _KIND.FUNCTION:
 | |
|         return not decl.signature.isforward
 | |
|     else:
 | |
|         # It must be a variable, which can only be implicitly extern here.
 | |
|         return decl.storage != 'extern'
 | |
| 
 | |
| 
 | |
| def has_internal_symbol(decl):
 | |
|     if not can_have_symbol(decl):
 | |
|         return False
 | |
|     return _info.get_actual_storage(decl) == 'static'
 | |
| 
 | |
| 
 | |
| def is_external_reference(decl):
 | |
|     if not can_have_symbol(decl):
 | |
|         return False
 | |
|     # We have to check the declared storage rather tnan the effective.
 | |
|     if decl.storage != 'extern':
 | |
|         return False
 | |
|     if decl.kind is _KIND.FUNCTION:
 | |
|         return decl.signature.isforward
 | |
|     # Otherwise it's a variable.
 | |
|     return True
 | |
| 
 | |
| 
 | |
| def is_local_var(decl):
 | |
|     if not decl.kind is _KIND.VARIABLE:
 | |
|         return False
 | |
|     return True if decl.parent else False
 | |
| 
 | |
| 
 | |
| def is_global_var(decl):
 | |
|     if not decl.kind is _KIND.VARIABLE:
 | |
|         return False
 | |
|     return False if decl.parent else True
 | |
| 
 | |
| 
 | |
| ##################################
 | |
| # filtering with matchers
 | |
| 
 | |
| def filter_by_kind(items, kind):
 | |
|     if kind == 'type':
 | |
|         kinds = _KIND._TYPE_DECLS
 | |
|     elif kind == 'decl':
 | |
|         kinds = _KIND._TYPE_DECLS
 | |
|     try:
 | |
|         okay = kind in _KIND
 | |
|     except TypeError:
 | |
|         kinds = set(kind)
 | |
|     else:
 | |
|         kinds = {kind} if okay else set(kind)
 | |
|     for item in items:
 | |
|         if item.kind in kinds:
 | |
|             yield item
 | |
| 
 | |
| 
 | |
| ##################################
 | |
| # grouping with matchers
 | |
| 
 | |
| def group_by_category(decls, categories, *, ignore_non_match=True):
 | |
|     collated = {}
 | |
|     for decl in decls:
 | |
|         # Matchers should be mutually exclusive.  (First match wins.)
 | |
|         for category, match in categories.items():
 | |
|             if match(decl):
 | |
|                 if category not in collated:
 | |
|                     collated[category] = [decl]
 | |
|                 else:
 | |
|                     collated[category].append(decl)
 | |
|                 break
 | |
|         else:
 | |
|             if not ignore_non_match:
 | |
|                 raise Exception(f'no match for {decl!r}')
 | |
|     return collated
 | |
| 
 | |
| 
 | |
| def group_by_kind(items):
 | |
|     collated = {kind: [] for kind in _KIND}
 | |
|     for item in items:
 | |
|         try:
 | |
|             collated[item.kind].append(item)
 | |
|         except KeyError:
 | |
|             raise ValueError(f'unsupported kind in {item!r}')
 | |
|     return collated
 | |
| 
 | |
| 
 | |
| def group_by_kinds(items):
 | |
|     # Collate into kind groups (decl, type, etc.).
 | |
|     collated = {_KIND.get_group(k): [] for k in _KIND}
 | |
|     for item in items:
 | |
|         group = _KIND.get_group(item.kind)
 | |
|         collated[group].append(item)
 | |
|     return collated
 |