#ifndef __ICODE2ASTDATA_C__
#define __ICODE2ASTDATA_C__ 1

#include "icode2ast.h"

// These belong in a .h header file however because header files can be
// included in multiple files, doing so would cause multiple copies of
// these arrays, which is either a waste of space or an error.

const char *rcs_version = "icode2ast.h V$Revision: 1.15 $";

int DIAGNOSE;
int CONTROL;

// int blocklevel = 0;  // now local to every module.

int next_free_astid = -1;
IMPAST *astid[MAX_AST_ENTRIES];

int used[MAX_AST_ENTRIES];


/*

     !   OR            G   ALIAS         c   MCODE
     "   JUMPIFD       H   BEGIN         d   DIM
     #   BNE           I   unused        e   EVENT
     $   DEF           J   JUMP          f   FOR
     %   XOR           K   FALSE         g   unused
     &   AND           L   LABEL         h   ALTBEG
     '   PUSHS         M   MAP           i   INDEX
     (   unused        N   PUSHI         j   JAM
     )   unused        O   LINE          k   unused
     *   MUL           P   PLANT         l   LANG
     +   ADD           Q   DIVIDE        m   MONITOR
     -   SUB           R   RETURN        n   SELECT
     .   CONCAT        S   ASSVAL        o   ON
     /   QUOT          T   TRUE          p   ASSPAR
     :   LOCATE        U   NEGATE        q   SUBA  { was ALTEND }
     ;   END           V   RESULT        r   RESOLVE
     <   unused        W   SJUMP         s   STOP
     =   unused        X   IEXP          t   unused
     >   unused        Y   DEFAULT       u   ADDA
     ?   JUMPIF        Z   ASSREF        v   MOD
     @   PUSH          [   LSH           w   SUBA
     A   INIT          \   NOT           x   REXP
     B   REPEAT        ]   RSH           y   DIAG
     C   JUMPIFA       ^   PROC          z   CONTROL
     D   PUSHR         _   SLABEL        {   START
     E   CALL          a   ACCESS        |   ALT
     F   GOTO          b   BOUNDS        }   FINISH
 */
const char *icode_name[LAST_OP] = {

  // DEFSW is an added I-Code (actually a restored one, as this code existed in older compilers)
  // for the default switch label.  Imp77, by the time this pass1 was in use, had abandoned
  // an explicit code for this and was outputting all the missing labels explicitly, but
  // that scheme will not work for i2c.
  
  // New code 'REDEF' is identical to 'DEF' except that it is only for internal use by i2c
  // and should not cause any C to be output. (and may be removed in this reimplementation)
    
        "<0>",            "<1>",     "<2>",      "<3>",    "<4>",      "<5>",    "<6>",    "<7>",
        "<8>",            "<9>",     "EOF",     "<11>",   "<12>",     "<13>",   "<14>",   "<15>",
       "<16>",           "<17>",    "<18>",     "<19>",   "<20>",     "<21>",   "<22>",   "<23>",
       "<24>",           "<25>",    "<26>",     "<27>",   "<28>",     "<29>",   "<30>",   "<31>",
  //                          !          "           #         $           %         &         '
       "<32>",         "OR    ", "JUMPIFD",   "BNE   ", "DEF   ",   "XOR   ", "AND   ", "PUSHS ",
  //        (                 )          *           +         ,           -         .         /
     "BLE   ",         "BGE   ",  "MUL   ",   "ADD   ", "PLUS??",   "SUB   ", "CONCAT", "QUOT  ",
  //
      "<'0'>",          "<'1'>",   "<'2'>",    "<'3'>",  "<'4'>",    "<'5'>",  "<'6'>",  "<'7'>",
  //                                     :           ;         <           =         >         ?
      "<'8'>",          "<'9'>",  "LOCATE",   "END   ", "blt   ",   "beq   ", "bgt   ", "JUMPIF",
  //        @                 A          B           C         D           E         F         G
     "PUSH  ",         "INIT  ",  "REPEAT",  "JUMPIFA", "PUSHR ",   "CALL  ", "GOTO  ", "ALIAS ",
  //        H                 I          J           K         K           M         N         O
     "BEGIN ", "select-input-2",  "JUMP  ",   "FALSE ", "LABEL ",   "MAP   ", "PUSHI ", "LINE  ",
  //        P                 Q          R           S         T           U         V         W
     "PLANT ",         "DIVIDE",  "RETURN",   "ASSVAL", "TRUE  ",   "NEGATE", "RESULT", "SJUMP ",
  //        X                 Y           Z          [         \           ]         ^         _
     "IEXP  ",        "DEFAULT",  "ASSREF",   "LSH   ", "NOT   ",   "RSH   ", "PROC  ", "SLABEL",
  //        `                 a          b           c         d           e         f         g
     "DEFSW ",         "ACCESS",  "BOUNDS",   "MCODE1", "DIM   ",   "EVENT ", "FOR   ", "REDEF?",
  //        h                 i          j           k         l           m         n         o
     "ALTBEG",         "INDEX ",  "JAM   ",   "BF    ", "LANG  ",  "MONITOR", "SELECT", "ON    ",
  //        p                 q          r           a         t           u         v         w
     "ASSPAR",         "SUBA  "
                   /*"ALTEND"*/, "RESOLVE",   "STOP  ", "BT    ",   "ADDA  ", "MOD   ", "MCODE2",
  //        x                  y         z           {         |           }         ~
     "REXP  ",         "DIAG  ", "CONTROL", "START  (",  "ALT |", "FINISH )", "ALTALT",  "<127>",
        
  // ALTALT is an escape code which is followed by alternative encoding of START/ALT/FINISH
  // (this is in the original pass1 - not sure why the standard encoding was changed unless
  //  it was because PSR was running out of printable opcodes and needed some more for the
  //  extensions to I-Code needed when adding new languages?)
  
  // reserved for later versions of ICode.
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>",
  
  // After 255, the codes are higher-level extensions to the AST generated by us.
  
  // details of ast functionality not yet firmed up...
        
  "Perms  ",
  "RecFmSpec",
  "Deleted",
  "AddressOf", //     ASTOP_ADDRESS_OF,
  "Indirect",  //     ASTOP_INDIRECT_THROUGH,
  "Cast   ",   //     ASTOP_CAST
  "Brackets",  //     ASTOP_BRACKETS   // not yet used
  "Index  ",   //     ASTOP_ARRAYINDEX // not yet used (may add a field to BOUNDSPAIR instead!)
  "Param  ",   //     ASTOP_PARAM      // not yet used (may add a field to ASSPAR instead!)
};

const char *specialdesc[4] = {
  /*  0: */ "none",
  /*  1: */ "byte-integer",
  /*  2: */ "short-integer",
  /*  3: */ "long-real",
};

const char *impspecialdesc[4] = {
  /*  0: */ "",
  /*  1: */ "%byte ",
  /*  2: */ "%short ",
  /*  3: */ "%long ",
};

const char *cspecialdesc[4] = {
  /*  0: */ "",
  /*  1: */ "unsigned char ",
  /*  2: */ "short ",
  /*  3: */ "long ",
};

const char *cspecialdesc_integer[4] = {
  /*  0: */ "int ",
  /*  1: */ "unsigned char ",
  /*  2: */ "short int ",
  /*  3: */ "long int ",
};

const char *cspecialdesc_real[4] = {
  /*  0: */ "float ",
  /*  1: */ "",
  /*  2: */ "float ",
  /*  3: */ "double ",
};

const char *typedesc[16] = {
  /*  0: */ "<type:0>",
  /*  1: */ "integer",
  /*  2: */ "real",
  /*  3: */ "string",
  /*  4: */ "record",
  /*  5: */ "Boolean",
  /*  6: */ "set",
  /*  7: */ "byte-enumerated",
  /*  8: */ "short-enumerated",
  /*  9: */ "pointer",
  /* 10: */ "char",
  /* 11: */ "<type:11>",
  /* 12: */ "<type:12>",
  /* 13: */ "<type:13>",
  /* 14: */ "<type:14>",
  /* 15: */ "general-area"
};

const char *imptypedesc[16] = {
  /*  0: */ "",
  /*  1: */ "%integer ",
  /*  2: */ "%real ",
  /*  3: */ "%string ",
  /*  4: */ "%record ",
  /*  5: */ "",
  /*  6: */ "",
  /*  7: */ "",
  /*  8: */ "",
  /*  9: */ "",
  /* 10: */ "",
  /* 11: */ "",
  /* 12: */ "",
  /* 13: */ "",
  /* 14: */ "",
  /* 15: */ ""
};

const char *ctypedesc[16] = {  // not sure if some of these belong in form rather than type?
  /*  0: */ "_imp_name", // "void" would sort of work but would lose type info.
                         // Using a struct allows us to pass the type/size/form details,
                         // but requires special handling both when the %name is
                         // assigned and when it is used.
  /*  1: */ "",
  /*  2: */ "", //
  /*  3: */ "_imp_string", // meh. Multiple structs actually used for each length of string.
  /*  4: */ "struct ",   // I'm chosing not to use typedef in this re-implementation of i2c.
  /*  5: */ "",
  /*  6: */ "",
  /*  7: */ "",
  /*  8: */ "",
  /*  9: */ "",
  /* 10: */ "",
  /* 11: */ "",
  /* 12: */ "",
  /* 13: */ "",
  /* 14: */ "",
  /* 15: */ ""
};

const char *formdesc[16] = {
  /*  0: */ "<form:0>",
  /*  1: */ "simple",
  /*  2: */ "name",
  /*  3: */ "label",
  /*  4: */ "record-format",
  /*  5: */ "<form:5>",
  /*  6: */ "switch",
  /*  7: */ "routine",
  /*  8: */ "function",
  /*  9: */ "map",
  /* 10: */ "predicate",
  /* 11: */ "array",
  /* 12: */ "array-name",
  /* 13: */ "name-array",
  /* 14: */ "name-array-name",
  /* 15: */ "<form:15>",
};

const char *impformdesc[16] = {
  /*  0: */ "",
  /*  1: */ "",
  /*  2: */ "%name ",
  /*  3: */ "%label ",
  /*  4: */ "%recordformat ",
  /*  5: */ "",
  /*  6: */ "%switch ",
  /*  7: */ "%routine ",
  /*  8: */ "%function ",
  /*  9: */ "%map ",
  /* 10: */ "%predicate ",
  /* 11: */ "%array ",
  /* 12: */ "%arrayname ",
  /* 13: */ "%namearray ",
  /* 14: */ "%namearrayname ",
  /* 15: */ "",
};

const char *cformdesc[16] = {
  /*  0: */ "",
  /*  1: */ "",
  /*  2: */ " *",
  /*  3: */ "// __label__ /* block-scoped label (GCC) */ ",
                                                     // Unfortunately in GCC "__label__ FRED;" has to come before any
                                                     // executable code in the block, which can usually be arranged
                                                     // by the programmer, *except* in the case of the main program
                                                     // block, where I am inserting _imp_initialise() as the first
                                                     // statement after int main().  Fixable, but haven't done so yet,
                                                     // so test file jump.imp will fail.   *** TO DO ***
                                                     // A simple and cheap workaround is just to not declare the label!
  /*  4: */ "struct ",  // "typedef struct ",
  /*  5: */ "",
  /*  6: */ "void /*switch*/ *",
  /*  7: */ "void ",  // %routine
  /*  8: */ " ",      // %fn
  /*  9: */ " *",     // %map
  /* 10: */ "int ",   // Boolean %predicate
  /* 11: */ " ",
  /* 12: */ " *",
  /* 13: */ " *",
  /* 14: */ " *",
  /* 15: */ "",
};

const char *linkagedesc[] = {
  /*  0: */ "auto",
  /*  1: */ "own",
  /*  2: */ "constant",
  /*  3: */ "external",
  /*  4: */ "system",
  /*  5: */ "dynamic",
  /*  6: */ "prim",
  /*  7: */ "perm"
};

const char *implinkagedesc[] = {
  /*  0: */ "",
  /*  1: */ "%own ",
  /*  2: */ "%constant ",
  /*  3: */ "%external ",
  /*  4: */ "%system ",
  /*  5: */ "%dynamic ",
  /*  6: */ "%prim ",
  /*  7: */ "%perm "
};

const char *clinkagedesc[] = {
  /*  0: */ "",
  /*  1: */ "static ",
  /*  2: */ "const ",
  /*  3: */ "extern ",
  /*  4: */ "extern ",
  /*  5: */ "extern ",
  /*  6: */ "extern ",
  /*  7: */ "extern "
};

// ICode comparison codes, as used in JUMPIF etc.
const char *imp_value_comparision[128] = {
  ['='] = "=",
  ['#'] = "#", // ("!=" is allowed too)
  ['<'] = "<",
  ['>'] = ">",
  ['('] = "<=",
  [')'] = ">=",
};

const char *c_value_comparision[128] = {
  ['='] = "==",
  ['#'] = "!=",
  ['<'] = "<",
  ['>'] = ">",
  ['('] = "<=",
  [')'] = ">=",
};

const char *imp_name_comparision[128] = {
  ['='] = "==",
  ['#'] = "##",
};

const char *c_name_comparision[128] = {
  ['='] = "==",
  ['#'] = "!=",
};

//struct { int mask; char *name; } oflags[] = {
//    8,  "-spec",
//    16, "-indirect",
//    32, "-unass"
//};

#endif // !__ICODE2ASTDATA_C__
