/* default_types.h
 *
 * Written by Matt Levy.
 * Modified by Artur Mikitiuk.
 * Modified 20 Aug 1999 by Neil Moore <neil@cs.uky.edu>
 * Modified  5 Sep 1999 by Neil Moore <neil@cs.uky.edu>
 *
 * Part of lderes.  See COPYRIGHT for copyright information.
 *
 */

#ifndef _DEFAULT_TYPES_H
#define _DEFAULT_TYPES_H	1

#include "hash.h"

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define DONT_KNOW -1
#define CONTRADICTORY -2

#define isKnown(bool) (bool >= 0)
typedef int Literal;
typedef unsigned short int Atom;
typedef signed short Boolean;
typedef unsigned short int UINT;

#define SIZE(array) (int) array[0]
#define MAKE_PAIR(x,y,pair) pair = x; pair <<= 16; pair |= y
#define EXTRACT_PAIR(x,y,pair) x = pair >> 16; y = pair & ~(x << 16)

#define negate(atom) (Literal) -atom
#define START_ATOM 1
#define NEXT_ATOM(atom) ++atom
#define LAST_ATOM(index,array) (index <= array[0])
#define NEGATED(lit) lit < 0
#define ATOM(lit) NEGATED(lit)?(Atom) (-lit):(Atom) lit
#define TRUE_VALUE(literal) NEGATED(literal)?FALSE:TRUE
#define INVALID_LITERAL(lit) lit == 0
#define CONTRADICT(val1, val2) (val1 + val2) == 1

/* Because this program is only concerned with simple formulas, a formula is an
array of literals.  The format of the array is:
    formula[0] = number of literals
    formula[size+1] = TRUE | FALSE   TRUE means is conjunction,
   				   FALSE means is disjunction
    formula[size+2] = number of true literals
    formula[size+3] = number of false literals
    formula[size+4] = index of default containing this formula as a prereq.
	(0 if none)
    formula[1] -> formula[size] = the actual id's of the literals in the formula
*/

typedef Literal *Formula;
typedef Formula *FormulaPtr;
#define FORM_SIZE(form) form[0]
#define NUMBER_TRUE(form) form[form[0]+2]
#define NUMBER_FALSE(form) form[form[0]+3]
#define ADD_TRUE(form) (form[form[0]+2])++
#define REMOVE_TRUE(form) (form[form[0]+2])--
#define ADD_FALSE(form) (form[form[0]+3])++
#define REMOVE_FALSE(form) (form[form[0]+3])--
#define AUDIT(form,table) {form[form[0]+2] = 0;form[form[0]+3] = 0; \
  for (int index = 1; index <= form[0]; index++) \
	  if (table.Prove(form[index])) \
		 ADD_TRUE(form); \
	  else if (table.Prove(negate(form[index]))) \
		 ADD_FALSE(form); }
#define IS_CONJUNCTION(form) form[form[0] + 1]
#define SET_REFERENCE(form,index) form[form[0] + 4] = index
#define GET_REFERENCE(form) form[form[0] + 4]

/* A default rule is a structure with three elements: a consequent (Formula), a 
    prerequisite (Formula), and an array of justifications (FormulaPtr).  */

typedef struct df_rule {
  int prerequisite, consequent, *justifications;
  Boolean good;
} DefaultRule;
typedef DefaultRule *DefaultRulePtr;

/* A set is defined as an array of bytes.  Element i is in a set iff the ith
entry is 1. */
typedef int Element;
typedef Element *Set;

/* The maximum size of the set is stored at set[0].  The depth is at
set[set[0]+1]. The actual size is stored at set[set[0]+2]. The stratum is at
set[set[0]+3].*/

#define SET_DEPTH(set) set[set[0]+1]
#define MEMBER(element,set) ((element <= set[0])?set[element] == 1:0)
#define MAX_SET_SIZE(set) set[0]
#define SET_SIZE(set) set[set[0]+2]
#define INCR_DEPTH(set) set[set[0]+1]++
#define EMPTY(set) (SET_SIZE(set) == 0)
#define SET_STRATUM(set) set[set[0]+3]
#define INCR_STRATUM(set) set[set[0]+3]++
#define ADD_ELEMENT(element,set) set[element]=1; SET_SIZE(set)++
#define REMOVE_ELEMENT(element,set) set[element]=0; SET_SIZE(set)--

inline Set CreateSet(int maxSize, Element depth);
inline void resetSet(Set set, int startPlace, int endPlace);
inline void AddElement(Set set, Element newElement);
inline void RemoveElement(Set set, Element newElement);
inline Set CopySet (Set set, Set space);
inline Boolean SubsetEmpty(Set set, int startRange, int endRange);
inline int SubsetSize(Set set, int startRange, int endRange);

/* A queue of integers is implemented using an array */

typedef Element *Queue;

/* The following conventions are used for queues:
	queue[0] contains the maximum queue size
	queue[size+1] head pointer
	queue[size+2] tail pointer */

#define NEXT_ENTRY(queue) ((queue[queue[0]+2] % queue[0]) + 1)
#define QUEUE_EMPTY(queue) (queue[queue[0]+1] == queue[queue[0]+2])
#define QUEUE_FULL(queue) (NEXT_ENTRY(queue) == queue[queue[0]+1])

inline Queue CreateQueue(int size);
inline Boolean Enqueue(Queue queue, Element element);
inline Element Dequeue(Queue queue);
inline void resetQueue(Queue queue);

/* A stack of Sets is implemented using an array */

typedef int *Stack;

/* The following conventions are used for stacks:
	stack[0] contains the maximum stack size
	stack[size+1] head pointer */

#define STACK_EMPTY(stack) (stack[stack[0]+1] == 0)
#define STACK_FULL(stack) (stack[0] == stack[stack[0]+1])

inline Stack CreateStack(int size);
inline Boolean Push(Stack stack, int element);
inline int Pop(Stack stack);

#endif /* _DEFAULT_TYPES_H */
