/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 *
 * association.cpp
 *
 * Author: pgess <v.melnychenko@xreate.org>
 * Created on August 12, 2017, 9:28 PM
 */
#include "xreatemanager.h"
#include "transcendlayer.h"
#include "pass/interpretationpass.h"
#include <gtest/gtest.h>

using namespace xreate::interpretation;
using namespace xreate;
using namespace std;

TEST(Association, TypedQuery_1) {
    auto man = ::xreate::details::tier1::XreateManager::prepare(R"Code(
        AtomNumT = type slave atomNumT.
        AtomStrT = type slave atomStrT.
        CompListT = type slave compListT.
        CompArithT = type slave compArithT.

        test = function:: num; entry
        {
            query1 = intrinsic query("atomNumT")::[AtomNumT].
            query2 = intrinsic query("atomStrT")::[AtomStrT].
            query3 = intrinsic query("compListT")::[CompListT].
            query4 = intrinsic query("compArithT")::[CompArithT].
            test1 = query1[0] == 5::            bool.
            test2 = query2[1] == "y"::          bool.
            test3 = query3[0, 1] == "x" ::      bool.
            test4 = query4[0, 0, 0] == 1::         bool.

            test1 + test2 + test3 + test4
        }
    )Code");

    man->transcend->addRawScript(R"RAW(
        atomNumT(5; 8).
        atomStrT("x"; "y").
        compListT(5, "x").
        compListT(8, "y").
        compArithT(add(1, 2)).
        compArithT(mul(5, 6)).
    )RAW");

    man->analyse();
    int (*test)() = (int (*)())man->run();
    int result = test();
    ASSERT_EQ(4, result);
}

TEST(Association, QueryLate_ast_1){
    auto man = XreateManager::prepare(
R"Code(
    test = function:: num; entry 
    {
        intrinsic query late("dict"->x:: bool)::bool 
        {
            (x == true)
        }
    }
)Code");
}

TEST(Association, QueryLate_pass_1){
    auto man = ::xreate::details::tier1::XreateManager::prepare(
R"Code(
    test = function:: num; entry 
    {
        intrinsic query late("dict"->x:: bool)::bool 
        {
            (x == true)
        }
    }
)Code");
    man->analyse();
    
    Expression instructionE = man->root->findFunction("test")->getEntryScope()->getBody();
    InterpretationData instructionData = Attachments::get<InterpretationData>(instructionE);
    ASSERT_EQ(QUERY_LATE, instructionData.op);
}

TEST(Association, QueryLate_target_1){
        auto man = ::xreate::details::tier1::XreateManager::prepare(
R"Code(
    Equipment = type variant {dresser, sink, stove}.
    Room = type variant{kitchen, bedroom, bathroom}.
        
    test = function:: num; entry 
    {
        room = bedroom() :: Room; room.
        equipment = intrinsic query late("whatshere"->x:: Equipment)::int; equipment
            { if (x == dresser()):: int {1} else {0} }.
        
        equipment + (room::int)
    }
)Code");
        
    man->transcend->addRawScript(
R"RAW(
    room(kitchen; bedroom; bathroom).
    equipment(dresser;sink;stove).
    interior(kitchen, stove).
    interior(bedroom, dresser).
    interior(bathroom, sink).
    
    late(VarTarget, VarRoom, Room, whatshere(Equipment)):-
        bind(VarTarget, equipment);
        bind(VarRoom, room);
        interior(Room, Equipment);
        equipment(Equipment);
        room(Room).
)RAW");
    
    man->analyse();
    int (*result)() = (int (*)()) man->run();
    ASSERT_EQ(2, result());
}



