mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 04:09:13 +00:00
JSSpecCompiler: Let FunctionDeclaration know its name and category
This is achieved by moving ClauseHeader::{AbstractOperation,Accessor, Method} to Function.h itself and storing them in FunctionDeclaration. This commit also introduces QualifiedName class that is used to store function's name split by '.' (just like it appear in the spec).
This commit is contained in:
parent
70cfa60f56
commit
0e7c33b1be
Notes:
sideshowbarker
2024-07-17 01:46:43 +09:00
Author: https://github.com/DanShaders
Commit: 0e7c33b1be
Pull-request: https://github.com/SerenityOS/serenity/pull/23647
Reviewed-by: https://github.com/ADKaster ✅
12 changed files with 170 additions and 96 deletions
|
@ -185,7 +185,7 @@ void Enumerator::dump_tree(StringBuilder& builder)
|
||||||
|
|
||||||
void FunctionPointer::dump_tree(StringBuilder& builder)
|
void FunctionPointer::dump_tree(StringBuilder& builder)
|
||||||
{
|
{
|
||||||
dump_node(builder, "Func \"{}\"", m_declaration->m_name);
|
dump_node(builder, "Func \"{}\"", m_declaration->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::dump_tree(StringBuilder& builder)
|
void List::dump_tree(StringBuilder& builder)
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace JSSpecCompiler {
|
||||||
|
|
||||||
void ReferenceResolvingPass::process_function()
|
void ReferenceResolvingPass::process_function()
|
||||||
{
|
{
|
||||||
for (auto argument : m_function->m_arguments)
|
for (auto argument : m_function->arguments())
|
||||||
m_function->m_local_variables.set(argument.name, make_ref_counted<NamedVariableDeclaration>(argument.name));
|
m_function->m_local_variables.set(argument.name, make_ref_counted<NamedVariableDeclaration>(argument.name));
|
||||||
GenericASTPass::process_function();
|
GenericASTPass::process_function();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ void ReferenceResolvingPass::on_leave(Tree tree)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto function = m_translation_unit->find_declaration_by_name(name)) {
|
if (auto function = m_translation_unit->find_abstract_operation_by_name(name)) {
|
||||||
replace_current_node_with(make_ref_counted<FunctionPointer>(function));
|
replace_current_node_with(make_ref_counted<FunctionPointer>(function));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Enumerate.h>
|
||||||
#include <AK/Queue.h>
|
#include <AK/Queue.h>
|
||||||
|
|
||||||
#include "AST/AST.h"
|
#include "AST/AST.h"
|
||||||
|
@ -430,9 +431,9 @@ void SSABuildingPass::rename_variables(Vertex u, Vertex from)
|
||||||
void SSABuildingPass::rename_variables()
|
void SSABuildingPass::rename_variables()
|
||||||
{
|
{
|
||||||
HashMap<StringView, size_t> argument_index_by_name;
|
HashMap<StringView, size_t> argument_index_by_name;
|
||||||
for (size_t i = 0; i < m_function->m_arguments.size(); ++i)
|
for (auto [i, argument] : enumerate(m_function->arguments()))
|
||||||
argument_index_by_name.set(m_function->m_arguments[i].name, i);
|
argument_index_by_name.set(argument.name, i);
|
||||||
m_function->m_ssa_arguments.resize(m_function->m_arguments.size());
|
m_function->m_ssa_arguments.resize(m_function->arguments().size());
|
||||||
|
|
||||||
for (auto const& [name, var_decl] : m_function->m_local_variables) {
|
for (auto const& [name, var_decl] : m_function->m_local_variables) {
|
||||||
make_new_ssa_variable_for(var_decl);
|
make_new_ssa_variable_for(var_decl);
|
||||||
|
|
|
@ -19,23 +19,21 @@ TranslationUnit::~TranslationUnit() = default;
|
||||||
|
|
||||||
void TranslationUnit::adopt_declaration(NonnullRefPtr<FunctionDeclaration>&& declaration)
|
void TranslationUnit::adopt_declaration(NonnullRefPtr<FunctionDeclaration>&& declaration)
|
||||||
{
|
{
|
||||||
declaration->m_translation_unit = this;
|
if (auto decl_name = declaration->declaration(); decl_name.has<AbstractOperationDeclaration>())
|
||||||
m_function_index.set(declaration->m_name, declaration.ptr());
|
m_abstract_operation_index.set(decl_name.get<AbstractOperationDeclaration>().name, declaration.ptr());
|
||||||
m_declarations_owner.append(move(declaration));
|
m_declarations_owner.append(move(declaration));
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinitionRef TranslationUnit::adopt_function(NonnullRefPtr<FunctionDefinition>&& definition)
|
void TranslationUnit::adopt_function(NonnullRefPtr<FunctionDefinition>&& definition)
|
||||||
{
|
{
|
||||||
FunctionDefinitionRef result = definition.ptr();
|
m_functions_to_compile.append(definition);
|
||||||
m_functions_to_compile.append(result);
|
|
||||||
adopt_declaration(definition);
|
adopt_declaration(definition);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDeclarationRef TranslationUnit::find_declaration_by_name(StringView name) const
|
FunctionDeclarationRef TranslationUnit::find_abstract_operation_by_name(StringView name) const
|
||||||
{
|
{
|
||||||
auto it = m_function_index.find(name);
|
auto it = m_abstract_operation_index.find(name);
|
||||||
if (it == m_function_index.end())
|
if (it == m_abstract_operation_index.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return it->value;
|
return it->value;
|
||||||
}
|
}
|
||||||
|
@ -50,14 +48,39 @@ EnumeratorRef TranslationUnit::get_node_for_enumerator_value(StringView value)
|
||||||
return enumerator;
|
return enumerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDeclaration::FunctionDeclaration(StringView name, Vector<FunctionArgument>&& arguments)
|
FunctionDeclaration::FunctionDeclaration(Declaration&& declaration, Location location)
|
||||||
: m_name(name)
|
: m_declaration(move(declaration))
|
||||||
, m_arguments(arguments)
|
, m_location(location)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinition::FunctionDefinition(StringView name, Tree ast, Vector<FunctionArgument>&& arguments)
|
String FunctionDeclaration::name() const
|
||||||
: FunctionDeclaration(name, move(arguments))
|
{
|
||||||
|
return m_declaration.visit(
|
||||||
|
[&](AbstractOperationDeclaration const& abstract_operation) {
|
||||||
|
return abstract_operation.name.to_string();
|
||||||
|
},
|
||||||
|
[&](MethodDeclaration const& method) {
|
||||||
|
return MUST(String::formatted("%{}%", method.name.to_string()));
|
||||||
|
},
|
||||||
|
[&](AccessorDeclaration const& accessor) {
|
||||||
|
return MUST(String::formatted("%get {}%", accessor.name.to_string()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadonlySpan<FunctionArgument> FunctionDeclaration::arguments() const
|
||||||
|
{
|
||||||
|
return m_declaration.visit(
|
||||||
|
[&](AccessorDeclaration const&) {
|
||||||
|
return ReadonlySpan<FunctionArgument> {};
|
||||||
|
},
|
||||||
|
[&](auto const& declaration) {
|
||||||
|
return declaration.arguments.span();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionDefinition::FunctionDefinition(Declaration&& declaration, Location location, Tree ast)
|
||||||
|
: FunctionDeclaration(move(declaration), location)
|
||||||
, m_ast(move(ast))
|
, m_ast(move(ast))
|
||||||
, m_named_return_value(make_ref_counted<NamedVariableDeclaration>("$return"sv))
|
, m_named_return_value(make_ref_counted<NamedVariableDeclaration>("$return"sv))
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,9 +22,8 @@ public:
|
||||||
~TranslationUnit();
|
~TranslationUnit();
|
||||||
|
|
||||||
void adopt_declaration(NonnullRefPtr<FunctionDeclaration>&& declaration);
|
void adopt_declaration(NonnullRefPtr<FunctionDeclaration>&& declaration);
|
||||||
FunctionDefinitionRef adopt_function(NonnullRefPtr<FunctionDefinition>&& definition);
|
void adopt_function(NonnullRefPtr<FunctionDefinition>&& definition);
|
||||||
|
FunctionDeclarationRef find_abstract_operation_by_name(StringView name) const;
|
||||||
FunctionDeclarationRef find_declaration_by_name(StringView name) const;
|
|
||||||
|
|
||||||
StringView filename() const { return m_filename; }
|
StringView filename() const { return m_filename; }
|
||||||
DiagnosticEngine& diag() { return m_diagnostic_engine; }
|
DiagnosticEngine& diag() { return m_diagnostic_engine; }
|
||||||
|
@ -37,7 +36,7 @@ private:
|
||||||
DiagnosticEngine m_diagnostic_engine;
|
DiagnosticEngine m_diagnostic_engine;
|
||||||
Vector<FunctionDefinitionRef> m_functions_to_compile;
|
Vector<FunctionDefinitionRef> m_functions_to_compile;
|
||||||
Vector<NonnullRefPtr<FunctionDeclaration>> m_declarations_owner;
|
Vector<NonnullRefPtr<FunctionDeclaration>> m_declarations_owner;
|
||||||
HashMap<StringView, FunctionDeclarationRef> m_function_index;
|
HashMap<FlyString, FunctionDeclarationRef> m_abstract_operation_index;
|
||||||
HashMap<StringView, EnumeratorRef> m_enumerator_nodes;
|
HashMap<StringView, EnumeratorRef> m_enumerator_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,20 +45,95 @@ struct FunctionArgument {
|
||||||
size_t optional_arguments_group;
|
size_t optional_arguments_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QualifiedName {
|
||||||
|
public:
|
||||||
|
QualifiedName() { }
|
||||||
|
|
||||||
|
QualifiedName(ReadonlySpan<StringView> parsed_name)
|
||||||
|
{
|
||||||
|
m_components.ensure_capacity(parsed_name.size());
|
||||||
|
for (auto component : parsed_name)
|
||||||
|
m_components.unchecked_append(MUST(FlyString::from_utf8(component)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QualifiedName(ReadonlySpan<FlyString> parsed_name)
|
||||||
|
{
|
||||||
|
m_components.ensure_capacity(parsed_name.size());
|
||||||
|
for (auto component : parsed_name)
|
||||||
|
m_components.unchecked_append(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
String to_string() const
|
||||||
|
{
|
||||||
|
return MUST(String::join("."sv, m_components));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<FlyString> const& components() const
|
||||||
|
{
|
||||||
|
return m_components;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlyString last_component() const
|
||||||
|
{
|
||||||
|
return m_components.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadonlySpan<FlyString> without_last_component() const
|
||||||
|
{
|
||||||
|
return components().span().slice(0, components().size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QualifiedName slice(size_t start, size_t length) const
|
||||||
|
{
|
||||||
|
return { m_components.span().slice(start, length) };
|
||||||
|
}
|
||||||
|
|
||||||
|
QualifiedName with_appended(FlyString component) const
|
||||||
|
{
|
||||||
|
auto new_components = m_components;
|
||||||
|
new_components.append(component);
|
||||||
|
return { new_components };
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector<FlyString> m_components;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AbstractOperationDeclaration {
|
||||||
|
FlyString name;
|
||||||
|
Vector<FunctionArgument> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AccessorDeclaration {
|
||||||
|
QualifiedName name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MethodDeclaration {
|
||||||
|
QualifiedName name;
|
||||||
|
Vector<FunctionArgument> arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Declaration = Variant<AbstractOperationDeclaration, AccessorDeclaration, MethodDeclaration>;
|
||||||
|
|
||||||
class FunctionDeclaration : public RefCounted<FunctionDeclaration> {
|
class FunctionDeclaration : public RefCounted<FunctionDeclaration> {
|
||||||
public:
|
public:
|
||||||
FunctionDeclaration(StringView name, Vector<FunctionArgument>&& arguments);
|
FunctionDeclaration(Declaration&& declaration, Location location);
|
||||||
|
|
||||||
virtual ~FunctionDeclaration() = default;
|
virtual ~FunctionDeclaration() = default;
|
||||||
|
|
||||||
TranslationUnitRef m_translation_unit = nullptr;
|
Declaration const& declaration() const { return m_declaration; }
|
||||||
StringView m_name;
|
Location location() const { return m_location; }
|
||||||
Vector<FunctionArgument> m_arguments;
|
String name() const;
|
||||||
|
ReadonlySpan<FunctionArgument> arguments() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Declaration m_declaration;
|
||||||
|
Location m_location;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionDefinition : public FunctionDeclaration {
|
class FunctionDefinition : public FunctionDeclaration {
|
||||||
public:
|
public:
|
||||||
FunctionDefinition(StringView name, Tree ast, Vector<FunctionArgument>&& arguments);
|
FunctionDefinition(Declaration&& declaration, Location location, Tree ast);
|
||||||
|
|
||||||
void reindex_ssa_variables();
|
void reindex_ssa_variables();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,13 @@ NonnullRefPtr<FunctionDefinition> CppASTConverter::convert()
|
||||||
for (auto const& parameter : m_function->parameters())
|
for (auto const& parameter : m_function->parameters())
|
||||||
arguments.append({ .name = parameter->full_name() });
|
arguments.append({ .name = parameter->full_name() });
|
||||||
|
|
||||||
return make_ref_counted<FunctionDefinition>(name, tree, move(arguments));
|
return make_ref_counted<FunctionDefinition>(
|
||||||
|
AbstractOperationDeclaration {
|
||||||
|
.name = MUST(FlyString::from_utf8(name)),
|
||||||
|
.arguments = move(arguments),
|
||||||
|
},
|
||||||
|
Location {},
|
||||||
|
tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -24,7 +24,7 @@ NonnullOwnPtr<SpecificationClause> SpecificationClause::create(SpecificationPars
|
||||||
[&](AK::Empty const&) {
|
[&](AK::Empty const&) {
|
||||||
result = make<SpecificationClause>(move(specification_clause));
|
result = make<SpecificationClause>(move(specification_clause));
|
||||||
},
|
},
|
||||||
[&](OneOf<ClauseHeader::AbstractOperation, ClauseHeader::Accessor, ClauseHeader::Method> auto const&) {
|
[&](OneOf<AbstractOperationDeclaration, AccessorDeclaration, MethodDeclaration> auto const&) {
|
||||||
result = make<SpecificationFunction>(move(specification_clause));
|
result = make<SpecificationFunction>(move(specification_clause));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -15,35 +15,29 @@ bool SpecificationFunction::post_initialize(XML::Node const* element)
|
||||||
VERIFY(element->as_element().name == tag_emu_clause);
|
VERIFY(element->as_element().name == tag_emu_clause);
|
||||||
|
|
||||||
auto& ctx = context();
|
auto& ctx = context();
|
||||||
|
m_location = ctx.location_from_xml_offset(element->offset);
|
||||||
|
|
||||||
auto maybe_id = get_attribute_by_name(element, attribute_id);
|
auto maybe_id = get_attribute_by_name(element, attribute_id);
|
||||||
if (!maybe_id.has_value()) {
|
if (!maybe_id.has_value()) {
|
||||||
ctx.diag().error(ctx.location_from_xml_offset(element->offset),
|
ctx.diag().error(m_location,
|
||||||
"no id attribute");
|
"no id attribute");
|
||||||
} else {
|
} else {
|
||||||
m_id = maybe_id.value();
|
m_id = maybe_id.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_header.header.visit(
|
m_header.header.visit(
|
||||||
[&](ClauseHeader::AbstractOperation const& abstract_operation) {
|
[&](AbstractOperationDeclaration const& abstract_operation) {
|
||||||
auto maybe_abstract_operation_id = get_attribute_by_name(element, attribute_aoid);
|
m_declaration = abstract_operation;
|
||||||
if (maybe_abstract_operation_id.has_value())
|
|
||||||
m_name = MUST(String::from_utf8(maybe_abstract_operation_id.value()));
|
|
||||||
|
|
||||||
auto const& [function_name, arguments] = abstract_operation;
|
auto abstract_operation_id = get_attribute_by_name(element, attribute_aoid).value();
|
||||||
m_arguments = arguments;
|
|
||||||
|
|
||||||
if (m_name != function_name) {
|
if (abstract_operation.name != abstract_operation_id) {
|
||||||
ctx.diag().warn(ctx.location_from_xml_offset(element->offset),
|
ctx.diag().warn(m_location,
|
||||||
"function name in header and <emu-clause>[aoid] do not match");
|
"function name in header and <emu-clause>[aoid] do not match");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](ClauseHeader::Accessor const& accessor) {
|
[&](OneOf<AccessorDeclaration, MethodDeclaration> auto const& declaration) {
|
||||||
m_name = MUST(String::formatted("%get {}%", MUST(String::join("."sv, accessor.qualified_name))));
|
m_declaration = declaration;
|
||||||
},
|
|
||||||
[&](ClauseHeader::Method const& method) {
|
|
||||||
m_name = MUST(String::formatted("%{}%", MUST(String::join("."sv, method.qualified_name))));
|
|
||||||
m_arguments = method.arguments;
|
|
||||||
},
|
},
|
||||||
[&](auto const&) {
|
[&](auto const&) {
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
@ -70,7 +64,7 @@ bool SpecificationFunction::post_initialize(XML::Node const* element)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (algorithm_nodes.size() != 1) {
|
if (algorithm_nodes.size() != 1) {
|
||||||
ctx.diag().error(ctx.location_from_xml_offset(element->offset),
|
ctx.diag().error(m_location,
|
||||||
"<emu-clause> specifing function should have exactly one <emu-alg> child"sv);
|
"<emu-clause> specifing function should have exactly one <emu-alg> child"sv);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +80,7 @@ bool SpecificationFunction::post_initialize(XML::Node const* element)
|
||||||
|
|
||||||
void SpecificationFunction::do_collect(TranslationUnitRef translation_unit)
|
void SpecificationFunction::do_collect(TranslationUnitRef translation_unit)
|
||||||
{
|
{
|
||||||
translation_unit->adopt_function(make_ref_counted<FunctionDefinition>(m_name, m_algorithm.tree(), move(m_arguments)));
|
translation_unit->adopt_function(make_ref_counted<FunctionDefinition>(m_declaration.release_value(), m_location, m_algorithm.tree()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,9 +145,8 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringView m_id;
|
StringView m_id;
|
||||||
String m_name;
|
Optional<Declaration> m_declaration;
|
||||||
|
Location m_location;
|
||||||
Vector<FunctionArgument> m_arguments;
|
|
||||||
Algorithm m_algorithm;
|
Algorithm m_algorithm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -644,14 +644,14 @@ TextParseErrorOr<Tree> TextParser::parse_step_with_substeps(Tree substeps)
|
||||||
}
|
}
|
||||||
|
|
||||||
// <qualified_name> :== <word> (. <word>)*
|
// <qualified_name> :== <word> (. <word>)*
|
||||||
TextParseErrorOr<Vector<StringView>> TextParser::parse_qualified_name()
|
TextParseErrorOr<QualifiedName> TextParser::parse_qualified_name()
|
||||||
{
|
{
|
||||||
Vector<StringView> qualified_name;
|
Vector<StringView> qualified_name;
|
||||||
qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data);
|
qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data);
|
||||||
while (true) {
|
while (true) {
|
||||||
auto token_or_error = consume_token_with_type(TokenType::MemberAccess);
|
auto token_or_error = consume_token_with_type(TokenType::MemberAccess);
|
||||||
if (token_or_error.is_error())
|
if (token_or_error.is_error())
|
||||||
return qualified_name;
|
return QualifiedName { qualified_name };
|
||||||
qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data);
|
qualified_name.append(TRY(consume_token_with_type(TokenType::Word)).data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,12 +702,14 @@ TextParseErrorOr<Vector<FunctionArgument>> TextParser::parse_function_arguments_
|
||||||
}
|
}
|
||||||
|
|
||||||
// <ao_declaration> :== <word> <function_arguments> $
|
// <ao_declaration> :== <word> <function_arguments> $
|
||||||
TextParseErrorOr<ClauseHeader::AbstractOperation> TextParser::parse_abstract_operation_declaration()
|
TextParseErrorOr<AbstractOperationDeclaration> TextParser::parse_abstract_operation_declaration()
|
||||||
{
|
{
|
||||||
auto rollback = rollback_point();
|
auto rollback = rollback_point();
|
||||||
|
|
||||||
ClauseHeader::AbstractOperation function_definition;
|
auto name = TRY(consume_token_with_type(TokenType::Word)).data;
|
||||||
function_definition.name = TRY(consume_token_with_type(TokenType::Word)).data;
|
|
||||||
|
AbstractOperationDeclaration function_definition;
|
||||||
|
function_definition.name = MUST(FlyString::from_utf8(name));
|
||||||
function_definition.arguments = TRY(parse_function_arguments_in_declaration());
|
function_definition.arguments = TRY(parse_function_arguments_in_declaration());
|
||||||
TRY(expect_eof());
|
TRY(expect_eof());
|
||||||
|
|
||||||
|
@ -716,25 +718,25 @@ TextParseErrorOr<ClauseHeader::AbstractOperation> TextParser::parse_abstract_ope
|
||||||
}
|
}
|
||||||
|
|
||||||
// <accessor_declaration> :== get <qualified_name> $
|
// <accessor_declaration> :== get <qualified_name> $
|
||||||
TextParseErrorOr<ClauseHeader::Accessor> TextParser::parse_accessor_declaration()
|
TextParseErrorOr<AccessorDeclaration> TextParser::parse_accessor_declaration()
|
||||||
{
|
{
|
||||||
auto rollback = rollback_point();
|
auto rollback = rollback_point();
|
||||||
|
|
||||||
TRY(consume_word("get"sv));
|
TRY(consume_word("get"sv));
|
||||||
ClauseHeader::Accessor accessor;
|
AccessorDeclaration accessor;
|
||||||
accessor.qualified_name = TRY(parse_qualified_name());
|
accessor.name = TRY(parse_qualified_name());
|
||||||
TRY(expect_eof());
|
TRY(expect_eof());
|
||||||
|
|
||||||
rollback.disarm();
|
rollback.disarm();
|
||||||
return accessor;
|
return accessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextParseErrorOr<ClauseHeader::Method> TextParser::parse_method_declaration()
|
TextParseErrorOr<MethodDeclaration> TextParser::parse_method_declaration()
|
||||||
{
|
{
|
||||||
auto rollback = rollback_point();
|
auto rollback = rollback_point();
|
||||||
|
|
||||||
ClauseHeader::Method method;
|
MethodDeclaration method;
|
||||||
method.qualified_name = TRY(parse_qualified_name());
|
method.name = TRY(parse_qualified_name());
|
||||||
method.arguments = TRY(parse_function_arguments_in_declaration());
|
method.arguments = TRY(parse_function_arguments_in_declaration());
|
||||||
TRY(expect_eof());
|
TRY(expect_eof());
|
||||||
|
|
||||||
|
|
|
@ -13,22 +13,8 @@
|
||||||
namespace JSSpecCompiler {
|
namespace JSSpecCompiler {
|
||||||
|
|
||||||
struct ClauseHeader {
|
struct ClauseHeader {
|
||||||
struct AbstractOperation {
|
|
||||||
StringView name;
|
|
||||||
Vector<FunctionArgument> arguments;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Accessor {
|
|
||||||
Vector<StringView> qualified_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Method {
|
|
||||||
Vector<StringView> qualified_name;
|
|
||||||
Vector<FunctionArgument> arguments;
|
|
||||||
};
|
|
||||||
|
|
||||||
StringView section_number;
|
StringView section_number;
|
||||||
Variant<AK::Empty, AbstractOperation, Accessor, Method> header;
|
Variant<AK::Empty, AbstractOperationDeclaration, AccessorDeclaration, MethodDeclaration> header;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextParseError { };
|
struct TextParseError { };
|
||||||
|
@ -102,11 +88,11 @@ private:
|
||||||
TextParseErrorOr<Tree> parse_if(Tree then_branch);
|
TextParseErrorOr<Tree> parse_if(Tree then_branch);
|
||||||
TextParseErrorOr<Tree> parse_else(Tree else_branch);
|
TextParseErrorOr<Tree> parse_else(Tree else_branch);
|
||||||
|
|
||||||
TextParseErrorOr<Vector<StringView>> parse_qualified_name();
|
TextParseErrorOr<QualifiedName> parse_qualified_name();
|
||||||
TextParseErrorOr<Vector<FunctionArgument>> parse_function_arguments_in_declaration();
|
TextParseErrorOr<Vector<FunctionArgument>> parse_function_arguments_in_declaration();
|
||||||
TextParseErrorOr<ClauseHeader::AbstractOperation> parse_abstract_operation_declaration();
|
TextParseErrorOr<AbstractOperationDeclaration> parse_abstract_operation_declaration();
|
||||||
TextParseErrorOr<ClauseHeader::Method> parse_method_declaration();
|
TextParseErrorOr<MethodDeclaration> parse_method_declaration();
|
||||||
TextParseErrorOr<ClauseHeader::Accessor> parse_accessor_declaration();
|
TextParseErrorOr<AccessorDeclaration> parse_accessor_declaration();
|
||||||
|
|
||||||
SpecificationParsingContext& m_ctx;
|
SpecificationParsingContext& m_ctx;
|
||||||
Vector<Token> const& m_tokens;
|
Vector<Token> const& m_tokens;
|
||||||
|
|
|
@ -71,8 +71,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AK::Formatter<Vector<FunctionArgument>> : AK::Formatter<StringView> {
|
struct AK::Formatter<ReadonlySpan<FunctionArgument>> : AK::Formatter<StringView> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, Vector<FunctionArgument> const& arguments)
|
ErrorOr<void> format(FormatBuilder& builder, ReadonlySpan<FunctionArgument> const& arguments)
|
||||||
{
|
{
|
||||||
size_t previous_optional_group = 0;
|
size_t previous_optional_group = 0;
|
||||||
for (size_t i = 0; i < arguments.size(); ++i) {
|
for (size_t i = 0; i < arguments.size(); ++i) {
|
||||||
|
@ -139,17 +139,6 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
TranslationUnit translation_unit(filename);
|
TranslationUnit translation_unit(filename);
|
||||||
|
|
||||||
// Functions referenced in DifferenceISODate
|
|
||||||
// TODO: This is here just for testing. In a long run, we need some place, which is not
|
|
||||||
// `serenity_main`, to store built-in functions.
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("CompareISODate"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("CreateDateDurationRecord"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("AddISODate"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("ISODaysInMonth"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("ISODateToEpochDays"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("truncate"sv, Vector<FunctionArgument> {}));
|
|
||||||
translation_unit.adopt_declaration(make_ref_counted<FunctionDeclaration>("remainder"sv, Vector<FunctionArgument> {}));
|
|
||||||
|
|
||||||
for (auto const& step : pipeline.pipeline()) {
|
for (auto const& step : pipeline.pipeline()) {
|
||||||
step.step->run(&translation_unit);
|
step.step->run(&translation_unit);
|
||||||
|
|
||||||
|
@ -161,14 +150,14 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
if (step.dump_ast) {
|
if (step.dump_ast) {
|
||||||
outln(stderr, "===== AST after {} =====", step.step->name());
|
outln(stderr, "===== AST after {} =====", step.step->name());
|
||||||
for (auto const& function : translation_unit.functions_to_compile()) {
|
for (auto const& function : translation_unit.functions_to_compile()) {
|
||||||
outln(stderr, "{}({}):", function->m_name, function->m_arguments);
|
outln(stderr, "{}({}):", function->name(), function->arguments());
|
||||||
outln(stderr, "{}", function->m_ast);
|
outln(stderr, "{}", function->m_ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (step.dump_cfg && translation_unit.functions_to_compile().size() && translation_unit.functions_to_compile()[0]->m_cfg != nullptr) {
|
if (step.dump_cfg && translation_unit.functions_to_compile().size() && translation_unit.functions_to_compile()[0]->m_cfg != nullptr) {
|
||||||
outln(stderr, "===== CFG after {} =====", step.step->name());
|
outln(stderr, "===== CFG after {} =====", step.step->name());
|
||||||
for (auto const& function : translation_unit.functions_to_compile()) {
|
for (auto const& function : translation_unit.functions_to_compile()) {
|
||||||
outln(stderr, "{}({}):", function->m_name, function->m_arguments);
|
outln(stderr, "{}({}):", function->name(), function->arguments());
|
||||||
outln(stderr, "{}", *function->m_cfg);
|
outln(stderr, "{}", *function->m_cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue