#ifndef __ICODE2AST_H__
#define __ICODE2AST_H__ 1

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>

#ifndef FALSE
#define TRUE (0==0)
#define FALSE (0!=0)
#endif

typedef struct ICODE_OR            {  int opcode;  } ICODE_OR;
typedef struct ICODE_JUMPIFD       {
  int opcode;
  int cond, label;
} ICODE_JUMPIFD;
typedef struct ICODE_BNE           {  int opcode;  } ICODE_BNE;
typedef struct ICODE_DEF           {
  int opcode;
  int tag;
  char *id;
  int a, b, c;
} ICODE_DEF;
typedef struct ICODE_XOR           {  int opcode;  } ICODE_XOR;
typedef struct ICODE_AND           {  int opcode;  } ICODE_AND;
typedef struct ICODE_PUSHS         {
  int opcode;
  char *sconst;
} ICODE_PUSHS;
typedef struct ICODE_BLE           {  int opcode;  } ICODE_BLE;
typedef struct ICODE_BGE           {  int opcode;  } ICODE_BGE;
typedef struct ICODE_MUL           {  int opcode;  } ICODE_MUL;
typedef struct ICODE_ADD           {  int opcode;  } ICODE_ADD;
typedef struct ICODE_PLUS          {  int opcode;  } ICODE_PLUS;
typedef struct ICODE_SUB           {  int opcode;  } ICODE_SUB;
typedef struct ICODE_CONCAT        {  int opcode;  } ICODE_CONCAT;
typedef struct ICODE_QUOT          {  int opcode;  } ICODE_QUOT;
typedef struct ICODE_LOCATE        {
  int opcode;
  int label;
} ICODE_LOCATE;
typedef struct ICODE_END           {  int opcode;  } ICODE_END;
typedef struct ICODE_BLT           {  int opcode;  } ICODE_BLT;
typedef struct ICODE_BEQ           {  int opcode;  } ICODE_BEQ;
typedef struct ICODE_BGT           {  int opcode;  } ICODE_BGT;
typedef struct ICODE_JUMPIF        {
  int opcode;
  int cond, label;
} ICODE_JUMPIF;
typedef struct ICODE_PUSH          {
  int opcode;
  int tag;
} ICODE_PUSH;
typedef struct ICODE_INIT          {
  int opcode;
  int data;
} ICODE_INIT;
typedef struct ICODE_REPEAT        {
  int opcode;
  int label;
} ICODE_REPEAT;
typedef struct ICODE_JUMPIFA       {
  int opcode;
  int cond, label;
} ICODE_JUMPIFA;
typedef struct ICODE_PUSHR         {
  int opcode;
  int code, exponent;
  char *str;
} ICODE_PUSHR;
typedef struct ICODE_CALL          {  int opcode;  } ICODE_CALL;
typedef struct ICODE_GOTO          {
  int opcode;
  int label;
} ICODE_GOTO;
typedef struct ICODE_ALIAS         {
  int opcode;
  char *alias;
} ICODE_ALIAS;
typedef struct ICODE_BEGIN         {  int opcode;  } ICODE_BEGIN;
typedef struct ICODE_SELECTINPUT2  {  int opcode;  } ICODE_SELECTINPUT2;
typedef struct ICODE_JUMP          {
  int opcode;
  int label;
} ICODE_JUMP;
typedef struct ICODE_FALSE         {  int opcode;  } ICODE_FALSE;
typedef struct ICODE_LABEL         {
  int opcode;
  int label;
} ICODE_LABEL;
typedef struct ICODE_MAP           {  int opcode;  } ICODE_MAP;
typedef struct ICODE_PUSHI         {
  int opcode;
  int word32;
} ICODE_PUSHI;
typedef struct ICODE_LINE          {
  int opcode;
  int lineno;
  char *filename;
} ICODE_LINE;
typedef struct ICODE_PLANT         {  int opcode;  } ICODE_PLANT;
typedef struct ICODE_DIVIDE        {  int opcode;  } ICODE_DIVIDE;
typedef struct ICODE_RETURN        {  int opcode;  } ICODE_RETURN;
typedef struct ICODE_ASSVAL        {  int opcode;  } ICODE_ASSVAL;
typedef struct ICODE_TRUE          {  int opcode;  } ICODE_TRUE;
typedef struct ICODE_NEGATE        {  int opcode;  } ICODE_NEGATE;
typedef struct ICODE_RESULT        {  int opcode;  } ICODE_RESULT;
typedef struct ICODE_SJUMP         {
  int opcode;
  int label;
} ICODE_SJUMP;
typedef struct ICODE_IEXP          {  int opcode;  } ICODE_IEXP;
typedef struct ICODE_DEFAULT       {
  int opcode;
  int data;
} ICODE_DEFAULT;
typedef struct ICODE_ASSREF        {  int opcode;  } ICODE_ASSREF;
typedef struct ICODE_LSH           {  int opcode;  } ICODE_LSH;
typedef struct ICODE_NOT           {  int opcode;  } ICODE_NOT;
typedef struct ICODE_RSH           {  int opcode;  } ICODE_RSH;
typedef struct ICODE_PROC          {
  int opcode;
  int tag;
} ICODE_PROC;
typedef struct ICODE_SLABEL        {
  int opcode;
  int label;
} ICODE_SLABEL;
typedef struct ICODE_DEFSW         {
  int opcode;
  int label;
} ICODE_DEFSW;
typedef struct ICODE_ACCESS        {  int opcode;  } ICODE_ACCESS;
typedef struct ICODE_BOUNDS        {  int opcode;  } ICODE_BOUNDS;
typedef struct ICODE_MCODE1        {  int opcode;  } ICODE_MCODE1;
typedef struct ICODE_DIM           {
  int opcode;
  int dimens, arrays;
} ICODE_DIM;
typedef struct ICODE_EVENT         {
  int opcode;
  int data;
} ICODE_EVENT;
typedef struct ICODE_FOR           {
  int opcode;
  int label;
} ICODE_FOR;
typedef struct ICODE_REDEF         {  int opcode;  } ICODE_REDEF;
typedef struct ICODE_ALTBEG        {  int opcode;  } ICODE_ALTBEG;
typedef struct ICODE_INDEX         {  int opcode;  } ICODE_INDEX;
typedef struct ICODE_JAM           {  int opcode;  } ICODE_JAM;
typedef struct ICODE_BF            {
  int opcode;
  int label;
} ICODE_BF;
typedef struct ICODE_LANG          {
  int opcode;
  int language;
} ICODE_LANG;
typedef struct ICODE_MONITOR       {  int opcode;  } ICODE_MONITOR;
typedef struct ICODE_SELECT        {
  int opcode;
  int tag;
} ICODE_SELECT;
typedef struct ICODE_ON            {
  int opcode;
  int label, mask;
} ICODE_ON;
typedef struct ICODE_ASSPAR        {  int opcode;  } ICODE_ASSPAR;
typedef struct ICODE_SUBA          {  int opcode;  } ICODE_SUBA;
typedef struct ICODE_RESOLVE       {
  int opcode;
  int flags;
} ICODE_RESOLVE;
typedef struct ICODE_STOP          {  int opcode;  } ICODE_STOP;
typedef struct ICODE_BT            {
  int opcode;
  int label;
} ICODE_BT;
typedef struct ICODE_ADDA          {  int opcode;  } ICODE_ADDA;
typedef struct ICODE_MOD           {  int opcode;  } ICODE_MOD;
typedef struct ICODE_MCODE2        {  int opcode;  } ICODE_MCODE2;
typedef struct ICODE_REXP          {  int opcode;  } ICODE_REXP;
typedef struct ICODE_DIAG          {
  int opcode;
  int data;
} ICODE_DIAG;
typedef struct ICODE_CONTROL       {
  int opcode;
  int data;
} ICODE_CONTROL;
typedef struct ICODE_START         {  int opcode;  } ICODE_START;
typedef struct ICODE_ALT           {  int opcode;  } ICODE_ALT;
typedef struct ICODE_FINISH        {  int opcode;  } ICODE_FINISH;

