From 72794e7843c6f535c2109d37d17f39e925b2f972 Mon Sep 17 00:00:00 2001 From: Dan Klishch Date: Fri, 18 Aug 2023 13:12:53 -0400 Subject: [PATCH] JSSpecCompiler: Add function call canonicalization pass It simplifies ladders of BinaryOperators nodes in the function call arguments into nice and neat FunctionCall node. Ladders initially appear since I do not want to complicate expression parser, so it interprets `f(a, b, c, d)` as `f "function_call_operator" (a, (b, (c, d))))`. --- .../JSSpecCompiler/CMakeLists.txt | 1 + .../FunctionCallCanonicalizationPass.cpp | 34 +++++++++++++++++++ .../FunctionCallCanonicalizationPass.h | 26 ++++++++++++++ .../CodeGenerators/JSSpecCompiler/main.cpp | 12 +++++-- 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.cpp create mode 100644 Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.h diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt index 5c02c2559f..2fc266f17d 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES AST/AST.cpp AST/ASTPrinting.cpp + Compiler/FunctionCallCanonicalizationPass.cpp Compiler/GenericASTPass.cpp Parser/Lexer.cpp Parser/ParseError.cpp diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.cpp new file mode 100644 index 0000000000..9f0f18313e --- /dev/null +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Compiler/FunctionCallCanonicalizationPass.h" +#include "AST/AST.h" + +namespace JSSpecCompiler { + +RecursionDecision FunctionCallCanonicalizationPass::on_entry(Tree tree) +{ + if (auto binary_operation = as(tree); binary_operation) { + if (binary_operation->m_operation == BinaryOperator::FunctionCall) { + Vector arguments; + + auto current_tree = binary_operation->m_right; + while (true) { + auto argument_tree = as(current_tree); + if (!argument_tree || argument_tree->m_operation != BinaryOperator::Comma) + break; + arguments.append(argument_tree->m_left); + current_tree = argument_tree->m_right; + } + arguments.append(current_tree); + + replace_current_node_with(make_ref_counted(binary_operation->m_left, move(arguments))); + } + } + return RecursionDecision::Recurse; +} + +} diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.h b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.h new file mode 100644 index 0000000000..32e12f748e --- /dev/null +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/Compiler/FunctionCallCanonicalizationPass.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023, Dan Klishch + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include "Compiler/GenericASTPass.h" + +namespace JSSpecCompiler { + +// FunctionCallCanonicalizationPass simplifies ladders of BinaryOperators nodes in the function call +// arguments into nice and neat FunctionCall nodes. +// +// Ladders initially appear since I do not want to complicate expression parser, so it interprets +// `f(a, b, c, d)` as `f "function_call_operator" (a, (b, (c, d))))`. +class FunctionCallCanonicalizationPass : public GenericASTPass { +public: + using GenericASTPass::GenericASTPass; + +protected: + RecursionDecision on_entry(Tree tree) override; +}; + +} diff --git a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp index 771c0cf26d..6af22d9a18 100644 --- a/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/JSSpecCompiler/main.cpp @@ -9,12 +9,16 @@ #include #include +#include "Compiler/FunctionCallCanonicalizationPass.h" +#include "Function.h" #include "Parser/SpecParser.h" ErrorOr serenity_main(Main::Arguments) { using namespace JSSpecCompiler; + ExecutionContext context; + auto input = TRY(TRY(Core::File::standard_input())->read_until_eof()); XML::Parser parser { StringView(input.bytes()) }; @@ -30,8 +34,12 @@ ErrorOr serenity_main(Main::Arguments) outln("{}", maybe_function.error()->to_string()); return 1; } - auto function = maybe_function.value(); + auto spec_function = maybe_function.value(); - out("{}", function.m_algorithm.m_tree); + auto function = make_ref_counted(&context, spec_function.m_name, spec_function.m_algorithm.m_tree); + + FunctionCallCanonicalizationPass(function).run(); + + out("{}", function->m_ast); return 0; }