1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:28:11 +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

@ -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;
}
}