/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Author: pgess <v.melnychenko@xreate.org>
 */

/**
 * \file    abstractpass.h
 * \brief   Infrastructure to iterate over AST to facilitate analysis and compilation.
 */

#include "abstractpass.h"
#include "attachments.h"
#include "xreatemanager.h"

using namespace std;

namespace xreate {

template<>
void defaultValue<void>(){}

void IPass::finish(){}

IPass::IPass(PassManager *manager)
        : man(manager) {
}

template<>
void
AbstractPass<void>::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol)
{
    if (__visitedSymbols.isCached(symbol))
        return;

    __visitedSymbols.setCachedValue(symbol);
    const Expression& declaration = CodeScope::getDefinition(symbol, true);

    if (declaration.isDefined()){
        PassContext context2 = context.updateScope(symbol.scope);
        process(declaration, context2, hintSymbol);
    }
}

template<>
void
AbstractPass<void>::process(const Expression& expression, PassContext context, const std::string& varDecl){
    if (expression.__state == Expression::COMPOUND){
        for (const Expression &op: expression.getOperands()) {
            process(op, context);
        }

        for (CodeScope* scope: expression.blocks) {
            process(scope, context);
        }

        if (expression.op == Operator::CALL){
            processExpressionCall(expression, context);
        }

        return;
    }

    if (expression.__state == Expression::IDENT){
        assert(context.scope);
        processSymbol(Attachments::get<IdentifierSymbol>(expression), context, expression.getValueString());
    }
}
}

/**
 *  \class xreate::IPass
 *
 *  An each pass has to have IPass interface to be controllable by \ref XreateManager.
 *  However in most cases users should inherit minimal useful implementation  \ref xreate::AbstractPass
 *
 * \note It's usually expected that a custom pass publishes processing results by one of the following means:
 *  - xreate::Attachments for communicating with other passes
 *  - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
 *
 * \sa xreate::XreateManager, xreate::AbstractPass
 */

/**
 *  \class xreate::AbstractPass
 *
 * The class traverses the %AST in a minimally useful manner sparing clients from processing an every possible node manually. 
 * This way clients able to focus only on relevant nodes processing.
 *
 * The `Output` template parameter specifies the type of node processing result data.
 *
 * \note Automatically caches already visited nodes
 *
 * \note It's usually expected that a custom pass publishes processing results by one of the following means:
 *  - \ref xreate::Attachments for communicating with other passes
 *  - IAnalysisReport to prepare date for the \ref xreate::TranscendLayer solver
 *
 * \sa xreate::XreateManager, xreate::IPass, xreate::AST
 */