mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 04:17:35 +00:00
LibIDL+WrapperGenerator: Move IDL code into a library
IDL function overload resolution requires knowing each IDL function's parameters and their types at runtime. The simplest way to do that is just to make the types the generator uses available to the runtime. Parsing has moved to LibIDL, but code generation has not, since that is very specific to WrapperGenerator.
This commit is contained in:
parent
634a52b589
commit
c4668053d1
9 changed files with 25 additions and 12 deletions
|
@ -1,8 +1,7 @@
|
|||
set(SOURCES "")
|
||||
|
||||
lagom_tool(WrapperGenerator SOURCES
|
||||
set(SOURCES
|
||||
IDLGenerators.cpp
|
||||
IDLParser.cpp
|
||||
main.cpp)
|
||||
main.cpp
|
||||
)
|
||||
|
||||
lagom_tool(WrapperGenerator LIBS LibIDL)
|
||||
target_compile_options(WrapperGenerator PUBLIC -g)
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "IDLTypes.h"
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/Queue.h>
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibIDL/Types.h>
|
||||
|
||||
Vector<StringView> s_header_search_paths;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IDLTypes.h"
|
||||
#include <AK/CharacterTypes.h>
|
||||
#include <AK/GenericLexer.h>
|
||||
|
||||
namespace IDL {
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
Parser(String filename, StringView contents, String import_base_path);
|
||||
Interface& parse();
|
||||
|
||||
private:
|
||||
// https://webidl.spec.whatwg.org/#dfn-special-operation
|
||||
// A special operation is a getter, setter or deleter.
|
||||
enum class IsSpecialOperation {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
void assert_specific(char ch);
|
||||
void assert_string(StringView expected);
|
||||
void consume_whitespace();
|
||||
Optional<Interface&> resolve_import(auto path);
|
||||
|
||||
HashMap<String, String> parse_extended_attributes();
|
||||
void parse_attribute(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_interface(Interface&);
|
||||
void parse_non_interface_entities(bool allow_interface, Interface&);
|
||||
void parse_enumeration(Interface&);
|
||||
void parse_typedef(Interface&);
|
||||
void parse_interface_mixin(Interface&);
|
||||
void parse_dictionary(Interface&);
|
||||
void parse_callback_function(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_constructor(Interface&);
|
||||
void parse_getter(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_setter(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_deleter(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_stringifier(HashMap<String, String>& extended_attributes, Interface&);
|
||||
void parse_iterable(Interface&);
|
||||
Function parse_function(HashMap<String, String>& extended_attributes, Interface&, IsSpecialOperation is_special_operation = IsSpecialOperation::No);
|
||||
Vector<Parameter> parse_parameters();
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,339 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
|
||||
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/NonnullRefPtrVector.h>
|
||||
#include <AK/SourceGenerator.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/Tuple.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
|
||||
namespace IDL {
|
||||
|
||||
template<typename FunctionType>
|
||||
static size_t get_function_shortest_length(FunctionType& function)
|
||||
{
|
||||
size_t length = 0;
|
||||
for (auto& parameter : function.parameters) {
|
||||
if (!parameter.optional && !parameter.variadic)
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
enum class SequenceStorageType {
|
||||
Vector, // Used to safely store non-JS values
|
||||
MarkedVector, // Used to safely store JS::Value and anything that inherits JS::Cell, e.g. JS::Object
|
||||
};
|
||||
|
||||
struct CppType {
|
||||
String name;
|
||||
SequenceStorageType sequence_storage_type;
|
||||
};
|
||||
|
||||
struct Type : public RefCounted<Type> {
|
||||
Type() = default;
|
||||
|
||||
Type(String name, bool nullable)
|
||||
: name(move(name))
|
||||
, nullable(nullable)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Type() = default;
|
||||
|
||||
String name;
|
||||
bool nullable { false };
|
||||
bool is_string() const { return name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-integer-type
|
||||
bool is_integer() const { return name.is_one_of("byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", "unsigned long long"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-numeric-type
|
||||
bool is_numeric() const { return is_integer() || name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-primitive-type
|
||||
bool is_primitive() const { return is_numeric() || name.is_one_of("bigint", "boolean"); }
|
||||
};
|
||||
|
||||
struct Parameter {
|
||||
NonnullRefPtr<Type> type;
|
||||
String name;
|
||||
bool optional { false };
|
||||
Optional<String> optional_default_value;
|
||||
HashMap<String, String> extended_attributes;
|
||||
bool variadic { false };
|
||||
};
|
||||
|
||||
struct Function {
|
||||
NonnullRefPtr<Type> return_type;
|
||||
String name;
|
||||
Vector<Parameter> parameters;
|
||||
HashMap<String, String> extended_attributes;
|
||||
size_t overload_index { 0 };
|
||||
bool is_overloaded { false };
|
||||
|
||||
size_t shortest_length() const { return get_function_shortest_length(*this); }
|
||||
};
|
||||
|
||||
struct Constructor {
|
||||
String name;
|
||||
Vector<Parameter> parameters;
|
||||
|
||||
size_t shortest_length() const { return get_function_shortest_length(*this); }
|
||||
};
|
||||
|
||||
struct Constant {
|
||||
NonnullRefPtr<Type> type;
|
||||
String name;
|
||||
String value;
|
||||
};
|
||||
|
||||
struct Attribute {
|
||||
bool readonly { false };
|
||||
NonnullRefPtr<Type> type;
|
||||
String name;
|
||||
HashMap<String, String> extended_attributes;
|
||||
|
||||
// Added for convenience after parsing
|
||||
String getter_callback_name;
|
||||
String setter_callback_name;
|
||||
};
|
||||
|
||||
struct DictionaryMember {
|
||||
bool required { false };
|
||||
NonnullRefPtr<Type> type;
|
||||
String name;
|
||||
HashMap<String, String> extended_attributes;
|
||||
Optional<String> default_value;
|
||||
};
|
||||
|
||||
struct Dictionary {
|
||||
String parent_name;
|
||||
Vector<DictionaryMember> members;
|
||||
};
|
||||
|
||||
struct Typedef {
|
||||
HashMap<String, String> extended_attributes;
|
||||
NonnullRefPtr<Type> type;
|
||||
};
|
||||
|
||||
struct Enumeration {
|
||||
HashTable<String> values;
|
||||
HashMap<String, String> translated_cpp_names;
|
||||
String first_member;
|
||||
bool is_original_definition { true };
|
||||
};
|
||||
|
||||
struct CallbackFunction {
|
||||
NonnullRefPtr<Type> return_type;
|
||||
Vector<Parameter> parameters;
|
||||
bool is_legacy_treat_non_object_as_null { false };
|
||||
};
|
||||
|
||||
class Interface;
|
||||
|
||||
struct ParameterizedType : public Type {
|
||||
ParameterizedType() = default;
|
||||
|
||||
ParameterizedType(String name, bool nullable, NonnullRefPtrVector<Type> parameters)
|
||||
: Type(move(name), nullable)
|
||||
, parameters(move(parameters))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ParameterizedType() override = default;
|
||||
|
||||
NonnullRefPtrVector<Type> parameters;
|
||||
|
||||
void generate_sequence_from_iterable(SourceGenerator& generator, String const& cpp_name, String const& iterable_cpp_name, String const& iterator_method_cpp_name, IDL::Interface const&, size_t recursion_depth) const;
|
||||
};
|
||||
|
||||
static inline size_t get_shortest_function_length(Vector<Function&> const& overload_set)
|
||||
{
|
||||
size_t shortest_length = SIZE_MAX;
|
||||
for (auto const& function : overload_set)
|
||||
shortest_length = min(function.shortest_length(), shortest_length);
|
||||
return shortest_length;
|
||||
}
|
||||
|
||||
class Interface {
|
||||
AK_MAKE_NONCOPYABLE(Interface);
|
||||
AK_MAKE_NONMOVABLE(Interface);
|
||||
|
||||
public:
|
||||
explicit Interface() = default;
|
||||
|
||||
String name;
|
||||
String parent_name;
|
||||
|
||||
bool is_mixin { false };
|
||||
|
||||
HashMap<String, String> extended_attributes;
|
||||
|
||||
Vector<Attribute> attributes;
|
||||
Vector<Constant> constants;
|
||||
Vector<Constructor> constructors;
|
||||
Vector<Function> functions;
|
||||
Vector<Function> static_functions;
|
||||
bool has_stringifier { false };
|
||||
Optional<String> stringifier_attribute;
|
||||
bool has_unscopable_member { false };
|
||||
|
||||
Optional<NonnullRefPtr<Type>> value_iterator_type;
|
||||
Optional<Tuple<NonnullRefPtr<Type>, NonnullRefPtr<Type>>> pair_iterator_types;
|
||||
|
||||
Optional<Function> named_property_getter;
|
||||
Optional<Function> named_property_setter;
|
||||
|
||||
Optional<Function> indexed_property_getter;
|
||||
Optional<Function> indexed_property_setter;
|
||||
|
||||
Optional<Function> named_property_deleter;
|
||||
|
||||
HashMap<String, Dictionary> dictionaries;
|
||||
HashMap<String, Enumeration> enumerations;
|
||||
HashMap<String, Typedef> typedefs;
|
||||
HashMap<String, Interface*> mixins;
|
||||
HashMap<String, CallbackFunction> callback_functions;
|
||||
|
||||
// Added for convenience after parsing
|
||||
String wrapper_class;
|
||||
String wrapper_base_class;
|
||||
String fully_qualified_name;
|
||||
String constructor_class;
|
||||
String prototype_class;
|
||||
String prototype_base_class;
|
||||
HashMap<String, HashTable<String>> included_mixins;
|
||||
|
||||
String module_own_path;
|
||||
HashTable<String> required_imported_paths;
|
||||
Vector<Interface&> imported_modules;
|
||||
|
||||
HashMap<String, Vector<Function&>> overload_sets;
|
||||
HashMap<String, Vector<Function&>> static_overload_sets;
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-support-indexed-properties
|
||||
bool supports_indexed_properties() const { return indexed_property_getter.has_value(); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-support-named-properties
|
||||
bool supports_named_properties() const { return named_property_getter.has_value(); }
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-legacy-platform-object
|
||||
bool is_legacy_platform_object() const { return !extended_attributes.contains("Global") && (supports_indexed_properties() || supports_named_properties()); }
|
||||
|
||||
bool will_generate_code() const
|
||||
{
|
||||
return !name.is_empty() || any_of(enumerations, [](auto& entry) { return entry.value.is_original_definition; });
|
||||
}
|
||||
};
|
||||
|
||||
struct UnionType : public Type {
|
||||
UnionType() = default;
|
||||
|
||||
UnionType(String name, bool nullable, NonnullRefPtrVector<Type> member_types)
|
||||
: Type(move(name), nullable)
|
||||
, member_types(move(member_types))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~UnionType() override = default;
|
||||
|
||||
NonnullRefPtrVector<Type> member_types;
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
|
||||
NonnullRefPtrVector<Type> flattened_member_types() const
|
||||
{
|
||||
// 1. Let T be the union type.
|
||||
|
||||
// 2. Initialize S to ∅.
|
||||
NonnullRefPtrVector<Type> types;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : member_types) {
|
||||
// FIXME: 1. If U is an annotated type, then set U to be the inner type of U.
|
||||
|
||||
// 2. If U is a nullable type, then set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
|
||||
|
||||
// 3. If U is a union type, then add to S the flattened member types of U.
|
||||
if (is<UnionType>(type)) {
|
||||
auto& union_member_type = verify_cast<UnionType>(type);
|
||||
types.extend(union_member_type.flattened_member_types());
|
||||
} else {
|
||||
// 4. Otherwise, U is not a union type. Add U to S.
|
||||
types.append(type);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Return S.
|
||||
return types;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-number-of-nullable-member-types
|
||||
size_t number_of_nullable_member_types() const
|
||||
{
|
||||
// 1. Let T be the union type.
|
||||
|
||||
// 2. Initialize n to 0.
|
||||
size_t num_nullable_member_types = 0;
|
||||
|
||||
// 3. For each member type U of T:
|
||||
for (auto& type : member_types) {
|
||||
// 1. If U is a nullable type, then:
|
||||
if (type.nullable) {
|
||||
// 1. Set n to n + 1.
|
||||
++num_nullable_member_types;
|
||||
|
||||
// 2. Set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
|
||||
}
|
||||
|
||||
// 2. If U is a union type, then:
|
||||
if (is<UnionType>(type)) {
|
||||
auto& union_member_type = verify_cast<UnionType>(type);
|
||||
|
||||
// 1. Let m be the number of nullable member types of U.
|
||||
// 2. Set n to n + m.
|
||||
num_nullable_member_types += union_member_type.number_of_nullable_member_types();
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Return n.
|
||||
return num_nullable_member_types;
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type
|
||||
bool includes_nullable_type() const
|
||||
{
|
||||
// -> the type is a union type and its number of nullable member types is 1.
|
||||
return number_of_nullable_member_types() == 1;
|
||||
}
|
||||
|
||||
// -> https://webidl.spec.whatwg.org/#dfn-includes-undefined
|
||||
bool includes_undefined() const
|
||||
{
|
||||
// -> the type is a union type and one of its member types includes undefined.
|
||||
for (auto& type : member_types) {
|
||||
if (is<UnionType>(type)) {
|
||||
auto& union_type = verify_cast<UnionType>(type);
|
||||
if (union_type.includes_undefined())
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.name == "undefined"sv)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -7,12 +7,12 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "IDLParser.h"
|
||||
#include "IDLTypes.h"
|
||||
#include <AK/Debug.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <LibCore/ArgsParser.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibIDL/IDLParser.h>
|
||||
#include <LibIDL/Types.h>
|
||||
|
||||
extern Vector<StringView> s_header_search_paths;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue