// Copyright 2017-2019 VMware, Inc.
// SPDX-License-Identifier: BSD-2-Clause
//
// The BSD-2 license (the License) set forth below applies to all parts of the
// Cascade project.  You may not use this file except in compliance with the
// License.
//
// BSD-2 License
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef CASCADE_SRC_VERILOG_AST_VISITORS_BUILDER_H
#define CASCADE_SRC_VERILOG_AST_VISITORS_BUILDER_H

#include "verilog/ast/ast_fwd.h"

namespace cascade {

// A non-intrusive visitor.  This class uses the following convention:
// returning nullptr for an AST node which appears in a combinator (a many or a
// maybe) will result in that node being removed from the AST.  Returning
// nullptr for a node which does not appear in a combinator is undefined.  The
// default implementation of this class performs a recursive descent over the
// AST and returns a clone of the nodes that it encounters. 

struct Builder {
  virtual ~Builder() = default;

  virtual ArgAssign* build(const ArgAssign* aa);
  virtual Attributes* build(const Attributes* a);
  virtual AttrSpec* build(const AttrSpec* as);
  virtual CaseGenerateItem* build(const CaseGenerateItem* cgi);
  virtual CaseItem* build(const CaseItem* ci);
  virtual Event* build(const Event* e);
  virtual Expression* build(const BinaryExpression* be);
  virtual Expression* build(const ConditionalExpression* ce);
  virtual Expression* build(const FeofExpression* fe);
  virtual Expression* build(const FopenExpression* fe);
  virtual Expression* build(const Concatenation* c);
  virtual Expression* build(const Identifier* i);
  virtual Expression* build(const MultipleConcatenation* mc);
  virtual Expression* build(const Number* n);
  virtual Expression* build(const String* s);
  virtual Expression* build(const RangeExpression* re);
  virtual Expression* build(const UnaryExpression* ue);
  virtual GenerateBlock* build(const GenerateBlock* gb);
  virtual Id* build(const Id* i);
  virtual IfGenerateClause* build(const IfGenerateClause* igc);
  virtual ModuleDeclaration* build(const ModuleDeclaration* md);
  virtual ModuleItem* build(const AlwaysConstruct* ac);
  virtual ModuleItem* build(const IfGenerateConstruct* igc);
  virtual ModuleItem* build(const CaseGenerateConstruct* cgc);
  virtual ModuleItem* build(const LoopGenerateConstruct* lgc);
  virtual ModuleItem* build(const InitialConstruct* ic);
  virtual ModuleItem* build(const ContinuousAssign* ca);
  virtual ModuleItem* build(const GenvarDeclaration* gd);
  virtual ModuleItem* build(const LocalparamDeclaration* ld);
  virtual ModuleItem* build(const NetDeclaration* nd);
  virtual ModuleItem* build(const ParameterDeclaration* pd);
  virtual ModuleItem* build(const RegDeclaration* rd);
  virtual ModuleItem* build(const GenerateRegion* gr);
  virtual ModuleItem* build(const ModuleInstantiation* mi);
  virtual ModuleItem* build(const PortDeclaration* pd);
  virtual Statement* build(const BlockingAssign* ba);
  virtual Statement* build(const NonblockingAssign* na);
  virtual Statement* build(const CaseStatement* cs);
  virtual Statement* build(const ConditionalStatement* cs);
  virtual Statement* build(const ForStatement* fs);
  virtual Statement* build(const RepeatStatement* rs);
  virtual Statement* build(const ParBlock* pb);
  virtual Statement* build(const SeqBlock* sb);
  virtual Statement* build(const TimingControlStatement* rcs);
  virtual Statement* build(const DebugStatement* ds);
  virtual Statement* build(const FflushStatement* fs);
  virtual Statement* build(const FinishStatement* fs);
  virtual Statement* build(const FseekStatement* fs);
  virtual Statement* build(const GetStatement* gs);
  virtual Statement* build(const PutStatement* ps);
  virtual Statement* build(const RestartStatement* rs);
  virtual Statement* build(const RetargetStatement* rs);
  virtual Statement* build(const SaveStatement* ss);
  virtual Statement* build(const WhileStatement* ws);
  virtual TimingControl* build(const EventControl* ec);
  virtual VariableAssign* build(const VariableAssign* va);
};

} // namespace cascade

#endif
