Main loop

      ////////////////

#include
#include 
#include 
#include 
#include "cursor.h"
#include "slots.h"

// A process that performs a join 
// between two directed semantic graphs 
// The graphs are user specified, format defined externally.
//
// The join equation:
//      result equals left join right
// left,right and result are Cursor pointers into the 
// externally defined graph data bases
//
// joinloop, the routine  is generic, mainly pushing and popping
// cursors in the stack and executing call back
//
// calls are externally defined database methods
//
// Macros to operate on cursors
//
// Version 1,o, not really tested production alpha
// contact Matt Young 
// youngsanger@gmail.com
///////////////////////////////////
#define Stepping(p) p->exec(p,Step,0)
#define Skipping(p) p->exec(p,Skip,0)
#define Setting(p) p->exec(p,Set,0)
#define Resetting(p) p->exec(p,Reset,0)
#define Fetching(p) p->exec(p,Fetch,0)
#define Valuing(p,q) p->eval(p,q)
#define Putting(p,q) p->element=q->element; p->exec(p,Append,0)
#define Mode(p) p->mode// Forward references
#define Paused(p,q) (Mode(p) == Pause || Mode(q) == Pause)

// Forward references
void init_element(PCursor ); // Malloc and initialize a generic node structure
void expand_cursor(PCursor ,PCursor,PCursor,int);  // step into
int increment_loops(PCursor left,PCursor right,int ls,int rs);  // outer join loop
void put_element(PCursor); // output is a graph
void print_status(int l, int r); // debug utility
void print_keys(void);
#define Debug(l,r) print_status(l,r);print_keys()

// simple join loop, reentry capable, first two argument almost commute
// But the left side dominates termination
// It mainly does push and pop of the cursors, using the stack 
// and likely shold maintain its own cursor stack.
// the grammar defined externally
//
// Defines


enum ExpandModes { StepRight,StepLeft}; 

int join_cursor(PCursor left, PCursor right, PCursor result) 
 {
 int ls,rs;
// char* p;

// closed, only a break will exit
 do {  
// Order of possible events in the loop
// If the current cursors maybe paused, then start another pair
  while(Paused(left,right)) {
      NextTriple(&left,&right,&result);
   }
// An external attachment evaluates the opcode key pairs
    ls = Fetching(left);
  ls = Valuing(left,right);
    rs = Fetching(right);
    rs = Valuing(right,left);

 //Debug(ls,rs);
//p = (char *)left->start;
//p = left->element.key;
// Then do one of
// First: Breaks, Dones and Matches
 if(ls == Done || rs == Done)
  break;    
 else if(ls== End) {
// End of left sequence with no match
// Some might consider an attachment error
// But pass through the loop anyway
  Stepping(left);
  Skipping(right);
  }
 
// If this a Match-Break pair, in some order
// singletons report match, sequences report break
// Match only happens on dot element, sequences return Break   
 if(Matched(ls,rs)) {
  Putting(result,right);

// If result wants all matches then follow through
// and step the loops to continue traversal
  if(Mode(result) == Match_All) {
   if(increment_loops(left,right,ls,rs) == Break) 
    break;
   }
  else {
// Here both sides mmove on from thr match
// Check for singletons that generate Match
      if(ls == Match) 
       Stepping(left);     
      if(rs == Match)  
       Stepping(right);
      if((rs == Break) || (ls == Break)) {
       if(ls == Break && rs == Break)
         Mode(right) = Done;
       break;
   }
    }
 } //if Matched
// This is an unmatched pair
// Descend right
 else if(rs == Push) 
   expand_cursor(left,right,result,StepRight);
// Descend left  
 else if(ls == Push) 
  expand_cursor(left,right,result,StepLeft); 
// Just increment the inner(right) or outter(left)
 else if(increment_loops(left,right,ls,rs) == Break)
  break;
 } while(1); 
  return(Done);
 }

int increment_loops(PCursor left,PCursor right,int ls,int rs) {
 int s;
  if(rs == End) {
   Resetting(right);
     if(ls == Singleton || ls == Match) 
   s=Break; //Sequence has been searched
  else {
      Stepping(left); // step the outer 
   s=Null;
   }
  }
 else {
 // Just increment increment inner
   Stepping(right); 
  s=Null;
 }
  return(s);
 }
 

// This expands a group
// First, a utility
PCursor set_up_cursor(PCursor self) {
 char *p;
 PCursor cursor;
 cursor = dup_cursor(self); 
 Skipping(self);  // Cursor set forward on return
 cursor->exec(cursor,Step,0);
 Setting(cursor);
 ReplaceCursor(cursor); // The spot on the index
 return(cursor);
}

// The expansions
void expand_cursor(PCursor left,PCursor right, PCursor result,int mode) {
 PCursor cursor;
 // There is a match in the comma sequence
 // skip the right qnd step the left
 if(mode == StepRight) {
  cursor =set_up_cursor(right);
  join_cursor(left,cursor,result);
  ReplaceCursor(right);
  }
 else if(mode == StepLeft) {
  cursor =set_up_cursor(left); 
  join_cursor(cursor,right,result);
  ReplaceCursor(left);
  }
 del_cursor(cursor);
 }

//////////////////////////////
// Cursor methods
///////////////////////////// 
// Caller must have their own cursor initialization
PCursor new_cursor(int ksize) {
 PCursor self;
 self = malloc(sizeof(Cursor));
 memset(self,0,sizeof(Cursor));
 self->key_size= ksize;
 init_element(self); 
 return self;
}
#define SELF ((PCursor) self)
PCursor dup_cursor(PCursor self) {
 PCursor other;
 other= (PCursor) malloc(sizeof(Cursor));
 memcpy(other,self,sizeof(Cursor));
 init_element(other); 
 strcpy(other->element.key,SELF->element.key);
  return other;
}

void del_cursor(PCursor self) {
 //free(self->start);
 free(SELF->element.key);
 free(self);
}
void init_element(PCursor self) {
 self->element.key=malloc(self->key_size); // space for key string
 self->element.op=0;  // All nodes con sidered to be op and key pairs
 }

// Initilization, internal to attachment
// But this utility is included here, optionally.
// mainly for char * style processing
//
 
PCursor init_cursor(ExecCallback cursor_exec, EvalCallback cursor_eval,
  int ksize,void* buf) {
 PCursor self;
 self = new_cursor(ksize);
 self->exec = cursor_exec;
 self->eval = cursor_eval;
 
 self->start =  buf;
 self->current =  self->start;
 self->state = self->current;
 self->key_size=ksize;
 self->mode = 0;
  return(self);
 }


////////////////////////////////////////////////

No comments: