1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-22 21:17:40 +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:
Andrew Kaster 2022-10-08 16:48:04 -06:00 committed by Andreas Kling
parent 2341294c20
commit 067a53b7e7
3 changed files with 49 additions and 14 deletions

View file

@ -71,7 +71,8 @@ int main(int argc, char** argv)
if (import_base_path.is_null()) if (import_base_path.is_null())
import_base_path = lexical_path.dirname(); 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 = { static constexpr Array libweb_interface_namespaces = {
"CSS"sv, "CSS"sv,

View file

@ -8,6 +8,7 @@
*/ */
#include "IDLParser.h" #include "IDLParser.h"
#include <AK/Assertions.h>
#include <AK/LexicalPath.h> #include <AK/LexicalPath.h>
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <LibCore/File.h> #include <LibCore/File.h>
@ -76,9 +77,6 @@ static String convert_enumeration_value_to_cpp_enum_member(String const& value,
namespace IDL { namespace IDL {
HashTable<NonnullOwnPtr<Interface>> Parser::s_interfaces {};
HashMap<String, Interface*> Parser::s_resolved_imports {};
void Parser::assert_specific(char ch) void Parser::assert_specific(char ch)
{ {
if (!lexer.consume_specific(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()); 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); auto real_path = Core::File::real_path_for(include_path);
if (s_resolved_imports.contains(real_path)) if (top_level_resolved_imports().contains(real_path))
return *s_resolved_imports.find(real_path)->value; return *top_level_resolved_imports().find(real_path)->value;
if (import_stack.contains(real_path)) if (import_stack.contains(real_path))
report_parsing_error(String::formatted("Circular import detected: {}", include_path), filename, input, lexer.tell()); 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()); 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 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); import_stack.remove(real_path);
s_resolved_imports.set(real_path, &result); top_level_resolved_imports().set(real_path, &result);
return result; return result;
} }
@ -736,7 +734,7 @@ void Parser::parse_interface_mixin(Interface& interface)
{ {
auto mixin_interface_ptr = make<Interface>(); auto mixin_interface_ptr = make<Interface>();
auto& mixin_interface = *mixin_interface_ptr; 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.module_own_path = interface.module_own_path;
mixin_interface.is_mixin = true; mixin_interface.is_mixin = true;
@ -856,9 +854,9 @@ Interface& Parser::parse()
auto interface_ptr = make<Interface>(); auto interface_ptr = make<Interface>();
auto& interface = *interface_ptr; 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; interface.module_own_path = this_module;
s_resolved_imports.set(this_module, &interface); top_level_resolved_imports().set(this_module, &interface);
Vector<Interface&> imports; Vector<Interface&> imports;
HashTable<String> required_imported_paths; HashTable<String> required_imported_paths;
@ -998,6 +996,9 @@ Interface& Parser::parse()
interface.required_imported_paths.set(this_module); interface.required_imported_paths.set(this_module);
interface.imported_modules = move(imports); interface.imported_modules = move(imports);
if (top_level_parser() == this)
VERIFY(import_stack.is_empty());
return interface; 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;
}
} }

View file

@ -28,6 +28,8 @@ private:
Yes, Yes,
}; };
Parser(Parser* parent, String filename, StringView contents, String import_base_path);
void assert_specific(char ch); void assert_specific(char ch);
void assert_string(StringView expected); void assert_string(StringView expected);
void consume_whitespace(); void consume_whitespace();
@ -53,13 +55,17 @@ private:
NonnullRefPtr<Type> parse_type(); NonnullRefPtr<Type> parse_type();
void parse_constant(Interface&); void parse_constant(Interface&);
static HashTable<NonnullOwnPtr<Interface>> s_interfaces;
static HashMap<String, Interface*> s_resolved_imports;
String import_base_path; String import_base_path;
String filename; String filename;
StringView input; StringView input;
GenericLexer lexer; 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;
}; };
} }