/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 *
 * ast.cpp
 *
 *  Created on: 06/04/2020
 *      Author: pgess <v.melnychenko@xreate.org>
 */

#include "xreatemanager.h"
#include "pass/compilepass.h"
#include "supplemental/basics.h"
#include "gtest/gtest.h"

using namespace xreate;
using namespace std;

typedef bool (*FnB_NoA)();
TEST(Arithmetics, Logic_OpAnd1)
{
  string code = R"Code(
    test = function:: bool; entry() { true AND false and true }
  )Code";
  XreateManager* xreate = XreateManager::prepare(move(code));
  FnB_NoA program = (FnB_NoA) xreate->run();

  bool result = program();
  ASSERT_EQ(false, result);
}

TEST(Arithmetics, Logic_OpOr1)
{
  string code = R"Code(
    test = function:: bool; entry() { true AND false OR true }
  )Code";
  XreateManager* xreate = XreateManager::prepare(move(code));
  FnB_NoA program = (FnB_NoA) xreate->run();

  bool result = program();
  ASSERT_EQ(true, result);
}

TEST(Arithmetics, Logic_OpNeg1)
{
  string code = R"Code(
    test = function:: bool; entry() { -((true AND false)::bool) }
  )Code";
  XreateManager* xreate = XreateManager::prepare(move(code));
  FnB_NoA program = (FnB_NoA) xreate->run();

  bool result = program();
  ASSERT_EQ(true, result);
}

TEST(Arithmetics, Logic_DeMorgan1)
{
  string code = R"Code(
test = function:: bool; entry()
{
  xs = {false, true}:: [bool].
  ys = xs :: [bool]; csize(2).

  loop fold(xs->x:: bool, true ->acc):: bool
  {
    loop fold(ys->y:: bool, true ->acc):: bool
    {
      test = (-((x and y)::bool)) == (-x OR -y):: bool.

      test AND acc
    } AND acc
  }
}
)Code";
  XreateManager* xreate = XreateManager::prepare(move(code));
  FnB_NoA program = (FnB_NoA) xreate->run();

  bool result = program();
  ASSERT_EQ(true, result);
}

TEST(Arithmetics, Logic_If1){
  string code = R"Code(
test = function:: bool; entry()
{
  if (true, false, true):: bool {true} else {false}
}
)Code";
  XreateManager* xreate = XreateManager::prepare(move(code));
  FnB_NoA program = (FnB_NoA) xreate->run();

  bool result = program();
  ASSERT_EQ(false, result);
}

TEST(Arithmetics, OperatorMod1){
  string code = R"Code(
    test = function(x:: int, y::int):: int; entry()
    {
      x % y
    }
  )Code";

  XreateManager* xreate = XreateManager::prepare(move(code));
  Fn2Args program = (Fn2Args) xreate->run();

  ASSERT_EQ(1, program(4, 3));
}