#ifdef DOC_BUILD_INTERNAL
#endif
#include "fol.h"
typedef enum {FBOOL=0, FALPHA=1, FTOP=2, FTRUE=3, FFALSE=4, FAND=5, FOR=6, FNOT=7, FEXIST=8, FFORALL=9,
       FIMPLIES=10, FEQUIV=11, FEQUALBOOL=12, FXOR=13, FNAND=14, FNOR=15, FATMOST=16, FATLEAST=17,
       FITE=18, FEQUAL=19, FQUANTVARS=20, FTERMSTATE=21, FTFLAST=22} FOLSTATEFIELD;
FOLSTATE fol_Init(TERMSTATE termstate)
{
  FOLSTATE folstate;
  SYMBSTATE symbstate;
  MEMORY mem;
  symbstate = term_GetSymbstate(termstate);
  mem = symbol_GetStateMemory(symbstate);
  folstate = (FOLSTATE)memory_Malloc(mem, sizeof(FOLSTATENODE) * FTFLAST);
  folstate[FTERMSTATE] = (intptr_t)termstate;
  folstate[FBOOL] = symbol_CreateTypeConstant(symbstate, "BOOL");
  folstate[FALPHA] = symbol_CreateTypeConstant(symbstate, "Alpha");
  folstate[FTOP] = symbol_CreateTypeConstant(symbstate, "Top");
  folstate[FTRUE] = symbol_CreateOperator(symbstate, folstate[FBOOL], "true", 0);
  folstate[FFALSE] = symbol_CreateOperator(symbstate, folstate[FBOOL], "false", 0);
  folstate[FNOT] = symbol_CreateOperator(symbstate, folstate[FBOOL], "not", 1);
  symbol_SetArgumentType(symbstate, folstate[FNOT], folstate[FBOOL], 0);
  folstate[FAND] = symbol_CreateOperator(symbstate, folstate[FBOOL], "and", -1);
  symbol_SetArgumentType(symbstate, folstate[FAND], folstate[FBOOL], 0);
  folstate[FOR] = symbol_CreateOperator(symbstate, folstate[FBOOL], "or", -1);
  symbol_SetArgumentType(symbstate, folstate[FOR], folstate[FBOOL], 0);
  folstate[FIMPLIES] = symbol_CreateOperator(symbstate, folstate[FBOOL], "implies", 2);
  symbol_SetArgumentType(symbstate, folstate[FIMPLIES], folstate[FBOOL], 0);
  symbol_SetArgumentType(symbstate, folstate[FIMPLIES], folstate[FBOOL], 1);
  folstate[FEQUIV] = symbol_CreateOperator(symbstate, folstate[FBOOL], "equiv", 2);
  symbol_SetArgumentType(symbstate, folstate[FEQUIV], folstate[FBOOL], 0);
  symbol_SetArgumentType(symbstate, folstate[FEQUIV], folstate[FBOOL], 1);
  folstate[FEQUALBOOL] = symbol_CreateOperator(symbstate, folstate[FBOOL], "equalbool", -1);
  symbol_SetArgumentType(symbstate, folstate[FEQUALBOOL], folstate[FBOOL], 0);
  folstate[FFORALL] = symbol_CreateOperator(symbstate, folstate[FBOOL], "forall", 2);
  symbol_SetArgumentType(symbstate, folstate[FFORALL], folstate[FALPHA], 0);
  symbol_SetArgumentType(symbstate, folstate[FFORALL], folstate[FBOOL], 1);
  folstate[FEXIST] = symbol_CreateOperator(symbstate, folstate[FBOOL], "exist", 2);
  symbol_SetArgumentType(symbstate, folstate[FEXIST], folstate[FALPHA], 0);
  symbol_SetArgumentType(symbstate, folstate[FEXIST], folstate[FBOOL], 1);
  folstate[FQUANTVARS] = symbol_CreateFunction(symbstate, folstate[FALPHA], "", -1);
  symbol_SetArgumentType(symbstate, folstate[FQUANTVARS], folstate[FALPHA], 0);
  folstate[FATMOST] = symbol_CreateOperator(symbstate, folstate[FBOOL], "atmost", -2);
  symbol_SetArgumentType(symbstate, folstate[FATMOST], folstate[FALPHA], 0);
  symbol_SetArgumentType(symbstate, folstate[FATMOST], folstate[FBOOL], 1);
  folstate[FATLEAST] = symbol_CreateOperator(symbstate, folstate[FBOOL], "atleast", -2);
  symbol_SetArgumentType(symbstate, folstate[FATLEAST], folstate[FALPHA], 0);
  symbol_SetArgumentType(symbstate, folstate[FATLEAST], folstate[FBOOL], 1);
  folstate[FNOR] = symbol_CreateOperator(symbstate, folstate[FBOOL], "nor", -1);
  symbol_SetArgumentType(symbstate, folstate[FNOR], folstate[FBOOL], 0);
  folstate[FNAND] = symbol_CreateOperator(symbstate, folstate[FBOOL], "nand", -1);
  symbol_SetArgumentType(symbstate, folstate[FNAND], folstate[FBOOL], 0);
  folstate[FXOR] = symbol_CreateOperator(symbstate, folstate[FBOOL], "xor", -1);
  symbol_SetArgumentType(symbstate, folstate[FXOR], folstate[FBOOL], 0);
  folstate[FITE] = symbol_CreateOperator(symbstate, folstate[FBOOL], "ite", 3);
  symbol_SetArgumentType(symbstate, folstate[FITE], folstate[FBOOL], 0);
  symbol_SetArgumentType(symbstate, folstate[FITE], folstate[FBOOL], 1);
  folstate[FEQUAL] = symbol_CreatePredicate(symbstate, folstate[FBOOL], "=", 2);
  symbol_SetArgumentType(symbstate, folstate[FEQUAL], folstate[FTOP], 0);
  symbol_SetArgumentType(symbstate, folstate[FEQUAL], folstate[FTOP], 1);
  return folstate;
}
TERMSTATE fol_GetStateTermstate(FOLSTATE folstate)
{
  return (TERMSTATE)folstate[FTERMSTATE];
}
TERMSTATE fol_GetTermstate(FOLSTATE folstate)
{
  return (TERMSTATE)folstate[FTERMSTATE];
}
MEMORY fol_GetStateMemory(FOLSTATE folstate)
{
  return symbol_GetStateMemory(term_GetSymbstate((TERMSTATE)folstate[FTERMSTATE]));
}
MEMORY fol_GetMemory(FOLSTATE folstate)
{
  return symbol_GetStateMemory(term_GetSymbstate((TERMSTATE)folstate[FTERMSTATE]));
}
SYMBSTATE fol_GetStateSymbolState(FOLSTATE folstate)
{
  return term_GetSymbstate((TERMSTATE)folstate[FTERMSTATE]);
}
SYMBSTATE fol_GetSymbstate(FOLSTATE folstate)
{
  return term_GetSymbstate((TERMSTATE)folstate[FTERMSTATE]);
}
SYMBOL fol_True(FOLSTATE folstate)
{
  return folstate[FTRUE];
}
SYMBOL fol_False(FOLSTATE folstate)
{
  return folstate[FFALSE];
}
SYMBOL fol_Forall(FOLSTATE folstate)
{
  return folstate[FFORALL];
}
SYMBOL fol_Exist(FOLSTATE folstate)
{
  return folstate[FEXIST];
}
SYMBOL fol_And(FOLSTATE folstate)
{
  return folstate[FAND];
}
SYMBOL fol_Or(FOLSTATE folstate)
{
  return folstate[FOR];
}
SYMBOL fol_Not(FOLSTATE folstate)
{
  return folstate[FNOT];
}
SYMBOL fol_Implies(FOLSTATE folstate)
{
  return folstate[FIMPLIES];
}
SYMBOL fol_Equiv(FOLSTATE folstate)
{
  return folstate[FEQUIV];
}
SYMBOL fol_EqualBool(FOLSTATE folstate)
{
  return folstate[FEQUALBOOL];
}
SYMBOL fol_Equal(FOLSTATE folstate)
{
  return folstate[FEQUAL];
}
SYMBOL fol_Xor(FOLSTATE folstate)
{
  return folstate[FXOR];
}
SYMBOL fol_Ite(FOLSTATE folstate)
{
  return folstate[FITE];
}
SYMBOL fol_QuantVars(FOLSTATE folstate)
{
  return folstate[FQUANTVARS];
}
BOOL fol_IsTrue(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_True(Folstate));
}
BOOL fol_IsFalse(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_False(Folstate));
}
BOOL fol_IsForall(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Forall(Folstate));
}
BOOL fol_IsAnd(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_And(Folstate));
}
BOOL fol_IsExist(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Exist(Folstate));
}
BOOL fol_IsOr(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Or(Folstate));
}
BOOL fol_IsNot(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Not(Folstate));
}
BOOL fol_IsImplies(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Implies(Folstate));
}
BOOL fol_IsEquiv(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Equiv(Folstate));
}
BOOL fol_IsEqual(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Equal(Folstate));
}
BOOL fol_IsEqualBool(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_EqualBool(Folstate));
}
BOOL fol_IsXor(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Xor(Folstate));
}
BOOL fol_IsIte(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_Ite(Folstate));
}
BOOL fol_IsQuantVars(FOLSTATE Folstate, TERM Term)
{
  return symbol_Equal(term_TopSymbol(Term), fol_QuantVars(Folstate));
}
TYPE fol_TypeAlpha(FOLSTATE folstate)
{
  return folstate[FALPHA];
}
TYPE fol_TypeBool(FOLSTATE folstate)
{
  return folstate[FBOOL];
}
TYPE fol_TypeTop(FOLSTATE folstate)
{
  return folstate[FTOP];
}
BOOL fol_IsQuantifierSymbol(FOLSTATE Folstate, SYMBOL Symbol)
{
  return symbol_Equal(Symbol, fol_Exist(Folstate))
    || symbol_Equal(Symbol, fol_Forall(Folstate));
}
BOOL fol_IsQuantifier(FOLSTATE Folstate, TERM Term)
{
  return fol_IsExist(Folstate, Term) || fol_IsForall(Folstate, Term);
}
BOOL fol_IsAtom(FOLSTATE Folstate, TERM Term)
{
  return symbol_IsPredicate(term_TopSymbol(Term));
}
BOOL fol_IsLiteral(FOLSTATE Folstate, TERM Term)
{
  return fol_IsAtom(Folstate, Term) ||
    (fol_IsNot(Folstate, Term) &&
     fol_IsAtom(Folstate, term_FirstArgument(Term)));
}
BOOL fol_IsPropAtom(FOLSTATE Folstate, TERM Term)
{
  return symbol_IsPredicate(term_TopSymbol(Term)) && term_GetArity(Term) == 0;
}
BOOL fol_IsPropLiteral(FOLSTATE Folstate, TERM Term)
{
  return fol_IsPropAtom(Folstate, Term) ||
    (fol_IsNot(Folstate, Term) &&
     fol_IsPropAtom(Folstate, term_FirstArgument(Term)));
}
TERM fol_GetAtom(FOLSTATE Folstate, TERM Term)
{
  misc_ASSERT(fol_IsLiteral(Folstate,Term));
  if (symbol_IsPredicate(term_TopSymbol(Term)))
    return Term;
  else
    return term_FirstArgument(Term);
}
NAT fol_GetQuantifiedVariable(FOLSTATE Folstate, TERM Term)
{
  TERM var;
#ifdef SPASS_CHECK
  if (!fol_IsQuantifier(Folstate, Term)
      || 2 != term_GetArity(Term)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Illegal input. Not a Quantifier of arity 2.", __func__);
    misc_FinishErrorReport();
  }
#endif
  var = term_GetArgument(Term, 0);
#ifdef SPASS_CHECK
  if (!term_IsVariable(fol_GetTermstate(Folstate), var)) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In %s: Illegal input. arg0 of quantifier not a variable.", __func__);
    misc_FinishErrorReport();
  }
