/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * 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 "ir/load-utils.h"
#include "ir/utils.h"

namespace wasm::ExpressionManipulator {

Expression*
flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
  // Perform the copy using a stack of tasks (avoiding recursion).
  struct CopyTask {
    // The thing to copy.
    Expression* original;
    // The location of the pointer to write the copy to.
    Expression** destPointer;
  };
  std::vector<CopyTask> tasks;
  Expression* ret;
  tasks.push_back({original, &ret});
  while (!tasks.empty()) {
    auto task = tasks.back();
    tasks.pop_back();
    // If the custom copier handled this one, we have nothing to do.
    auto* copy = custom(task.original);
    if (copy) {
      *task.destPointer = copy;
      continue;
    }
    // If the original is a null, just copy that. (This can happen for an
    // optional child.)
    auto* original = task.original;
    if (original == nullptr) {
      *task.destPointer = nullptr;
      continue;
    }
    // Allocate a new copy, and copy the fields.

#define DELEGATE_ID original->_id

// Allocate a new expression of the right type, and create cast versions of it
// for later operations.
#define DELEGATE_START(id)                                                     \
  copy = wasm.allocator.alloc<id>();                                           \
  [[maybe_unused]] auto* castOriginal = original->cast<id>();                  \
  [[maybe_unused]] auto* castCopy = copy->cast<id>();

// Handle each type of field, copying it appropriately.
#define DELEGATE_FIELD_CHILD(id, field)                                        \
  tasks.push_back({castOriginal->field, &castCopy->field});

// Iterate in reverse order here so we visit children in normal order.
#define DELEGATE_FIELD_CHILD_VECTOR(id, field)                                 \
  castCopy->field.resize(castOriginal->field.size());                          \
  for (auto i = int64_t(castOriginal->field.size()) - 1; i >= 0; i--) {        \
    tasks.push_back({castOriginal->field[i], &castCopy->field[i]});            \
  }

#define COPY_FIELD(field) castCopy->field = castOriginal->field;

#define DELEGATE_FIELD_INT(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_LITERAL(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_NAME(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_SCOPE_NAME_DEF(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_TYPE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_HEAPTYPE(id, field) COPY_FIELD(field)
#define DELEGATE_FIELD_ADDRESS(id, field) COPY_FIELD(field)

#define COPY_FIELD_LIST(field)                                                 \
  for (Index i = 0; i < castOriginal->field.size(); i++) {                     \
    castCopy->field[i] = castOriginal->field[i];                               \
  }

#define COPY_VECTOR(field)                                                     \
  castCopy->field.resize(castOriginal->field.size());                          \
  COPY_FIELD_LIST(field)

#define COPY_ARRAY(field)                                                      \
  assert(castCopy->field.size() == castOriginal->field.size());                \
  COPY_FIELD_LIST(field)

#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) COPY_VECTOR(field)
#define DELEGATE_FIELD_NAME_VECTOR(id, field) COPY_VECTOR(field)
#define DELEGATE_FIELD_TYPE_VECTOR(id, field) COPY_VECTOR(field)

#define DELEGATE_FIELD_INT_ARRAY(id, field) COPY_ARRAY(field)
#define DELEGATE_FIELD_INT_VECTOR(id, field) COPY_VECTOR(field)

#include "wasm-delegations-fields.def"

    // The type can be simply copied.
    copy->type = original->type;

    // Write the copy to where it should be referred to.
    *task.destPointer = copy;
  }
  return ret;
}

// Splice an item into the middle of a block's list
void spliceIntoBlock(Block* block, Index index, Expression* add) {
  block->list.insertAt(index, add);
  block->finalize(block->type);
}

} // namespace wasm::ExpressionManipulator
