// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "src/tint/transform/promote_side_effects_to_decl.h"

#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/for_loop_statement.h"
#include "src/tint/sem/if_statement.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/variable.h"
#include "src/tint/transform/manager.h"
#include "src/tint/transform/utils/get_insertion_point.h"
#include "src/tint/transform/utils/hoist_to_decl_before.h"
#include "src/tint/utils/scoped_assignment.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::PromoteSideEffectsToDecl);

namespace tint::transform {
namespace {

// Base state class for common members
class StateBase {
 protected:
  CloneContext& ctx;
  ProgramBuilder& b;
  const sem::Info& sem;

  explicit StateBase(CloneContext& ctx_in)
      : ctx(ctx_in), b(*ctx_in.dst), sem(ctx_in.src->Sem()) {}
};

// This first transform converts side-effecting for-loops to loops and else-ifs
// to else {if}s so that the next transform, DecomposeSideEffects, can insert
// hoisted expressions above their current location.
struct SimplifySideEffectStatements
    : Castable<PromoteSideEffectsToDecl, Transform> {
  class State;
  void Run(CloneContext& ctx, const DataMap& inputs, DataMap&) const override;
};

class SimplifySideEffectStatements::State : public StateBase {
  HoistToDeclBefore hoist_to_decl_before;

 public:
  explicit State(CloneContext& ctx_in)
      : StateBase(ctx_in), hoist_to_decl_before(ctx_in) {}

  void Run() {
    for (auto* node : ctx.src->ASTNodes().Objects()) {
      if (auto* expr = node->As<ast::Expression>()) {
        auto* sem_expr = sem.Get(expr);
        if (!sem_expr || !sem_expr->HasSideEffects()) {
          continue;
        }

        hoist_to_decl_before.Prepare(sem_expr);
      }
    }

    hoist_to_decl_before.Apply();
    ctx.Clone();
  }
};

void SimplifySideEffectStatements::Run(CloneContext& ctx,
                                       const DataMap&,
                                       DataMap&) const {
  State state(ctx);
  state.Run();
}

// Decomposes side-effecting expressions to ensure order of evaluation. This
// handles both breaking down logical binary expressions for short-circuit
// evaluation, as well as hoisting expressions to ensure order of evaluation.
struct DecomposeSideEffects : Castable<PromoteSideEffectsToDecl, Transform> {
  class CollectHoistsState;
  class DecomposeState;
  void Run(CloneContext& ctx, const DataMap& inputs, DataMap&) const override;
};

// CollectHoistsState traverses the AST top-down, identifying which expressions
// need to be hoisted to ensure order of evaluation, both those that give
// side-effects, as well as those that receive, and returns a set of these
// expressions.
using ToHoistSet = std::unordered_set<const ast::Expression*>;
class DecomposeSideEffects::CollectHoistsState : public StateBase {
  // Expressions to hoist because they either cause or receive side-effects.
  ToHoistSet to_hoist;

  // Used to mark expressions as not or no longer having side-effects.
  std::unordered_set<const ast::Expression*> no_side_effects;

  // Returns true if `expr` has side-effects. Unlike invoking
  // sem::Expression::HasSideEffects(), this function takes into account whether
  // `expr` has been hoisted, returning false in that case. Furthermore, it
  // returns the correct result on parent expression nodes by traversing the
  // expression tree, memoizing the results to ensure O(1) amortized lookup.
  bool HasSideEffects(const ast::Expression* expr) {
    if (no_side_effects.count(expr)) {
      return false;
    }

    return Switch(
        expr,
        [&](const ast::CallExpression* e) -> bool {
          return sem.Get(e)->HasSideEffects();
        },
        [&](const ast::BinaryExpression* e) {
          if (HasSideEffects(e->lhs) || HasSideEffects(e->rhs)) {
            return true;
          }
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::IndexAccessorExpression* e) {
          if (HasSideEffects(e->object) || HasSideEffects(e->index)) {
            return true;
          }
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::MemberAccessorExpression* e) {
          if (HasSideEffects(e->structure) || HasSideEffects(e->member)) {
            return true;
          }
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::BitcastExpression* e) {  //
          if (HasSideEffects(e->expr)) {
            return true;
          }
          no_side_effects.insert(e);
          return false;
        },

        [&](const ast::UnaryOpExpression* e) {  //
          if (HasSideEffects(e->expr)) {
            return true;
          }
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::IdentifierExpression* e) {
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::LiteralExpression* e) {
          no_side_effects.insert(e);
          return false;
        },
        [&](const ast::PhonyExpression* e) {
          no_side_effects.insert(e);
          return false;
        },
        [&](Default) {
          TINT_ICE(Transform, b.Diagnostics()) << "Unhandled expression type";
          return false;
        });
  }

  // Adds `e` to `to_hoist` for hoisting to a let later on.
  void Hoist(const ast::Expression* e) {
    no_side_effects.insert(e);
    to_hoist.emplace(e);
  }

  // Hoists any expressions in `maybe_hoist` and clears it
  void Flush(ast::ExpressionList& maybe_hoist) {
    for (auto* m : maybe_hoist) {
      Hoist(m);
    }
    maybe_hoist.clear();
  }

  // Recursive function that processes expressions for side-effects. It
  // traverses the expression tree child before parent, left-to-right. Each call
  // returns whether the input expression should maybe be hoisted, allowing the
  // parent node to decide whether to hoist or not. Generally:
  // * When 'true' is returned, the expression is added to the maybe_hoist list.
  // * When a side-effecting expression is met, we flush the expressions in the
  // maybe_hoist list, as they are potentially receivers of the side-effects.
  // * For index and member accessor expressions, special care is taken to not
  // over-hoist the lhs expressions, as these may be be chained to refer to a
  // single memory location.
  bool ProcessExpression(const ast::Expression* expr,
                         ast::ExpressionList& maybe_hoist) {
    auto process = [&](const ast::Expression* e) -> bool {
      return ProcessExpression(e, maybe_hoist);
    };

    auto default_process = [&](const ast::Expression* e) {
      auto maybe = process(e);
      if (maybe) {
        maybe_hoist.emplace_back(e);
      }
      if (HasSideEffects(e)) {
        Flush(maybe_hoist);
      }
      return false;
    };

    auto binary_process = [&](auto* lhs, auto* rhs) {
      // If neither side causes side-effects, but at least one receives them,
      // let parent node hoist. This avoids over-hoisting side-effect receivers
      // of compound binary expressions (e.g. for "((a && b) && c) && f()", we
      // don't want to hoist each of "a", "b", and "c" separately, but want to
      // hoist "((a && b) && c)".
      if (!HasSideEffects(lhs) && !HasSideEffects(rhs)) {
        auto lhs_maybe = process(lhs);
        auto rhs_maybe = process(rhs);
        if (lhs_maybe || rhs_maybe) {
          return true;
        }
        return false;
      }

      default_process(lhs);
      default_process(rhs);
      return false;
    };

    auto accessor_process = [&](auto* lhs, auto* rhs) {
      auto maybe = process(lhs);
      // If lhs is a variable, let parent node hoist otherwise flush it right
      // away. This is to avoid over-hoisting the lhs of accessor chains (e.g.
      // for "v[a][b][c] + g()" we want to hoist all of "v[a][b][c]", not "t1 =
      // v[a]", then "t2 = t1[b]" then "t3 = t2[c]").
      if (maybe && HasSideEffects(lhs)) {
        maybe_hoist.emplace_back(lhs);
        Flush(maybe_hoist);
        maybe = false;
      }
      default_process(rhs);
      return maybe;
    };

    return Switch(
        expr,
        [&](const ast::CallExpression* e) -> bool {
          // We eagerly flush any variables in maybe_hoist for the current
          // call expression. Then we scope maybe_hoist to the processing of
          // the call args. This ensures that given: g(c, a(0), d) we hoist
          // 'c' because of 'a(0)', but not 'd' because there's no need, since
          // the call to g() will be hoisted if necessary.
          if (HasSideEffects(e)) {
            Flush(maybe_hoist);
          }

          TINT_SCOPED_ASSIGNMENT(maybe_hoist, {});
          for (auto* a : e->args) {
            default_process(a);
          }

          // Always hoist this call, even if it has no side-effects to ensure
          // left-to-right order of evaluation.
          // E.g. for "no_side_effects() + side_effects()", we want to hoist
          // no_side_effects() first.
          return true;
        },
        [&](const ast::IdentifierExpression* e) {
          if (auto* sem_e = sem.Get(e)) {
            if (auto* var_user = sem_e->As<sem::VariableUser>()) {
              // Don't hoist constants.
              if (var_user->ConstantValue().IsValid()) {
                return false;
              }
              // Don't hoist read-only variables as they cannot receive
              // side-effects.
              if (var_user->Variable()->Access() == ast::Access::kRead) {
                return false;
              }
              return true;
            }
          }
          return false;
        },
        [&](const ast::BinaryExpression* e) {
          if (e->IsLogical() && HasSideEffects(e)) {
            // Don't hoist children of logical binary expressions with
            // side-effects. These will be handled by DecomposeState.
            process(e->lhs);
            process(e->rhs);
            return false;
          }
          return binary_process(e->lhs, e->rhs);
        },
        [&](const ast::BitcastExpression* e) {  //
          return process(e->expr);
        },
        [&](const ast::UnaryOpExpression* e) {  //
          auto r = process(e->expr);
          // Don't hoist address-of expressions.
          // E.g. for "g(&b, a(0))", we hoist "a(0)" only.
          if (e->op == ast::UnaryOp::kAddressOf) {
            return false;
          }
          return r;
        },
        [&](const ast::IndexAccessorExpression* e) {
          return accessor_process(e->object, e->index);
        },
        [&](const ast::MemberAccessorExpression* e) {
          return accessor_process(e->structure, e->member);
        },
        [&](const ast::LiteralExpression*) {
          // Leaf
          return false;
        },
        [&](const ast::PhonyExpression*) {
          // Leaf
          return false;
        },
        [&](Default) {
          TINT_ICE(Transform, b.Diagnostics()) << "Unhandled expression type";
          return false;
        });
  }

