Skip to content
Snippets Groups Projects
Select Git revision
  • d0e1cee1d4e62b656772c77fc42e0cd7afad8f66
  • master default protected
  • github/fork/hrani/master
  • github/fork/dilawar/master
  • chamcham
  • chhennapoda
  • wheel
  • 3.2.0-pre0
  • v3.1.3
  • 3.1.2
  • 3.1.1
  • chamcham-3.1.1
  • 3.1.0
  • ghevar_3.0.2_pre2
  • ghevar_3.0.2
15 results

simple_test.hpp

Blame
  • visitor.hpp 7.83 KiB
    #pragma once
    
    #include "error.hpp"
    #include "expression.hpp"
    
    /// visitor base class
    /// The visitors for all AST nodes throw an exception
    /// by default, with node types calling the default visitor for a parent
    /// For example, all BinaryExpression types call the visitor defined for
    /// BinaryExpression, so by overriding just the base implementation, all of the
    /// children get that implementation for free, which might be useful for some
    /// use cases.
    ///
    /// heavily inspired by the DMD D compiler : github.com/D-Programming-Language/dmd
    class Visitor {
    public:
        virtual void visit(Expression *e) = 0;
        virtual void visit(Symbol *e)               { visit((Expression*) e); }
        virtual void visit(LocalVariable *e)        { visit((Expression*) e); }
        virtual void visit(IdentifierExpression *e) { visit((Expression*) e); }
        virtual void visit(NumberExpression *e)     { visit((Expression*) e); }
        virtual void visit(IntegerExpression *e)    { visit((NumberExpression*) e); }
        virtual void visit(LocalDeclaration *e)     { visit((Expression*) e); }
        virtual void visit(ArgumentExpression *e)   { visit((Expression*) e); }
        virtual void visit(PrototypeExpression *e)  { visit((Expression*) e); }
        virtual void visit(CallExpression *e)       { visit((Expression*) e); }
        virtual void visit(ReactionExpression *e)   { visit((Expression*) e); }
        virtual void visit(StoichTermExpression *e) { visit((Expression*) e); }
        virtual void visit(StoichExpression *e)     { visit((Expression*) e); }
        virtual void visit(CompartmentExpression *e) { visit((Expression*) e); }
        virtual void visit(VariableExpression *e)   { visit((Expression*) e); }
        virtual void visit(IndexedVariable *e)      { visit((Expression*) e); }
        virtual void visit(FunctionExpression *e)   { visit((Expression*) e); }
        virtual void visit(IfExpression *e)         { visit((Expression*) e); }
        virtual void visit(SolveExpression *e)      { visit((Expression*) e); }
        virtual void visit(DerivativeExpression *e) { visit((Expression*) e); }
        virtual void visit(PDiffExpression *e)      { visit((Expression*) e); }
        virtual void visit(ProcedureExpression *e)  { visit((Expression*) e); }
        virtual void visit(NetReceiveExpression *e) { visit((ProcedureExpression*) e); }
        virtual void visit(APIMethod *e)            { visit((Expression*) e); }
        virtual void visit(ConductanceExpression *e) { visit((Expression*) e); }
        virtual void visit(BlockExpression *e)      { visit((Expression*) e); }
        virtual void visit(InitialBlock *e)         { visit((BlockExpression*) e); }
    
        virtual void visit(UnaryExpression *e) = 0;
        virtual void visit(NegUnaryExpression *e)   { visit((UnaryExpression*) e); }
        virtual void visit(ExpUnaryExpression *e)   { visit((UnaryExpression*) e); }
        virtual void visit(LogUnaryExpression *e)   { visit((UnaryExpression*) e); }
        virtual void visit(CosUnaryExpression *e)   { visit((UnaryExpression*) e); }
        virtual void visit(SinUnaryExpression *e)   { visit((UnaryExpression*) e); }
    
        virtual void visit(BinaryExpression *e) = 0;
        virtual void visit(ConditionalExpression *e) {visit((BinaryExpression*) e); }
        virtual void visit(AssignmentExpression *e) { visit((BinaryExpression*) e); }
        virtual void visit(ConserveExpression *e)   { visit((BinaryExpression*) e); }
        virtual void visit(LinearExpression *e)     { visit((BinaryExpression*) e); }
        virtual void visit(AddBinaryExpression *e)  { visit((BinaryExpression*) e); }
        virtual void visit(SubBinaryExpression *e)  { visit((BinaryExpression*) e); }
        virtual void visit(MulBinaryExpression *e)  { visit((BinaryExpression*) e); }
        virtual void visit(DivBinaryExpression *e)  { visit((BinaryExpression*) e); }
        virtual void visit(PowBinaryExpression *e)  { visit((BinaryExpression*) e); }
    
        virtual ~Visitor() {};
    };
    
    // Visitor specialization intended for use as a base class for visitors that
    // operate as function or procedure body rewriters after semantic analysis.
    //
    // Block rewriter visitors construct a new block body from a supplied
    // `BlockExpression`, `ProcedureExpression` or `FunctionExpression`. By default,
    // expressions are simply copied to the list of statements corresponding to the
    // rewritten block; nested blocks as provided by `IfExpression` objects are
    // handled recursively.
    //
    // The `finalize()` method is called after visiting all the statements in the
    // top-level block, and is intended to be overrided by derived classes as required.
    //
    // The `as_block()` method is intended to be called by users of the derived block
    // rewriter objects. It constructs a new `BlockExpression` from the accumulated
    // replacement statements and applies a semantic pass if the `BlockRewriterBase`
    // was given a corresponding scope
    //
    // The visitor maintains significant internal state: the `reset` method should
    // be called between visits of top-level blocks.
    //
    // Errors are recorded through the `error_stack` mixin rather than by
    // throwing an exception.
    
    class BlockRewriterBase : public Visitor, public error_stack {
    public:
        BlockRewriterBase() {}
        BlockRewriterBase(scope_ptr block_scope):
            block_scope_(block_scope) {}
    
        virtual void visit(Expression *e) override {
            statements_.push_back(e->clone());
        }
    
        virtual void visit(UnaryExpression *e) override { visit((Expression*)e); }
        virtual void visit(BinaryExpression *e) override { visit((Expression*)e); }
    
        virtual void visit(BlockExpression *e) override {
            bool top = !started_;
            if (top) {
                loc_ = e->location();
                started_ = true;
    
                if (!block_scope_) {
                    block_scope_ = e->scope();
                }
            }
    
            for (auto& s: e->statements()) {
                s->accept(this);
            }
    
            if (top) {
                finalize();
            }
        }
    
        virtual void visit(IfExpression* e) override {
            expr_list_type outer;
            std::swap(outer, statements_);
    
            e->true_branch()->accept(this);
            auto true_branch = make_expression<BlockExpression>(
                e->true_branch()->location(),
                std::move(statements_),
                true);
    
            statements_.clear();
            expression_ptr false_branch;
            if (e->false_branch()) {
                e->false_branch()->accept(this);
                false_branch = make_expression<BlockExpression>(
                        e->false_branch()->location(),
                        std::move(statements_),
                        true);
            }
    
            statements_ = std::move(outer);
            statements_.push_back(make_expression<IfExpression>(
                e->location(),
                e->condition()->clone(),
                std::move(true_branch),
                std::move(false_branch)));
        }
    
        virtual void visit(ProcedureExpression* e) override {
            e->body()->accept(this);
        }
    
        virtual void visit(FunctionExpression* e) override {
            e->body()->accept(this);
        }
    
        virtual expression_ptr as_block(bool is_nested=false) {
            if (has_error()) return nullptr;
    
            expr_list_type body_stmts;
            for (const auto& s: statements_) body_stmts.push_back(s->clone());
    
            auto body = make_expression<BlockExpression>(
                loc_,
                std::move(body_stmts),
                is_nested);
    
            if (block_scope_) {
                body->semantic(block_scope_);
            }
            return body;
        }
    
        // Reset state.
        virtual void reset() {
            statements_.clear();
            started_ = false;
            loc_ = Location{};
            clear_errors();
            clear_warnings();
        }
    
    protected:
        // False until processing of top block starts.
        bool started_ = false;
    
        // Location of original block.
        Location loc_;
    
        // Scope for semantic pass.
        scope_ptr block_scope_;
    
        // Statements in replacement procedure body.
        expr_list_type statements_;
    
        // Finalise statements list at end of top block visit.
        virtual void finalize() {}
    };