typedef struct ICODE_ALTALT {
  int opcode;
  unsigned char alttype;
} ICODE_ALTALT;

typedef struct ICODE               {  int opcode;  } ICODE;

typedef struct IMPAST IMPAST;

typedef struct IAST_PERMS {
  int opcode;
  IMPAST *perms;
} IAST_PERMS;

typedef struct IMPAST {
  IMPAST *next_icode;
  union {
    int                 opcode;

    // The first group are all true ICodes:
    
    ICODE_OR            or;
    ICODE_JUMPIFD       jumpifd;
    ICODE_BNE           bne;
    ICODE_DEF           def;
    ICODE_XOR           xor;
    ICODE_AND           and;
    ICODE_PUSHS         pushs;
    ICODE_BLE           ble;
    ICODE_BGE           bge;
    ICODE_MUL           mul;
    ICODE_ADD           add;
    ICODE_PLUS          plus;
    ICODE_SUB           sub;
    ICODE_CONCAT        concat;
    ICODE_QUOT          quot;
    ICODE_LOCATE        locate;
    ICODE_END           end;
    ICODE_BLT           blt;
    ICODE_BEQ           beq;
    ICODE_BGT           bgt;
    ICODE_JUMPIF        jumpif;
    ICODE_PUSH          push;
    ICODE_INIT          init;
    ICODE_REPEAT        repeat;
    ICODE_JUMPIFA       jumpifa;
    ICODE_PUSHR         pushr;
    ICODE_CALL          call;
    ICODE_GOTO          igoto;
    ICODE_ALIAS         alias;
    ICODE_BEGIN         begin;
    ICODE_SELECTINPUT2  selectinput2;
    ICODE_JUMP          jump;
    ICODE_FALSE         ifalse;
    ICODE_LABEL         label;
    ICODE_MAP           map;
    ICODE_PUSHI         pushi;
    ICODE_LINE          line;
    ICODE_PLANT         plant;
    ICODE_DIVIDE        divide;
    ICODE_RETURN        ireturn;
    ICODE_ASSVAL        assval;
    ICODE_TRUE          itrue;
    ICODE_NEGATE        negate;
    ICODE_RESULT        result;
    ICODE_SJUMP         sjump;
    ICODE_IEXP          iexp;
    ICODE_DEFAULT       idefault;
    ICODE_ASSREF        assref;
    ICODE_LSH           lsh;
    ICODE_NOT           not;
    ICODE_RSH           rsh;
    ICODE_PROC          proc;
    ICODE_SLABEL        slabel;
    ICODE_DEFSW         defsw;
    ICODE_ACCESS        access;
    ICODE_BOUNDS        bounds;
    ICODE_MCODE1        mcode1;
    ICODE_DIM           dim;
    ICODE_EVENT         event;
    ICODE_FOR           ifor;
    ICODE_REDEF         redef;
    ICODE_ALTBEG        altbeg;
    ICODE_INDEX         index;
    ICODE_JAM           jam;
    ICODE_BF            bf;
    ICODE_LANG          lang;
    ICODE_MONITOR       monitor;
    ICODE_SELECT        select;
    ICODE_ON            on;
    ICODE_ASSPAR        asspar;
    ICODE_SUBA          suba;
    ICODE_RESOLVE       resolve;
    ICODE_STOP          stop;
    ICODE_BT            bt;
    ICODE_ADDA          adda;
    ICODE_MOD           mod;
    ICODE_MCODE2        mcode2;
    ICODE_REXP          rexp;
    ICODE_DIAG          diag;
    ICODE_CONTROL       control;
    ICODE_START         start;
    ICODE_ALT           alt;
    ICODE_FINISH        finish;
    ICODE_ALTALT        altalt;

    // From here down, not true icodes, but higher-level AST items
    // constructed by this code to make C generation easier.
    
    IAST_PERMS          perms;
  };
} IMPAST;