  // Starts the recursive processing of a statement's expression(s) to hoist
  // side-effects to lets.
  void ProcessStatement(const ast::Expression* expr) {
    if (!expr) {
      return;
    }

    ast::ExpressionList maybe_hoist;
    ProcessExpression(expr, maybe_hoist);
  }

  // Special case for processing assignment statement expressions, as we must
  // evaluate the rhs before the lhs, and possibly hoist the rhs expression.
  void ProcessAssignment(const ast::Expression* lhs,
                         const ast::Expression* rhs) {
    // Evaluate rhs before lhs
    ast::ExpressionList maybe_hoist;
    if (ProcessExpression(rhs, maybe_hoist)) {
      maybe_hoist.emplace_back(rhs);
    }

    // If the rhs has side-effects, it may affect the lhs, so hoist it right
    // away. e.g. "b[c] = a(0);"
    if (HasSideEffects(rhs)) {
      // Technically, we can always hoist rhs, but don't bother doing so when
      // the lhs is just a variable or phony.
      if (!lhs->IsAnyOf<ast::IdentifierExpression, ast::PhonyExpression>()) {
        Flush(maybe_hoist);
      }
    }

    // If maybe_hoist still has values, it means they are potential side-effect
    // receivers. We pass this in while processing the lhs, in which case they
    // may get hoisted if the lhs has side-effects. E.g. "b[a(0)] = c;".
    ProcessExpression(lhs, maybe_hoist);
  }

 public:
  explicit CollectHoistsState(CloneContext& ctx_in) : StateBase(ctx_in) {}

  ToHoistSet Run() {
    // Traverse all statements, recursively processing their expression tree(s)
    // to hoist side-effects to lets.
    for (auto* node : ctx.src->ASTNodes().Objects()) {
      auto* stmt = node->As<ast::Statement>();
      if (!stmt) {
        continue;
      }

      Switch(
          stmt,
          [&](const ast::AssignmentStatement* s) {
            ProcessAssignment(s->lhs, s->rhs);
          },
          [&](const ast::CallStatement* s) {  //
            ProcessStatement(s->expr);
          },
          [&](const ast::ElseStatement* s) {  //
            ProcessStatement(s->condition);
          },
          [&](const ast::ForLoopStatement* s) {
            ProcessStatement(s->condition);
          },
          [&](const ast::IfStatement* s) {  //
            ProcessStatement(s->condition);
          },
          [&](const ast::ReturnStatement* s) {  //
            ProcessStatement(s->value);
          },
          [&](const ast::SwitchStatement* s) {
            ProcessStatement(s->condition);
          },
          [&](const ast::VariableDeclStatement* s) {
            ProcessStatement(s->variable->constructor);
          });
    }

    return std::move(to_hoist);
  }
};

// DecomposeState performs the actual transforming of the AST to ensure order of
// evaluation, using the set of expressions to hoist collected by
// CollectHoistsState.
class DecomposeSideEffects::DecomposeState : public StateBase {
  ToHoistSet to_hoist;

  // Returns true if `binary_expr` should be decomposed for short-circuit eval.
  bool IsLogicalWithSideEffects(const ast::BinaryExpression* binary_expr) {
    return binary_expr->IsLogical() &&
           (sem.Get(binary_expr->lhs)->HasSideEffects() ||
            sem.Get(binary_expr->rhs)->HasSideEffects());
  }

