#include <stdio.h>
#include "ops.h"
#include <string.h>

/*
typedef enum OPType_e { EQ = 0, NE = 3, GT = 6, LE = 8, AND = 10, OR = 12 } OpType_t;
char OP_strs[] = {"==,!=,>,<,&,|"};

#define str_op        "!~+*-/=&^<>%"


OPERATIONS
----------

Assignment:
x =    lhs assigned to rhs

Logical/Relational:
- !    true if rhs is 0, else false
x ==   is eqal to
x !=   is not equal to
x >    rhs is greater than lhs
x >=   rhs is greater or equal to lhs
x <    lhs is greater then rhs
x <=   lhs is greater or equal to lhs
x &&   lhs and rhs are not equal to zero
x ||   one of lhs or rhs is not equal to zero
 
 
Bitwise:
- ~    bitwise not rhs
x |    lhs or rhs
x &    lhs and rhs
x ^    lhs xor rhs
- <<   lhs shifted left by rhs
- >>   lhs shifted right by lhs
    
- ~=   lhs assigned to bitwise not of rhs    
- &=   lhs assigned to lhs and with rhs
- |=   lhs assigned to lhs or with rhs
- ^=   lhs assigned to lhs xor with rhs
- >>=  lhs assigned to lhs shifted right by rhs
- <<=  lhs assigned to lhs shifted left by rhs
 
Math:
x +    lhs added to rhs
x -    rhs subtracted from lhs
x *    rhs multiplied by lhs
x /    rhs divided by lhs
x %    remaineder of rhs divided by lhs
- **   lhs to the exponenet of rhs
 
- +=   lhs assigned to lhs plus rhs    
- -=   lhs assigned to lhs minus rhs
- *=   lhs assigned to lhs times rhs
- /=   lhs assigned to lhs divided by rhs
- %=   lhs assigned to remainder of lhs divided by rhs
 
 
 const op const -> result (assigmnet denied)
 var   op const -> result (and lhs if assignment)
 const op var   -> result (assignment denied)
 var   op var   -> result (and lhs if assignment)
 
 
 
*/




/*
operation ( *result,  *lhs, *rhs) {
  modify result and possibly lhs
 rhs is not modified
  return OK   
}
*/

Status_t opIassignNotI (long * result,  long * lhs, long * rhs) {
 *result = *lhs =~ *rhs;
  return OK;
}

Status_t opIassignI (long * result,  long * lhs, long * rhs) {
 *result = *lhs = *rhs;
  return OK;
}

Status_t opIeqI( long * result, long * lhs, long * rhs) {
  if (*lhs == *rhs)  *result = 1;
  else               *result = 0;
  return OK;
}

Status_t opIneqI( long * result, long * lhs, long * rhs) {
  if (*lhs == *rhs)  *result = 0;
  else               *result = 1;
  return OK;  
}

Status_t opIgtI( long * result, long * lhs, long * rhs) {
  if (*lhs > *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opIlessI( long * result, long * lhs, long * rhs) {
  if (*lhs < *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opIgteI( long * result, long * lhs, long * rhs) {
  if (*lhs >= *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opIlesseI( long * result, long * lhs, long * rhs) {
  if (*lhs <= *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opIandI( long * result, long * lhs, long * rhs) {
  if ((*lhs != 0) && (*rhs != 0))   *result = 1;
  else                              *result = 0;
  return OK;  
}

Status_t opIorI( long * result, long * lhs, long * rhs) {
  if ((*lhs != 0) || (*rhs != 0))   *result = 1;
  else                              *result = 0;
  return OK;  
}

Status_t opIaddI( long * result, long * lhs, long * rhs) {
  *result = *lhs + *rhs;
  return OK;  
}

Status_t opImoduI ( long * result, long * lhs, long * rhs) {
  *result = *lhs % *rhs;
  return OK;
}

Status_t opImulI( long * result, long * lhs, long * rhs) {
  *result = (*lhs) * (*rhs);
  return OK;  
}

Status_t opIdivI( long * result, long * lhs, long * rhs) {
  *result = *lhs / *rhs;
  return OK;  
}


Status_t opIsubI( long * result, long * lhs, long * rhs) {
  *result = *lhs - *rhs;
  return OK;  
}


Status_t opIbxorI( long * result, long * lhs, long * rhs) {
  *result = *lhs ^ *rhs;
  return OK;  
}

Status_t opIbandI( long * result, long * lhs, long * rhs) {
  *result = *lhs & *rhs;
  return OK;  
}

Status_t opIborI( long * result, long * lhs, long * rhs) {
  *result = *lhs | *rhs;
  return OK;  
}

Status_t opIshlI( long * result, long * lhs, long * rhs) {
  *result = *lhs << *rhs;
  return OK;  
}

Status_t opIshrI( long * result, long * lhs, long * rhs) {
  *result = *lhs >> *rhs;
  return OK;  
}





Status_t opDandD( double * result, double * lhs, double * rhs) {
  if ((*lhs != 0) && (*rhs != 0))   *result = 1;
  else                              *result = 0;
  return OK;  
}

Status_t opDorD( double * result, double * lhs, double * rhs) {
  if ((*lhs != 0) || (*rhs != 0))   *result = 1;
  else                              *result = 0;
  return OK;  
}

Status_t opDaddD( double * result, double * lhs, double * rhs) {
  *result = *lhs + *rhs;
  return OK;  
}


Status_t opDsubD( double * result, double * lhs, double * rhs) {
  *result = *lhs - *rhs;
  return OK;  
}


Status_t opDassignD (double * result,  double * lhs, double * rhs) {
 *result = *lhs = *rhs;
  return OK;
}

Status_t opDeqD( double * result, double * lhs, double * rhs) {
  if (*lhs == *rhs)  *result = 1;
  else               *result = 0;
  return OK;
}

Status_t opDneqD( double * result, double * lhs, double * rhs) {
  if (*lhs == *rhs)  *result = 0;
  else               *result = 1;
  return OK;  
}

Status_t opDgtD( double * result, double * lhs, double * rhs) {
  if (*lhs > *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opDlessD( double * result, double * lhs, double * rhs) {
  if (*lhs < *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opDgteD( double * result, double * lhs, double * rhs) {
  if (*lhs >= *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}

Status_t opDlesseD( double * result, double * lhs, double * rhs) {
  if (*lhs <= *rhs)   *result = 1;
  else               *result = 0;
  return OK;  
}


Status_t opDmulD( double * result, double * lhs, double * rhs) {
  *result = (*lhs) * (*rhs);
  return OK;  
}

Status_t opDdivD( double * result, double * lhs, double * rhs) {
  *result = *lhs / *rhs;
  return OK;  
}

Status_t opDmoduD ( double * result, double * lhs, double * rhs) {
  *result = fmod(*lhs,*rhs);
  return OK;
}

Status_t opDshlD( double * result, double * lhs, double * rhs) {
  
  *result = *lhs * pow(2, *rhs);
  return OK;  
}

Status_t opDshrD( double * result, double * lhs, double * rhs) {
  *result = *lhs / pow(2, *rhs);
  return OK;  
}


Status_t opResolve(OpType_t * out, char * in ) {
/*
  typedef enum OPType_e   { EQ = 0, NE = 3, GT = 6, LE = 8, AND = 10, OR = 12, EQXOR = 14, ADD = 17, XOR = 19 } OpType_t;
  */
  
  if (0);
  else if(!strcmp(in, "="))     *out = IS;
  else if(!strcmp(in, "=="))    *out = EQ;
  else if(!strcmp(in, "!="))    *out = NE;
  else if(!strcmp(in, ">"))     *out = GT;
  else if(!strcmp(in, ">="))    *out = GTRE;
  else if(!strcmp(in, "<"))     *out = LE;
  else if(!strcmp(in, "<="))    *out = LERE;
  else if(!strcmp(in, "&&"))    *out = AND;
  else if(!strcmp(in, "||"))    *out = OR;
  else if(!strcmp(in, "^="))    *out = EQXOR;
  else if(!strcmp(in, "+"))     *out = ADD;
  else if(!strcmp(in, "^"))     *out = XOR;  
  else if(!strcmp(in, "-"))     *out = SUB;  
  else if(!strcmp(in, "|"))     *out = BOR;  
  else if(!strcmp(in, "&"))     *out = BAND;  
  else if(!strcmp(in, "*"))     *out = MUL;
  else if(!strcmp(in, "/"))     *out = DIV;
  else if(!strcmp(in, "%"))     *out = MODU;
  else if(!strcmp(in, ">>"))    *out = SHIFTR;
  else if(!strcmp(in, "<<"))    *out = SHIFTL;
  else                          return NoMatch;
                                return OK;
}






/*

int main(void) {

  long a, l, r;
  
  l = 2;
  r = 4;
  
  opIassignI(&a, &l, &r);
  printf("(%ld)      %ld assign %ld \n", a, l, r);
  
  l = 2;
  
  opIeqI(&a, &l, &r);
  printf("(%ld)      %ld == %ld \n", a, l, r);

  opIneqI(&a, &l, &r);
  printf("(%ld)      %ld != %ld \n", a, l, r);
  
  opIgtI(&a, &l, &r);
  printf("(%ld)      %ld > %ld \n", a, l, r);
  
  opIlessI(&a, &l, &r);
  printf("(%ld)      %ld < %ld \n", a, l, r);

  opIgteI(&a, &l, &r);
  printf("(%ld)      %ld >= %ld \n", a, l, r);
  
  opIlesseI(&a, &l, &r);
  printf("(%ld)      %ld <= %ld \n", a, l, r);

  opIandI(&a, &l, &r);
  printf("(%ld)      %ld & %ld \n", a, l, r);
  
  opIorI(&a, &l, &r);
  printf("(%ld)      %ld | %ld \n", a, l, r);
  
  return 0;
}
*/