#endif
  return term_TopSymbol(var);
}
short fol_GetLiteralPolarity(FOLSTATE Folstate, TERM Term)
{
  misc_ASSERT(fol_IsLiteral(Folstate,Term));
  if (symbol_IsPredicate(term_TopSymbol(Term)))
    return 1;
  else
    return -1;
}
TERM fol_Negate(FOLSTATE Folstate, TERM T)
{
  TERM res;
  res = term_CreateArity(fol_GetStateTermstate(Folstate),fol_Not(Folstate),1);
  term_SetArgument(res,0,T);
  return res;
}
TERM fol_NegateToggle(FOLSTATE Folstate, TERM T)
{
  TERM res;
  if (fol_IsNot(Folstate, T)) {
    res = term_FirstArgument(T);
    term_Free(fol_GetStateTermstate(Folstate), T);
    return res;
  }
  else {
    return fol_Negate(Folstate, T);
  }
}
TERM fol_CreateQuantifiedFormula(FOLSTATE folstate, SYMBOL Quantifier, ARRAY Arguments)
{
#ifdef CHECK
  if (!fol_IsQuantifierSymbol(Quantifier)
      || !symbol_Equal(term_TopSymbol(array_GetElement(Arguments,0)),fol_QuantVars(folstate))) {
    misc_StartErrorReport();
    misc_ErrorReport("\n In fol_CreateQuantifier: Symbol isn't FOL quantifier or argument not a quant var term.\n");
    misc_FinishErrorReport();
  }
#endif
  return term_Create(fol_GetStateTermstate(folstate), Quantifier, Arguments);
}
int fol_ComparePropLiteral(FOLSTATE folstate,
    TERM litL, TERM litR)
{
  TERM atomL,atomR;
  int res;
#ifdef SPASS_CHECK
  if (!(fol_IsLiteral(folstate, litL) && fol_IsLiteral(folstate, litR))){
    term_Print(fol_GetStateTermstate(folstate),litL);
    printf("\n");
    term_Print(fol_GetStateTermstate(folstate),litR);
    printf("\n");
    misc_StartErrorReport();
    misc_ErrorReport("\n %s: Illegal input.", __func__);
    misc_FinishErrorReport();
  }
#endif
  atomL = term_IsAtom(litL)?litL : term_FirstArgument(litL);
  atomR = term_IsAtom(litR)?litR : term_FirstArgument(litR);
  res = term_CompareTotal(fol_GetStateTermstate(folstate),atomL,atomR);
  if(res==0)
    res = term_IsAtom(litR)-(term_IsAtom(litL));
  return res;
}
int fol_ComparePropLiteral_func(const void * left, const void * right, void * folstate)
{
  return fol_ComparePropLiteral((FOLSTATE) folstate, *((TERM*) left), *((TERM*) right));
}
void fol_Free(FOLSTATE folstate)
{
  memory_Free(fol_GetStateMemory(folstate), folstate, sizeof(FOLSTATENODE) * FTFLAST);
}