  // Recursive function used to decompose an expression for short-circuit eval.
  const ast::Expression* Decompose(const ast::Expression* expr,
                                   ast::StatementList* curr_stmts) {
    // Helper to avoid passing in same args.
    auto decompose = [&](auto& e) { return Decompose(e, curr_stmts); };

    // Clones `expr`, possibly hoisting it to a let.
    auto clone_maybe_hoisted =
        [&](const ast::Expression* e) -> const ast::Expression* {
      if (to_hoist.count(e)) {
        auto name = b.Symbols().New();
        auto* v = b.Let(name, nullptr, ctx.Clone(e));
        auto* decl = b.Decl(v);
        curr_stmts->push_back(decl);
        return b.Expr(name);
      }
      return ctx.Clone(e);
    };

    return Switch(
        expr,
        [&](const ast::BinaryExpression* bin_expr) -> const ast::Expression* {
          if (!IsLogicalWithSideEffects(bin_expr)) {
            // No short-circuit, emit usual binary expr
            ctx.Replace(bin_expr->lhs, decompose(bin_expr->lhs));
            ctx.Replace(bin_expr->rhs, decompose(bin_expr->rhs));
            return clone_maybe_hoisted(bin_expr);
          }

          // Decompose into ifs to implement short-circuiting
          // For example, 'let r = a && b' becomes:
          //
          // var temp = a;
          // if (temp) {
          //   temp = b;
          // }
          // let r = temp;
          //
          // and similarly, 'let r = a || b' becomes:
          //
          // var temp = a;
          // if (!temp) {
          //     temp = b;
          // }
          // let r = temp;
          //
          // Further, compound logical binary expressions are also handled
          // recursively, for example, 'let r = (a && (b && c))' becomes:
          //
          // var temp = a;
          // if (temp) {
          //     var temp2 = b;
          //     if (temp2) {
          //         temp2 = c;
          //     }
          //     temp = temp2;
          // }
          // let r = temp;

          auto name = b.Sym();
          curr_stmts->push_back(
              b.Decl(b.Var(name, nullptr, decompose(bin_expr->lhs))));

          const ast::Expression* if_cond = nullptr;
          if (bin_expr->IsLogicalOr()) {
            if_cond = b.Not(name);
          } else {
            if_cond = b.Expr(name);
          }

          const ast::BlockStatement* if_body = nullptr;
          {
            ast::StatementList stmts;
            TINT_SCOPED_ASSIGNMENT(curr_stmts, &stmts);
            auto* new_rhs = decompose(bin_expr->rhs);
            curr_stmts->push_back(b.Assign(name, new_rhs));
            if_body = b.Block(std::move(*curr_stmts));
          }

          curr_stmts->push_back(b.If(if_cond, if_body));

          return b.Expr(name);
        },
        [&](const ast::IndexAccessorExpression* idx) {
          ctx.Replace(idx->object, decompose(idx->object));
          ctx.Replace(idx->index, decompose(idx->index));
          return clone_maybe_hoisted(idx);
        },
        [&](const ast::BitcastExpression* bitcast) {
          ctx.Replace(bitcast->expr, decompose(bitcast->expr));
          return clone_maybe_hoisted(bitcast);
        },
        [&](const ast::CallExpression* call) {
          if (call->target.name) {
            ctx.Replace(call->target.name, decompose(call->target.name));
          }
          for (auto* a : call->args) {
            ctx.Replace(a, decompose(a));
          }
          return clone_maybe_hoisted(call);
        },
        [&](const ast::MemberAccessorExpression* member) {
          ctx.Replace(member->structure, decompose(member->structure));
          ctx.Replace(member->member, decompose(member->member));
          return clone_maybe_hoisted(member);
        },
        [&](const ast::UnaryOpExpression* unary) {
          ctx.Replace(unary->expr, decompose(unary->expr));
          return clone_maybe_hoisted(unary);
        },
        [&](const ast::LiteralExpression* lit) {
          return clone_maybe_hoisted(lit);  // Leaf expression, just clone as is
        },
        [&](const ast::IdentifierExpression* id) {
          return clone_maybe_hoisted(id);  // Leaf expression, just clone as is
        },
        [&](const ast::PhonyExpression* phony) {
          return clone_maybe_hoisted(
              phony);  // Leaf expression, just clone as is
        },
        [&](Default) {
          TINT_ICE(AST, b.Diagnostics())
              << "unhandled expression type: " << expr->TypeInfo().name;
          return nullptr;
        });
  }

  // Inserts statements in `stmts` before `stmt`
  void InsertBefore(const ast::StatementList& stmts,
                    const ast::Statement* stmt) {
    if (!stmts.empty()) {
      auto ip = utils::GetInsertionPoint(ctx, stmt);
      for (auto* s : stmts) {
        ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, s);
      }
    }
  }

