| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | from c_parser import ( | 
					
						
							|  |  |  |     parse_files as _parse_files, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from c_parser.info import ( | 
					
						
							|  |  |  |     KIND, | 
					
						
							|  |  |  |     TypeDeclaration, | 
					
						
							|  |  |  |     resolve_parsed, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2020-10-30 15:46:52 -06:00
										 |  |  | from c_parser.match import ( | 
					
						
							|  |  |  |     filter_by_kind, | 
					
						
							|  |  |  |     group_by_kinds, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | from . import ( | 
					
						
							|  |  |  |     analyze as _analyze, | 
					
						
							|  |  |  |     datafiles as _datafiles, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | from .info import Analysis | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def analyze(filenmes, **kwargs): | 
					
						
							| 
									
										
										
										
											2023-12-01 17:37:40 +08:00
										 |  |  |     results = iter_analysis_results(filenames, **kwargs) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |     return Analysis.from_results(results) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def iter_analysis_results(filenmes, *, | 
					
						
							|  |  |  |                           known=None, | 
					
						
							|  |  |  |                           **kwargs | 
					
						
							|  |  |  |                           ): | 
					
						
							|  |  |  |     decls = iter_decls(filenames, **kwargs) | 
					
						
							|  |  |  |     yield from analyze_decls(decls, known) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def iter_decls(filenames, *, | 
					
						
							|  |  |  |                kinds=None, | 
					
						
							|  |  |  |                parse_files=_parse_files, | 
					
						
							|  |  |  |                **kwargs | 
					
						
							|  |  |  |                ): | 
					
						
							|  |  |  |     kinds = KIND.DECLS if kinds is None else (KIND.DECLS & set(kinds)) | 
					
						
							|  |  |  |     parse_files = parse_files or _parse_files | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parsed = parse_files(filenames, **kwargs) | 
					
						
							|  |  |  |     parsed = filter_by_kind(parsed, kinds) | 
					
						
							|  |  |  |     for item in parsed: | 
					
						
							|  |  |  |         yield resolve_parsed(item) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def analyze_decls(decls, known, *, | 
					
						
							|  |  |  |                   analyze_resolved=None, | 
					
						
							|  |  |  |                   handle_unresolved=True, | 
					
						
							|  |  |  |                   relroot=None, | 
					
						
							|  |  |  |                   ): | 
					
						
							|  |  |  |     knowntypes, knowntypespecs = _datafiles.get_known( | 
					
						
							|  |  |  |         known, | 
					
						
							|  |  |  |         handle_unresolved=handle_unresolved, | 
					
						
							|  |  |  |         analyze_resolved=analyze_resolved, | 
					
						
							|  |  |  |         relroot=relroot, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decls = list(decls) | 
					
						
							| 
									
										
										
										
											2020-10-30 15:46:52 -06:00
										 |  |  |     collated = group_by_kinds(decls) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     types = {decl: None for decl in collated['type']} | 
					
						
							|  |  |  |     typespecs = _analyze.get_typespecs(types) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def analyze_decl(decl): | 
					
						
							|  |  |  |         return _analyze.analyze_decl( | 
					
						
							|  |  |  |             decl, | 
					
						
							|  |  |  |             typespecs, | 
					
						
							|  |  |  |             knowntypespecs, | 
					
						
							|  |  |  |             types, | 
					
						
							|  |  |  |             knowntypes, | 
					
						
							|  |  |  |             analyze_resolved=analyze_resolved, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     _analyze.analyze_type_decls(types, analyze_decl, handle_unresolved) | 
					
						
							|  |  |  |     for decl in decls: | 
					
						
							|  |  |  |         if decl in types: | 
					
						
							|  |  |  |             resolved = types[decl] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             resolved = analyze_decl(decl) | 
					
						
							|  |  |  |             if resolved and handle_unresolved: | 
					
						
							|  |  |  |                 typedeps, _ = resolved | 
					
						
							|  |  |  |                 if not isinstance(typedeps, TypeDeclaration): | 
					
						
							|  |  |  |                     if not typedeps or None in typedeps: | 
					
						
							|  |  |  |                         raise NotImplementedError((decl, resolved)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         yield decl, resolved | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ####################################### | 
					
						
							|  |  |  | # checks | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def check_all(analysis, checks, *, failfast=False): | 
					
						
							|  |  |  |     for check in checks or (): | 
					
						
							|  |  |  |         for data, failure in check(analysis): | 
					
						
							|  |  |  |             if failure is None: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             yield data, failure | 
					
						
							|  |  |  |             if failfast: | 
					
						
							|  |  |  |                 yield None, None | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         # We failed fast. | 
					
						
							|  |  |  |         break |