/*
 * Copyright 2018 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.
 */

#ifndef wasm_ir_iteration_h
#define wasm_ir_iteration_h

#include "ir/properties.h"
#include "wasm.h"

namespace wasm {

//
// Allows iteration over the children of the expression, in order of execution
// where relevant.
//
//  * This skips missing children, e.g. if an if has no else, it is represented
//    as having 2 children (and not 3 with the last a nullptr).
//
// In general, it is preferable not to use this class and to directly access the
// children (using e.g. iff->ifTrue etc.), as that is faster. However, in cases
// where speed does not matter, this can be convenient. TODO: reimplement these
// to avoid materializing all the children at once.
//
//   ChildIterator - Iterates over all children
//
//   ValueChildIterator - Iterates over all children that produce values used by
//                        this instruction. For example, includes If::condition
//                        but not If::ifTrue.
//
template<class Specific> class AbstractChildIterator {
  using Self = AbstractChildIterator<Specific>;

  struct Iterator {
    using difference_type = std::ptrdiff_t;
    using value_type = Expression*;
    using pointer = Expression**;
    using reference = Expression*&;
    using iterator_category = std::forward_iterator_tag;

    const Self* parent;
    Index index;

    Iterator(const Self* parent, Index index) : parent(parent), index(index) {}

    bool operator!=(const Iterator& other) const {
      return index != other.index || parent != other.parent;
    }

    bool operator==(const Iterator& other) const { return !(*this != other); }

    void operator++() { index++; }

    Expression*& operator*() {
      return *parent->children[parent->mapIndex(index)];
    }
  };

  friend struct Iterator;

  Index mapIndex(Index index) const {
    assert(index < children.size());

    // The vector of children is in reverse order, as that is how
    // wasm-delegations-fields works. To get the order of execution, reverse
    // things.
    return children.size() - 1 - index;
  }

public:
  // The vector of children in the order emitted by wasm-delegations-fields
  // (which is in reverse execution order).
  // TODO: rename this "reverseChildren"?
  SmallVector<Expression**, 4> children;

  AbstractChildIterator(Expression* parent) {
    auto* self = (Specific*)this;

#define DELEGATE_ID parent->_id

#define DELEGATE_START(id) [[maybe_unused]] auto* cast = parent->cast<id>();

#define DELEGATE_GET_FIELD(id, field) cast->field

#define DELEGATE_FIELD_CHILD(id, field) self->addChild(parent, &cast->field);

#define DELEGATE_FIELD_OPTIONAL_CHILD(id, field)                               \
  if (cast->field) {                                                           \
    self->addChild(parent, &cast->field);                                      \
  }

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

#include "wasm-delegations-fields.def"
  }

  Iterator begin() const { return Iterator(this, 0); }
  Iterator end() const { return Iterator(this, children.size()); }

  void addChild(Expression* parent, Expression** child) {
    children.push_back(child);
  }

  // API for accessing children in random order.
  Expression*& getChild(Index index) { return *children[mapIndex(index)]; }

  Index getNumChildren() { return children.size(); }
};

class ChildIterator : public AbstractChildIterator<ChildIterator> {
public:
  ChildIterator(Expression* parent)
    : AbstractChildIterator<ChildIterator>(parent) {}
};

class ValueChildIterator : public AbstractChildIterator<ValueChildIterator> {
public:
  ValueChildIterator(Expression* parent)
    : AbstractChildIterator<ValueChildIterator>(parent) {}

  void addChild(Expression* parent, Expression** child) {
    if (Properties::isControlFlowStructure(parent)) {
      // If conditions are the only value children of control flow structures
      if (auto* iff = parent->dynCast<If>()) {
        if (child == &iff->condition) {
          children.push_back(child);
        }
      }
    } else {
      // All children on non-control flow expressions are value children
      children.push_back(child);
    }
  }
};

// Returns true if the current expression contains a certain kind of expression,
// within the given depth of BFS. If depth is -1, this searches all children.
template<typename T> bool containsChild(Expression* parent, int depth = -1) {
  std::vector<Expression*> exprs;
  std::vector<Expression*> nextExprs;
  exprs.push_back(parent);
  while (!exprs.empty() && depth > 0) {
    for (auto* expr : exprs) {
      for (auto* child : ChildIterator(expr)) {
        if (child->is<T>()) {
          return true;
        }
        nextExprs.push_back(child);
      }
    }
    exprs.swap(nextExprs);
    nextExprs.clear();
    if (depth > 0) {
      depth--;
    }
  }
  return false;
}

} // namespace wasm

#endif // wasm_ir_iteration_h