enum OP { // these *must* match the numeric order of icodes, starting at 0, no gaps
  OP_0,
  OP_1,
  OP_2,
  OP_3,
  OP_4,
  OP_5,
  OP_6,
  OP_7,
  OP_8,
  OP_9,
  OP_10,
  OP_11,
  OP_12,
  OP_13,
  OP_14,
  OP_15,
  OP_16,
  OP_17,
  OP_18,
  OP_19,
  OP_20,
  OP_21,
  OP_22,
  OP_23,
  OP_24,
  OP_25,
  OP_26,
  OP_27,
  OP_28,
  OP_29,
  OP_30,
  OP_31,
  OP_32,
  OP_OR,
  OP_JUMPIFD,
  OP_BNE,
  OP_DEF,
  OP_XOR,
  OP_AND,
  OP_PUSHS,
  OP_BLE,
  OP_BGE,
  OP_MUL,
  OP_ADD,
  OP_PLUS,
  OP_SUB,
  OP_CONCAT,
  OP_QUOT,
  OP_SYM0,
  OP_SYM1,
  OP_SYM2,
  OP_SYM3,
  OP_SYM4,
  OP_SYM5,
  OP_SYM6,
  OP_SYM7,
  OP_SYM8,
  OP_SYM9,
  OP_LOCATE,
  OP_END,
  OP_BLT,
  OP_BEQ,
  OP_BGT,
  OP_JUMPIF,
  OP_PUSH,
  OP_INIT,
  OP_REPEAT,
  OP_JUMPIFA,
  OP_PUSHR,
  OP_CALL,
  OP_GOTO,
  OP_ALIAS,
  OP_BEGIN,
  OP_SELECTINPUT2,
  OP_JUMP,
  OP_FALSE,
  OP_LABEL,
  OP_MAP,
  OP_PUSHI,
  OP_LINE,
  OP_PLANT,
  OP_DIVIDE,
  OP_RETURN,
  OP_ASSVAL,
  OP_TRUE,
  OP_NEGATE,
  OP_RESULT,
  OP_SJUMP,
  OP_IEXP,
  OP_DEFAULT,
  OP_ASSREF,
  OP_LSH,
  OP_NOT,
  OP_RSH,
  OP_PROC,
  OP_SLABEL,
  OP_DEFSW,
  OP_ACCESS,
  OP_BOUNDS,
  OP_MCODE1,
  OP_DIM,
  OP_EVENT,
  OP_FOR,

  OP_REDEF,
//#define OP_UNDEF 128
  // replacement for DEF in rewritten icode so that it is not output as C
  // This is for the procedure parameter procedure which is repeated inside
  // the procedure after the abbreviated version was in the FP list.
  // This rewrite puts the full version inside the parameter list as well
  // as following it: the first instance is for being output in C and
  // the second instance is for i2c to use when calling the passed procedure
  // inside the enclosing procedure.  So 'UNDEF' is an invisible 'DEF' -
  // handled exactly as DEF was before, but not printed out.

  OP_ALTBEG,
  OP_INDEX,
  OP_JAM,
  OP_BF,
  OP_LANG,
  OP_MONITOR,
  OP_SELECT,
  OP_ON,
  OP_ASSPAR,
  OP_SUBA,
  OP_RESOLVE,
  OP_STOP,
  OP_BT,
  OP_ADDA,
  OP_MOD,
  OP_MCODE2,
  OP_REXP,
  OP_DIAG,
  OP_CONTROL,
  OP_START,
  OP_ALT,
  OP_FINISH,
  OP_ALTALT,
  OP_127,

  // reserved for later versions of ICode:

  op_128, op_129, op_130, op_131, op_132, op_133, op_134, op_135,
  op_136, op_137, op_138, op_139, op_140, op_141, op_142, op_143,
  op_144, op_145, op_146, op_147, op_148, op_149, op_150, op_151,
  op_152, op_153, op_154, op_155, op_156, op_157, op_158, op_159,
  op_160, op_161, op_162, op_163, op_164, op_165, op_166, op_167,
  op_168, op_169, op_170, op_171, op_172, op_173, op_174, op_175,
  op_176, op_177, op_178, op_179, op_180, op_181, op_182, op_183,
  op_184, op_185, op_186, op_187, op_188, op_189, op_190, op_191,
  op_192, op_193, op_194, op_195, op_196, op_197, op_198, op_199,
  op_200, op_201, op_202, op_203, op_204, op_205, op_206, op_207,
  op_208, op_209, op_210, op_211, op_212, op_213, op_214, op_215,
  op_216, op_217, op_218, op_219, op_220, op_221, op_222, op_223,
  op_224, op_225, op_226, op_227, op_228, op_229, op_230, op_231,
  op_232, op_233, op_234, op_235, op_236, op_237, op_238, op_239,
  op_240, op_241, op_242, op_243, op_244, op_245, op_246, op_247,
  op_248, op_249, op_250, op_251, op_252, op_253, op_254, op_255,
  
  // From here down, these are pseudo-icodes for higher-level objects
  // constructed from the input ICodes.

  ASTOP_PERMS,

  // and a self-determining size of enumeration:
  LAST_OP
};

#define T_INTEGER 1
#define T_REAL 2
#define T_STRING 3
#define T_RECORD 4
#define T_BOOLEAN 5
#define T_SET 6
#define T_BYTE_ENUMERATED 7
#define T_SHORT_ENUMERATED 8
#define T_POINTER 9
#define T_CHAR 10
#define T_GENERAL 15

#define SPECIAL_DEFAULT 0
#define SPECIAL_BYTE_INT 1
#define SPECIAL_SHORT_INT 2
#define SPECIAL_LONG_REAL 3

#define F_RECORDFORMAT 4
#define F_ROUTINE 7
#define F_FN 8
#define F_MAP 9
#define F_PREDICATE 10

#define FORM (tf & 0xF)
#define IS_PROCEDURE ((FORM == F_ROUTINE) || (FORM == F_FN) || (FORM == F_MAP) || (FORM == F_PREDICATE))
#define IN_ENCLOSING_PROCEDURE (forms[next_free_form-1] != F_RECORDFORMAT)
#define IS_SPEC_ONLY (((ostate) & 8) != 0)
#define IS_INDIRECT (((ostate) & 16) != 0)
#define IS_UNASS (((ostate) & 32) != 0)

#define MAX_CHUNKS (16*1024)

/* Headers for icode2ast.c */
extern IMPAST *read_one_icode(void); 
extern IMPAST *load_icode_file(void); 
extern void dump_ast(IMPAST *icode, FILE *out);
#ifdef NEVER
extern int flagged_for_replacement(char *s); 
#endif

extern void push_spec(int spec); 
extern int pop_spec(void);

//extern int next_free_form;
//extern int forms[MAX_CHUNKS];
extern void push_form(int form); 
extern int pop_form(void);

#ifdef NEVER
extern void save_fn(int icode_idx, char *fname);
extern int get_fn(char *fname); 
#endif

/* End of headers for icode2ast.c */
#endif
