#define X_APP 1
#include <stdio.h>

#define AST_idx_mask 0x7FFFFFFU
#define AST_type_shift 27U
#define AST_type_mask  31U
#define AST_BIP     (16U << AST_type_shift)
#define AST_PHRASE  (17U << AST_type_shift)
#define AST_LITERAL (18U << AST_type_shift)


static int printlit(int sx) {
  int ch;
#ifdef NEVER
  fprintf(stderr, "{@%08x}", sx);
  for (;;) {
    ch = Stringpool(sx);
    if (ch == '\0') break;
    fprintf(stderr, "%lc", ch);
    sx++;
  }
#else
  source_descriptor ap = atom(sx);
  //fprintf(stderr, "@%d: start=%d end=%d skipped=%08x canon=%08x t=\"", sx,
  //        ap.start, ap.end, ap.skipped, ap.canon);
  int p = ap.start;
  for (;;) {
    if (p == ap.end) break;
    ch = source(p).ch;
    if (ch == '\0') {
      fprintf(stderr, "[ERROR]");
    }
    fprintf(stderr, "%lc", ch);
    p++;
  }
  //fprintf(stderr, "\"\n");
#endif
  return sx;
}

int compile(int Ph, int depth) {

  if (Ph < 0) return Ph;
  // AST format not properly designed yet.  These are placeholders:
#define P(x) AST((Ph&AST_idx_mask)+4+TUPLE_RESULT_FIELDS+(x)-1)
#ifdef wlit
#undef wlit
#endif
#define wlit(x) printlit((x)&AST_idx_mask) // used to print in tree walk

  int AST_index = Ph&AST_idx_mask;
  int AST_type  = Ph & (AST_type_mask << AST_type_shift);
  int op    = AST(AST_index+1);
  int alt   = AST(AST_index+2);
  int count = AST(AST_index+3);

  // e.g. on initial call, ...
  // P<SS> = ...;
  // /*785*/ COUNT_OF_ALTS    | 0x000001,
  // /*786*/ COUNT_OF_PHRASES | 0x000004,
  // /*787*/ SEMANTIC_TYPE    | S_init,
  // /*788*/ SEMANTIC_TYPE    | S_Imp77_stropping,
  // /*789*/ PHRASE_TYPE      | G_STATEMENTS,
  // /*790*/ SEMANTIC_TYPE    | S_terminate,

  // Ph=20043fa0  AST_type = 2  AST_index = 278432  op=785[58000001]  alt=0  count=4

  if (AST_type == AST_LITERAL) {
    //printlit(AST_index);
    return -1;
  }
  if (AST_type == AST_BIP) {
    //PrintAtom(AST_index);
    return -1;
  }
  if (AST_type != AST_PHRASE) {
    return -1;
  }

  // converting from a grammar index to the more dense phrase index is
  // an expensive lookup.  There are two obvious ways to avoid it:
  //
  // 1) Index the switch below by G_* instead of P_*.
  // 2) Add another item to the grammar so that gram[G_x] contains P_x.
  //    - this is a good solution but there's a lot of places where
  //    changes will be needed to make it work.
  // 3) Not space efficient: have an array as large as the grammar
  //    to directly index G_x to P_x.  No good reason to do this other
  //    than simplicity.
  
  static int PHRASE;
  for (PHRASE = 0; PHRASE < NUM_SIMPLE_PHRASES; PHRASE++) {
    if (sequential_phrase_no_to_grammar_index[PHRASE] /* aka P_to_G_*/ == op) break;
  }
  if (PHRASE == NUM_SIMPLE_PHRASES) {
    // NOT FOUND!
    fprintf(stderr, "I overlooked something.\n"); exit(1);
  }
  /*  
  fprintf(stderr, "Ph=%08x  AST_type = %d  AST_index = %d  Grammar index=%d  Phrase=G_%ls  alt=%d  count=%d\n",
                      Ph,              AST_type>>AST_type_shift,
                                                       AST_index,
                                                                         op,
                                                                                    phrasename_c[PHRASE+NUM_BIPS],
                                                                                  alt,      count);
  */

  int t[LARGEST_ALT];
  int r = 0;

  switch (PHRASE+NUM_BIPS) {
#include "imp77-switch.h"

   default:
     fprintf(stderr, "*** Switch entry %d not found.\n", op);
     return r;
  }
}
