Skip to content

Commit

Permalink
feat: add local variable inliner.
Browse files Browse the repository at this point in the history
  • Loading branch information
ashigeru committed Aug 14, 2024
1 parent 48c8f6a commit 8b4f627
Show file tree
Hide file tree
Showing 6 changed files with 647 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ add_library(yugawara
yugawara/analyzer/details/collect_join_keys.cpp
yugawara/analyzer/details/rewrite_scan.cpp
yugawara/analyzer/details/classify_expression.cpp
yugawara/analyzer/details/inline_variables.cpp

# analyzer misc.
yugawara/analyzer/details/detect_join_endpoint_style.cpp
Expand Down
168 changes: 168 additions & 0 deletions src/yugawara/analyzer/details/inline_variables.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include "inline_variables.h"

#include <takatori/scalar/dispatch.h>

#include <takatori/util/clonable.h>

namespace yugawara::analyzer::details {

namespace {

class engine {
public:
explicit engine(inline_variables::map_type const& replacements) noexcept :
replacements_ { replacements }
{}

void process(::takatori::util::ownership_reference<::takatori::scalar::expression> target) {
if (auto expr = target.find()) {
auto replacement = dispatch(*expr);
if (replacement) {
target.set(std::move(replacement));
}
}
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> dispatch(::takatori::scalar::expression& expression) {
return ::takatori::scalar::dispatch(*this, expression);
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::expression& expression) {
(void) expression;
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::immediate& expression) {
(void) expression;
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::variable_reference& expression) {
auto found = replacements_.find(expression.variable().reference());
if (found == replacements_.end()) {
return {};
}
return ::takatori::util::clone_unique(found->second);
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::unary& expression) {
if (auto replacement = dispatch(expression.operand())) {
expression.operand(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::cast& expression) {
if (auto replacement = dispatch(expression.operand())) {
expression.operand(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::binary& expression) {
if (auto replacement = dispatch(expression.left())) {
expression.left(std::move(replacement));
}
if (auto replacement = dispatch(expression.right())) {
expression.right(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::compare& expression) {
if (auto replacement = dispatch(expression.left())) {
expression.left(std::move(replacement));
}
if (auto replacement = dispatch(expression.right())) {
expression.right(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::match& expression) {
if (auto replacement = dispatch(expression.input())) {
expression.input(std::move(replacement));
}
if (auto replacement = dispatch(expression.pattern())) {
expression.pattern(std::move(replacement));
}
if (auto replacement = dispatch(expression.escape())) {
expression.escape(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::conditional& expression) {
for (auto&& alternative : expression.alternatives()) {
if (auto replacement = dispatch(alternative.condition())) {
alternative.condition(std::move(replacement));
}
if (auto replacement = dispatch(alternative.body())) {
alternative.body(std::move(replacement));
}
}
if (auto otherwise = expression.default_expression()) {
if (auto replacement = dispatch(*otherwise)) {
expression.default_expression(std::move(replacement));
}
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::coalesce& expression) {
apply_list(expression.alternatives());
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::let& expression) {
for (auto&& decl : expression.variables()) {
if (auto replacement = dispatch(decl.value())) {
decl.value(std::move(replacement));
}
}
if (auto replacement = dispatch(expression.body())) {
expression.body(std::move(replacement));
}
return {};
}

[[nodiscard]] std::unique_ptr<::takatori::scalar::expression> operator()(::takatori::scalar::function_call& expression) {
apply_list(expression.arguments());
return {};
}

private:
inline_variables::map_type const& replacements_;

void apply_list(::takatori::tree::tree_element_vector<::takatori::scalar::expression>& list) {
for (auto iter = list.begin(); iter != list.end(); ++iter) {
if (auto replacement = dispatch(*iter)) {
(void) list.exchange(iter, std::move(replacement));
}
}
}
};

} // namespace

void inline_variables::reserve(std::size_t size) {
variables_.reserve(size);
replacements_.reserve(size);
}

void inline_variables::declare(
::takatori::descriptor::variable variable,
std::unique_ptr<::takatori::scalar::expression> replacement) {
auto key = variable.reference();
if (replacements_.find(key) == replacements_.end()) {
variables_.emplace_back(std::move(variable));
}
replacements_.emplace(key, std::move(replacement));
}

void inline_variables::apply(::takatori::util::ownership_reference<::takatori::scalar::expression> target) const {
engine e { replacements_ };
e.process(std::move(target));
}

} // namespace yugawara::analyzer::details
46 changes: 46 additions & 0 deletions src/yugawara/analyzer/details/inline_variables.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include <tsl/hopscotch_map.h>

#include <takatori/descriptor/variable.h>

#include <takatori/scalar/expression.h>

#include <takatori/util/ownership_reference.h>

namespace yugawara::analyzer::details {

class inline_variables {
public:
using map_type = ::tsl::hopscotch_map<
::takatori::descriptor::variable::reference_type,
std::unique_ptr<::takatori::scalar::expression>>;

/**
* @brief reserves the space for the variables to be inlined.
* @param size the number of variables to be inlined
*/
void reserve(std::size_t size);

/**
* @brief declares a variable to be inlined.
* @param variable the target variable
* @param replacement the replacement expression
* @return this
*/
void declare(
::takatori::descriptor::variable variable,
std::unique_ptr<::takatori::scalar::expression> replacement);

/**
* @brief applies the inlining of the variables to the target expression.
* @param target the target expression
*/
void apply(::takatori::util::ownership_reference<::takatori::scalar::expression> target) const;

private:
std::vector<::takatori::descriptor::variable> variables_ {};
map_type replacements_;
};

} // namespace yugawara::analyzer::details
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ add_test_executable(yugawara/analyzer/details/rewrite_join_test.cpp)
add_test_executable(yugawara/analyzer/details/collect_join_keys_test.cpp)
add_test_executable(yugawara/analyzer/details/rewrite_scan_test.cpp)
add_test_executable(yugawara/analyzer/details/classify_expression_test.cpp)
add_test_executable(yugawara/analyzer/details/inline_variables_test.cpp)
add_test_executable(yugawara/analyzer/intermediate_plan_optimizer_test.cpp)

# serializer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class classify_expression_test : public ::testing::Test {
};
}

type::repository types;
binding::factory bindings;
};

Expand Down
Loading

0 comments on commit 8b4f627

Please sign in to comment.