  // Decomposes expressions of `stmt`, returning a replacement statement or
  // nullptr if not replacing it.
  const ast::Statement* DecomposeStatement(const ast::Statement* stmt) {
    return Switch(
        stmt,
        [&](const ast::AssignmentStatement* s) -> const ast::Statement* {
          if (!sem.Get(s->lhs)->HasSideEffects() &&
              !sem.Get(s->rhs)->HasSideEffects()) {
            return nullptr;
          }
          // rhs before lhs
          ast::StatementList stmts;
          ctx.Replace(s->rhs, Decompose(s->rhs, &stmts));
          ctx.Replace(s->lhs, Decompose(s->lhs, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::CallStatement* s) -> const ast::Statement* {
          if (!sem.Get(s->expr)->HasSideEffects()) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(s->expr, Decompose(s->expr, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::ElseStatement* s) -> const ast::Statement* {
          if (!s->condition || !sem.Get(s->condition)->HasSideEffects()) {
            return nullptr;
          }
          // NOTE: We shouldn't reach here as else-if with side-effect
          // conditions are simplified to else { if } by
          // SimplifySideEffectStatements.
          ast::StatementList stmts;
          ctx.Replace(s->condition, Decompose(s->condition, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::ForLoopStatement* s) -> const ast::Statement* {
          if (!s->condition || !sem.Get(s->condition)->HasSideEffects()) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(s->condition, Decompose(s->condition, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::IfStatement* s) -> const ast::Statement* {
          if (!sem.Get(s->condition)->HasSideEffects()) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(s->condition, Decompose(s->condition, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::ReturnStatement* s) -> const ast::Statement* {
          if (!s->value || !sem.Get(s->value)->HasSideEffects()) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(s->value, Decompose(s->value, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::SwitchStatement* s) -> const ast::Statement* {
          if (!sem.Get(s->condition)) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(s->condition, Decompose(s->condition, &stmts));
          InsertBefore(stmts, s);
          return ctx.CloneWithoutTransform(s);
        },
        [&](const ast::VariableDeclStatement* s) -> const ast::Statement* {
          auto* var = s->variable;
          if (!var->constructor ||
              !sem.Get(var->constructor)->HasSideEffects()) {
            return nullptr;
          }
          ast::StatementList stmts;
          ctx.Replace(var->constructor, Decompose(var->constructor, &stmts));
          InsertBefore(stmts, s);
          return b.Decl(ctx.CloneWithoutTransform(var));
        },
        [](Default) -> const ast::Statement* {
          // Other statement types don't have expressions
          return nullptr;
        });
  }

 public:
  explicit DecomposeState(CloneContext& ctx_in, ToHoistSet to_hoist_in)
      : StateBase(ctx_in), to_hoist(std::move(to_hoist_in)) {}

  void Run() {
    // We replace all BlockStatements as this allows us to iterate over the
    // block statements and ctx.InsertBefore hoisted declarations on them.
    ctx.ReplaceAll(
        [&](const ast::BlockStatement* block) -> const ast::Statement* {
          for (auto* stmt : block->statements) {
            if (auto* new_stmt = DecomposeStatement(stmt)) {
              ctx.Replace(stmt, new_stmt);
            }

            // Handle for loops, as they are the only other AST node that
            // contains statements outside of BlockStatements.
            if (auto* fl = stmt->As<ast::ForLoopStatement>()) {
              if (auto* new_stmt = DecomposeStatement(fl->initializer)) {
                ctx.Replace(fl->initializer, new_stmt);
              }
              if (auto* new_stmt = DecomposeStatement(fl->continuing)) {
                ctx.Replace(fl->continuing, new_stmt);
              }
            }
          }
          return nullptr;
        });

    ctx.Clone();
  }
};

void DecomposeSideEffects::Run(CloneContext& ctx,
                               const DataMap&,
                               DataMap&) const {
  // First collect side-effecting expressions to hoist
  CollectHoistsState collect_hoists_state{ctx};
  auto to_hoist = collect_hoists_state.Run();

  // Now decompose these expressions
  DecomposeState decompose_state{ctx, std::move(to_hoist)};
  decompose_state.Run();
}

}  // namespace

PromoteSideEffectsToDecl::PromoteSideEffectsToDecl() = default;
PromoteSideEffectsToDecl::~PromoteSideEffectsToDecl() = default;

Output PromoteSideEffectsToDecl::Run(const Program* program,
                                     const DataMap& data) const {
  transform::Manager manager;
  manager.Add<SimplifySideEffectStatements>();
  manager.Add<DecomposeSideEffects>();

  auto output = manager.Run(program, data);
  return output;
}

}  // namespace tint::transform
