/*
 * 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/.
 *
 * File:   polymorph.cpp
 * Author: pgess <v.melnychenko@xreate.org>
 *
 * Created on November 9, 2017, 12:14 PM
 */

#include "polymorph.h"

using namespace std;
namespace xreate { namespace polymorph {

const std::string atomPolymorph = "dfa_callguard";

void
PolymorphQuery::init(TranscendLayer* transcend){
    __transcend = transcend;

    StaticModel queryResult = transcend->query(atomPolymorph);
    if (queryResult.size()){
        for (auto entry: queryResult){
            auto answer = TranscendLayer::parse<SymbolNode, Expression>(entry.second);
            SymbolNode symbCaller = std::get<0>(answer);
            SymbolGeneralized symbCallerUnpacked = transcend->unpack(symbCaller);
            Expression guard = std::get<1>(answer);

            __cacheEarlyReasoning.emplace(symbCallerUnpacked, guard);
        }
    }
}

Expression
PolymorphQuery::get(const Expression& e){
    SymbolGeneralized symbol=Attachments::exists<SymbolAlias>(e)?
        SymbolGeneralized(Attachments::get<SymbolAlias>(e))
        : SymbolGeneralized(SymbolAnonymous{e.id});

    if (__cacheEarlyReasoning.count(symbol)){
        return __cacheEarlyReasoning.at(symbol);
    }

    SymbolNode symbolPacked = __transcend->pack(symbol, "");
    StaticModel answer = __transcend->queryCompiled().queryLate(atomPolymorph, symbolPacked);
    assert(answer.size() && "Can't find a guard");

    Expression result;
    tie(result) = TranscendLayer::parse<Expression>(answer.begin()->second);
    return result;
}

}} //end of xreate::polymorph
