mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-11 17:00:37 +00:00
AK: Introduce SourceGenerator::fork().
Previously, I abused the copy constructor, this is a lot better.
This commit is contained in:
parent
bf1ed34236
commit
61e73b1a7b
Notes:
sideshowbarker
2024-07-19 01:46:48 +09:00
Author: https://github.com/asynts Commit: https://github.com/SerenityOS/serenity/commit/61e73b1a7b5 Pull-request: https://github.com/SerenityOS/serenity/pull/3828
3 changed files with 48 additions and 67 deletions
|
@ -34,54 +34,32 @@
|
|||
namespace AK {
|
||||
|
||||
class SourceGenerator {
|
||||
AK_MAKE_NONCOPYABLE(SourceGenerator);
|
||||
|
||||
public:
|
||||
using MappingType = HashMap<StringView, String>;
|
||||
|
||||
explicit SourceGenerator(SourceGenerator& parent, char opening = '@', char closing = '@')
|
||||
: m_parent(&parent)
|
||||
explicit SourceGenerator(StringBuilder& builder, char opening = '@', char closing = '@')
|
||||
: m_builder(builder)
|
||||
, m_opening(opening)
|
||||
, m_closing(closing)
|
||||
{
|
||||
}
|
||||
explicit SourceGenerator(char opening = '@', char closing = '@')
|
||||
: m_parent(nullptr)
|
||||
explicit SourceGenerator(StringBuilder& builder, const MappingType& mapping, char opening = '@', char closing = '@')
|
||||
: m_builder(builder)
|
||||
, m_mapping(mapping)
|
||||
, m_opening(opening)
|
||||
, m_closing(closing)
|
||||
{
|
||||
m_builder = new StringBuilder();
|
||||
}
|
||||
|
||||
SourceGenerator fork() { return SourceGenerator { m_builder, m_mapping, m_opening, m_closing }; }
|
||||
|
||||
void set(StringView key, String value) { m_mapping.set(key, value); }
|
||||
String get(StringView key) const { return m_mapping.get(key).value(); }
|
||||
|
||||
String lookup(StringView key) const
|
||||
{
|
||||
if (auto opt = m_mapping.get(key); opt.has_value())
|
||||
return opt.value();
|
||||
|
||||
if (m_parent == nullptr) {
|
||||
dbgln("Can't find key '{}'", key);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
return m_parent->lookup(key);
|
||||
}
|
||||
|
||||
String generate() const { return builder().build(); }
|
||||
|
||||
StringBuilder& builder()
|
||||
{
|
||||
if (m_parent)
|
||||
return m_parent->builder();
|
||||
else
|
||||
return *m_builder;
|
||||
}
|
||||
const StringBuilder& builder() const
|
||||
{
|
||||
if (m_parent)
|
||||
return m_parent->builder();
|
||||
else
|
||||
return *m_builder;
|
||||
}
|
||||
StringView as_string_view() const { return m_builder.string_view(); }
|
||||
String as_string() const { return m_builder.build(); }
|
||||
|
||||
void append(StringView pattern)
|
||||
{
|
||||
|
@ -94,7 +72,7 @@ public:
|
|||
return lexer.consume_while([&](char ch) { return ch != stop; });
|
||||
};
|
||||
|
||||
builder().append(consume_until_without_consuming_stop_character(m_opening));
|
||||
m_builder.append(consume_until_without_consuming_stop_character(m_opening));
|
||||
|
||||
if (lexer.consume_specific(m_opening)) {
|
||||
const auto placeholder = consume_until_without_consuming_stop_character(m_closing);
|
||||
|
@ -102,7 +80,7 @@ public:
|
|||
if (!lexer.consume_specific(m_closing))
|
||||
ASSERT_NOT_REACHED();
|
||||
|
||||
builder().append(lookup(placeholder));
|
||||
m_builder.append(get(placeholder));
|
||||
} else {
|
||||
ASSERT(lexer.is_eof());
|
||||
}
|
||||
|
@ -110,9 +88,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
SourceGenerator* m_parent;
|
||||
StringBuilder& m_builder;
|
||||
MappingType m_mapping;
|
||||
OwnPtr<StringBuilder> m_builder;
|
||||
char m_opening, m_closing;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,19 +28,31 @@
|
|||
|
||||
#include <AK/SourceGenerator.h>
|
||||
|
||||
TEST_CASE(wrap_builder)
|
||||
{
|
||||
StringBuilder builder;
|
||||
SourceGenerator generator { builder };
|
||||
|
||||
generator.append("Hello, World!");
|
||||
|
||||
EXPECT_EQ(builder.string_view(), "Hello, World!");
|
||||
}
|
||||
|
||||
TEST_CASE(generate_c_code)
|
||||
{
|
||||
SourceGenerator generator;
|
||||
StringBuilder builder;
|
||||
SourceGenerator generator { builder };
|
||||
generator.set("name", "foo");
|
||||
|
||||
generator.append("const char* @name@ (void) { return \"@name@\"; }");
|
||||
|
||||
EXPECT_EQ(generator.generate(), "const char* foo (void) { return \"foo\"; }");
|
||||
EXPECT_EQ(generator.as_string_view(), "const char* foo (void) { return \"foo\"; }");
|
||||
}
|
||||
|
||||
TEST_CASE(scoped)
|
||||
{
|
||||
SourceGenerator global_generator;
|
||||
StringBuilder builder;
|
||||
SourceGenerator global_generator { builder };
|
||||
|
||||
global_generator.append("\n");
|
||||
|
||||
|
@ -49,8 +61,7 @@ TEST_CASE(scoped)
|
|||
global_generator.append("@foo@ @bar@\n"); // foo-0 bar-0
|
||||
|
||||
{
|
||||
SourceGenerator scoped_generator_1 { global_generator };
|
||||
|
||||
auto scoped_generator_1 = global_generator.fork();
|
||||
scoped_generator_1.set("bar", "bar-1");
|
||||
global_generator.append("@foo@ @bar@\n"); // foo-0 bar-0
|
||||
}
|
||||
|
@ -58,28 +69,25 @@ TEST_CASE(scoped)
|
|||
global_generator.append("@foo@ @bar@\n"); // foo-0 bar-0
|
||||
|
||||
{
|
||||
SourceGenerator scoped_generator_2 { global_generator };
|
||||
|
||||
auto scoped_generator_2 = global_generator.fork();
|
||||
scoped_generator_2.set("foo", "foo-2");
|
||||
scoped_generator_2.append("@foo@ @bar@\n"); // foo-2 bar-0
|
||||
|
||||
{
|
||||
// FIXME: This is never put onto the output?
|
||||
|
||||
SourceGenerator scoped_generator_3 { scoped_generator_2 };
|
||||
auto scoped_generator_3 = scoped_generator_2.fork();
|
||||
scoped_generator_3.set("bar", "bar-3");
|
||||
scoped_generator_3.append("@foo@ @bar@\n"); // foo-2 bar-3
|
||||
}
|
||||
|
||||
{
|
||||
SourceGenerator scoped_generator_4 { global_generator };
|
||||
auto scoped_generator_4 = global_generator.fork();
|
||||
scoped_generator_4.append("@foo@ @bar@\n"); // foo-0 bar-0
|
||||
}
|
||||
|
||||
scoped_generator_2.append("@foo@ @bar@\n"); // foo-2 bar-0
|
||||
}
|
||||
|
||||
EXPECT_EQ(global_generator.generate(), "\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-2 bar-0\nfoo-2 bar-3\nfoo-0 bar-0\nfoo-2 bar-0\n");
|
||||
EXPECT_EQ(global_generator.as_string_view(), "\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-0 bar-0\nfoo-2 bar-0\nfoo-2 bar-3\nfoo-0 bar-0\nfoo-2 bar-0\n");
|
||||
}
|
||||
|
||||
TEST_MAIN(SourceGenerator)
|
||||
|
|
|
@ -200,7 +200,8 @@ int main(int argc, char** argv)
|
|||
while (lexer.tell() < file_contents.size())
|
||||
parse_endpoint();
|
||||
|
||||
SourceGenerator generator;
|
||||
StringBuilder builder;
|
||||
SourceGenerator generator { builder };
|
||||
|
||||
generator.append(R"~~~(
|
||||
#pragma once
|
||||
|
@ -219,7 +220,7 @@ int main(int argc, char** argv)
|
|||
)~~~");
|
||||
|
||||
for (auto& endpoint : endpoints) {
|
||||
SourceGenerator endpoint_generator { generator };
|
||||
auto endpoint_generator = generator.fork();
|
||||
|
||||
endpoint_generator.set("endpoint.name", endpoint.name);
|
||||
endpoint_generator.set("endpoint.magic", String::number(endpoint.magic));
|
||||
|
@ -234,7 +235,7 @@ namespace Messages::@endpoint.name@ {
|
|||
enum class MessageID : i32 {
|
||||
)~~~");
|
||||
for (auto& message : endpoint.messages) {
|
||||
SourceGenerator message_generator { endpoint_generator };
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
|
||||
message_ids.set(message.name, message_ids.size() + 1);
|
||||
message_generator.set("message.name", message.name);
|
||||
|
@ -292,8 +293,7 @@ enum class MessageID : i32 {
|
|||
};
|
||||
|
||||
auto do_message = [&](const String& name, const Vector<Parameter>& parameters, const String& response_type = {}) {
|
||||
SourceGenerator message_generator { endpoint_generator };
|
||||
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
message_generator.set("message.name", name);
|
||||
message_generator.set("message.response_type", response_type);
|
||||
message_generator.set("message.constructor", constructor_for_message(name, parameters));
|
||||
|
@ -323,7 +323,7 @@ public:
|
|||
)~~~");
|
||||
|
||||
for (auto& parameter : parameters) {
|
||||
SourceGenerator parameter_generator { message_generator };
|
||||
auto parameter_generator = message_generator.fork();
|
||||
|
||||
parameter_generator.set("parameter.type", parameter.type);
|
||||
parameter_generator.set("parameter.name", parameter.name);
|
||||
|
@ -373,7 +373,7 @@ public:
|
|||
)~~~");
|
||||
|
||||
for (auto& parameter : parameters) {
|
||||
SourceGenerator parameter_generator { message_generator };
|
||||
auto parameter_generator = message_generator.fork();
|
||||
|
||||
parameter_generator.set("parameter.name", parameter.name);
|
||||
parameter_generator.append(R"~~~(
|
||||
|
@ -387,8 +387,7 @@ public:
|
|||
)~~~");
|
||||
|
||||
for (auto& parameter : parameters) {
|
||||
SourceGenerator parameter_generator { message_generator };
|
||||
|
||||
auto parameter_generator = message_generator.fork();
|
||||
parameter_generator.set("parameter.type", parameter.type);
|
||||
parameter_generator.set("parameter.name", parameter.name);
|
||||
parameter_generator.append(R"~~~(
|
||||
|
@ -401,8 +400,7 @@ private:
|
|||
)~~~");
|
||||
|
||||
for (auto& parameter : parameters) {
|
||||
SourceGenerator parameter_generator { message_generator };
|
||||
|
||||
auto parameter_generator = message_generator.fork();
|
||||
parameter_generator.set("parameter.type", parameter.type);
|
||||
parameter_generator.set("parameter.name", parameter.name);
|
||||
parameter_generator.append(R"~~~(
|
||||
|
@ -484,7 +482,7 @@ public:
|
|||
|
||||
for (auto& message : endpoint.messages) {
|
||||
auto do_decode_message = [&](const String& name) {
|
||||
SourceGenerator message_generator { endpoint_generator };
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
|
||||
message_generator.set("message.name", name);
|
||||
|
||||
|
@ -532,7 +530,7 @@ public:
|
|||
)~~~");
|
||||
for (auto& message : endpoint.messages) {
|
||||
auto do_decode_message = [&](const String& name, bool returns_something) {
|
||||
SourceGenerator message_generator { endpoint_generator };
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
|
||||
message_generator.set("message.name", name);
|
||||
message_generator.append(R"~~~(
|
||||
|
@ -561,7 +559,7 @@ public:
|
|||
)~~~");
|
||||
|
||||
for (auto& message : endpoint.messages) {
|
||||
SourceGenerator message_generator { endpoint_generator };
|
||||
auto message_generator = endpoint_generator.fork();
|
||||
|
||||
message_generator.set("message.name", message.name);
|
||||
|
||||
|
@ -589,7 +587,7 @@ private:
|
|||
)~~~");
|
||||
}
|
||||
|
||||
outln("{}", generator.generate());
|
||||
outln("{}", generator.as_string_view());
|
||||
|
||||
#ifdef DEBUG
|
||||
for (auto& endpoint : endpoints) {
|
||||
|
@ -612,6 +610,4 @@ private:
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue