mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:22:45 +00:00 
			
		
		
		
	LibIDL: Remove static maps for interfaces and resolved imports
Instead, create a tree of Parsers all pointing to a top-level Parser. All module imports and interfaces are stored at the top level, instead of in a static map. This allows creating multiple IDL::Parsers in the same process without them stepping on each others toes.
This commit is contained in:
		
							parent
							
								
									2341294c20
								
							
						
					
					
						commit
						067a53b7e7
					
				
					 3 changed files with 49 additions and 14 deletions
				
			
		|  | @ -71,7 +71,8 @@ int main(int argc, char** argv) | |||
|     if (import_base_path.is_null()) | ||||
|         import_base_path = lexical_path.dirname(); | ||||
| 
 | ||||
|     auto& interface = IDL::Parser(path, data, import_base_path).parse(); | ||||
|     IDL::Parser parser(path, data, import_base_path); | ||||
|     auto& interface = parser.parse(); | ||||
| 
 | ||||
|     static constexpr Array libweb_interface_namespaces = { | ||||
|         "CSS"sv, | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "IDLParser.h" | ||||
| #include <AK/Assertions.h> | ||||
| #include <AK/LexicalPath.h> | ||||
| #include <AK/QuickSort.h> | ||||
| #include <LibCore/File.h> | ||||
|  | @ -76,9 +77,6 @@ static String convert_enumeration_value_to_cpp_enum_member(String const& value, | |||
| 
 | ||||
| namespace IDL { | ||||
| 
 | ||||
| HashTable<NonnullOwnPtr<Interface>> Parser::s_interfaces {}; | ||||
| HashMap<String, Interface*> Parser::s_resolved_imports {}; | ||||
| 
 | ||||
| void Parser::assert_specific(char ch) | ||||
| { | ||||
|     if (!lexer.consume_specific(ch)) | ||||
|  | @ -143,8 +141,8 @@ Optional<Interface&> Parser::resolve_import(auto path) | |||
|         report_parsing_error(String::formatted("{}: No such file or directory", include_path), filename, input, lexer.tell()); | ||||
| 
 | ||||
|     auto real_path = Core::File::real_path_for(include_path); | ||||
|     if (s_resolved_imports.contains(real_path)) | ||||
|         return *s_resolved_imports.find(real_path)->value; | ||||
|     if (top_level_resolved_imports().contains(real_path)) | ||||
|         return *top_level_resolved_imports().find(real_path)->value; | ||||
| 
 | ||||
|     if (import_stack.contains(real_path)) | ||||
|         report_parsing_error(String::formatted("Circular import detected: {}", include_path), filename, input, lexer.tell()); | ||||
|  | @ -155,10 +153,10 @@ Optional<Interface&> Parser::resolve_import(auto path) | |||
|         report_parsing_error(String::formatted("Failed to open {}: {}", real_path, file_or_error.error()), filename, input, lexer.tell()); | ||||
| 
 | ||||
|     auto data = file_or_error.value()->read_all(); | ||||
|     auto& result = Parser(real_path, data, import_base_path).parse(); | ||||
|     auto& result = Parser(this, real_path, data, import_base_path).parse(); | ||||
|     import_stack.remove(real_path); | ||||
| 
 | ||||
|     s_resolved_imports.set(real_path, &result); | ||||
|     top_level_resolved_imports().set(real_path, &result); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
|  | @ -736,7 +734,7 @@ void Parser::parse_interface_mixin(Interface& interface) | |||
| { | ||||
|     auto mixin_interface_ptr = make<Interface>(); | ||||
|     auto& mixin_interface = *mixin_interface_ptr; | ||||
|     VERIFY(s_interfaces.set(move(mixin_interface_ptr)) == AK::HashSetResult::InsertedNewEntry); | ||||
|     VERIFY(top_level_interfaces().set(move(mixin_interface_ptr)) == AK::HashSetResult::InsertedNewEntry); | ||||
|     mixin_interface.module_own_path = interface.module_own_path; | ||||
|     mixin_interface.is_mixin = true; | ||||
| 
 | ||||
|  | @ -856,9 +854,9 @@ Interface& Parser::parse() | |||
| 
 | ||||
|     auto interface_ptr = make<Interface>(); | ||||
|     auto& interface = *interface_ptr; | ||||
|     VERIFY(s_interfaces.set(move(interface_ptr)) == AK::HashSetResult::InsertedNewEntry); | ||||
|     VERIFY(top_level_interfaces().set(move(interface_ptr)) == AK::HashSetResult::InsertedNewEntry); | ||||
|     interface.module_own_path = this_module; | ||||
|     s_resolved_imports.set(this_module, &interface); | ||||
|     top_level_resolved_imports().set(this_module, &interface); | ||||
| 
 | ||||
|     Vector<Interface&> imports; | ||||
|     HashTable<String> required_imported_paths; | ||||
|  | @ -998,6 +996,9 @@ Interface& Parser::parse() | |||
|         interface.required_imported_paths.set(this_module); | ||||
|     interface.imported_modules = move(imports); | ||||
| 
 | ||||
|     if (top_level_parser() == this) | ||||
|         VERIFY(import_stack.is_empty()); | ||||
| 
 | ||||
|     return interface; | ||||
| } | ||||
| 
 | ||||
|  | @ -1009,4 +1010,31 @@ Parser::Parser(String filename, StringView contents, String import_base_path) | |||
| { | ||||
| } | ||||
| 
 | ||||
| Parser::Parser(Parser* parent, String filename, StringView contents, String import_base_path) | ||||
|     : import_base_path(move(import_base_path)) | ||||
|     , filename(move(filename)) | ||||
|     , input(contents) | ||||
|     , lexer(input) | ||||
|     , parent(parent) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| Parser* Parser::top_level_parser() | ||||
| { | ||||
|     Parser* current = this; | ||||
|     for (Parser* next = this; next; next = next->parent) | ||||
|         current = next; | ||||
|     return current; | ||||
| } | ||||
| 
 | ||||
| HashMap<String, Interface*>& Parser::top_level_resolved_imports() | ||||
| { | ||||
|     return top_level_parser()->resolved_imports; | ||||
| } | ||||
| 
 | ||||
| HashTable<NonnullOwnPtr<Interface>>& Parser::top_level_interfaces() | ||||
| { | ||||
|     return top_level_parser()->interfaces; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ private: | |||
|         Yes, | ||||
|     }; | ||||
| 
 | ||||
|     Parser(Parser* parent, String filename, StringView contents, String import_base_path); | ||||
| 
 | ||||
|     void assert_specific(char ch); | ||||
|     void assert_string(StringView expected); | ||||
|     void consume_whitespace(); | ||||
|  | @ -53,13 +55,17 @@ private: | |||
|     NonnullRefPtr<Type> parse_type(); | ||||
|     void parse_constant(Interface&); | ||||
| 
 | ||||
|     static HashTable<NonnullOwnPtr<Interface>> s_interfaces; | ||||
|     static HashMap<String, Interface*> s_resolved_imports; | ||||
| 
 | ||||
|     String import_base_path; | ||||
|     String filename; | ||||
|     StringView input; | ||||
|     GenericLexer lexer; | ||||
| 
 | ||||
|     HashTable<NonnullOwnPtr<Interface>>& top_level_interfaces(); | ||||
|     HashTable<NonnullOwnPtr<Interface>> interfaces; | ||||
|     HashMap<String, Interface*>& top_level_resolved_imports(); | ||||
|     HashMap<String, Interface*> resolved_imports; | ||||
|     Parser* top_level_parser(); | ||||
|     Parser* parent = nullptr; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andrew Kaster
						Andrew Kaster