//! @file a68g-types.h
//! @author J. Marcel van der Veer

//! @section Copyright
//!
//! This file is part of Algol68G - an Algol 68 compiler-interpreter.
//! Copyright 2001-2025 J. Marcel van der Veer [algol68g@xs4all.nl].

//! @section License
//!
//! This program is free software; you can redistribute it and/or modify it 
//! under the terms of the GNU General Public License as published by the 
//! Free Software Foundation; either version 3 of the License, or 
//! (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful, but 
//! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
//! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
//! more details. You should have received a copy of the GNU General Public 
//! License along with this program. If not, see [http://www.gnu.org/licenses/].

//! @section Synopsis
//!
//! Internal type definitions.

#if !defined (__A68G_TYPES_H__)
#define __A68G_TYPES_H__

#include "a68g-nil.h"

// Type definitions

#define COMPLEX_T double complex

typedef unt char BYTE_T;
typedef BYTE_T *A68G_STRUCT;

typedef char BUFFER[BUFFER_SIZE + 1];
typedef int CHAR_T;
typedef int LEAP_T;
typedef MP_T A68G_LONG[DEFAULT_DOUBLE_DIGITS + 2];
typedef struct A68G_ARRAY A68G_ARRAY;
typedef struct A68G_BITS A68G_BITS;
typedef struct A68G_BOOL A68G_BOOL;
typedef struct A68G_BYTES A68G_BYTES;
typedef struct A68G_CHANNEL A68G_CHANNEL;
typedef struct A68G_CHAR A68G_CHAR;
typedef struct A68G_COLLITEM A68G_COLLITEM;
typedef struct A68G_FILE A68G_FILE;
typedef struct A68G_FORMAT A68G_FORMAT;
typedef struct A68G_HANDLE A68G_HANDLE;
typedef struct A68G_INT A68G_INT;
typedef struct A68G_LONG_BYTES A68G_LONG_BYTES;
typedef struct A68G_PROCEDURE A68G_PROCEDURE;
typedef struct A68G_REAL A68G_REAL;
typedef struct A68G_REF A68G_REF, A68G_ROW;
typedef struct A68G_SOUND A68G_SOUND;
typedef struct A68G_STREAM A68G_STREAM;
typedef struct A68G_TUPLE A68G_TUPLE;
typedef struct A68G_UNION A68G_UNION;
typedef struct ACTIVATION_RECORD ACTIVATION_RECORD;
typedef struct DEC_T DEC_T;
typedef struct DIAGNOSTIC_T DIAGNOSTIC_T;
typedef struct FILES_T FILES_T;
typedef struct GINFO_T GINFO_T;
typedef struct KEYWORD_T KEYWORD_T;
typedef struct LINE_T LINE_T;
typedef struct MODES_T MODES_T;
typedef struct MOID_T MOID_T;
typedef struct NODE_INFO_T NODE_INFO_T;
typedef struct OPTION_LIST_T OPTION_LIST_T;
typedef struct OPTIONS_T OPTIONS_T;
typedef struct PACK_T PACK_T;
typedef struct POSTULATE_T POSTULATE_T;
typedef struct PROP_T PROP_T;
typedef struct REFINEMENT_T REFINEMENT_T;
typedef struct SOID_T SOID_T;
typedef struct TABLE_T TABLE_T;
typedef struct TAG_T TAG_T;
typedef struct TOKEN_T TOKEN_T;
typedef unt FILE_T, MOOD_T;
typedef void GPROC (NODE_T *);

typedef PROP_T PROP_PROC (NODE_T *);

struct A68G_REAL
{
  STATUS_MASK_T status;
  REAL_T value;
} ALIGNED;

struct DEC_T
{
  char *text;
  DEC_T *sub, *less, *more;
  int level;
};

struct ACTIVATION_RECORD
{
  ADDR_T static_link, dynamic_link, dynamic_scope, parameters;
  BOOL_T proc_frame;
  int frame_no, frame_level, parameter_level;
  jmp_buf *jump_stat;
  NODE_T *node;
  #if defined (BUILD_PARALLEL_CLAUSE)
    pthread_t thread_id;
  #endif
};

struct PROP_T
{
  NODE_T *source;
  PROP_PROC *unit;
};

struct A68G_STREAM
{
  BOOL_T opened, writemood;
  char *name;
  FILE_T fd;
} ALIGNED;

struct DIAGNOSTIC_T
{
  char *text, *symbol;
  DIAGNOSTIC_T *next;
  int attribute, number;
  LINE_T *line;
  NODE_T *where;
};

struct FILES_T
{
  char *path, *initial_name, *generic_name;
  struct A68G_STREAM binary, diags, plugin, script, object, source, listing, pretty;
};

struct KEYWORD_T
{
  char *text;
  int attribute;
  KEYWORD_T *less, *more;
};

struct MODES_T
{
  MOID_T *BITS, *BOOL, *BYTES, *CHANNEL, *CHAR, *COLLITEM, *COMPL, *COMPLEX,
    *C_STRING, *ERROR, *FILE, *FORMAT, *HEX_NUMBER, *HIP, *INT, *LONG_BITS, *LONG_BYTES,
    *LONG_COMPL, *LONG_COMPLEX, *LONG_INT, *LONG_LONG_BITS, *LONG_LONG_COMPL,
    *LONG_LONG_COMPLEX, *LONG_LONG_INT, *LONG_LONG_REAL, *LONG_REAL, *NUMBER, *PIPE,
    *PROC_REAL_REAL, *PROC_LONG_REAL_LONG_REAL, *PROC_REF_FILE_BOOL, *PROC_REF_FILE_VOID, *PROC_ROW_CHAR,
    *PROC_STRING, *PROC_VOID, *REAL, *REF_BITS, *REF_BOOL, *REF_BYTES,
    *REF_CHAR, *REF_COMPL, *REF_COMPLEX, *REF_FILE, *REF_FORMAT, *REF_INT,
    *REF_LONG_BITS, *REF_LONG_BYTES, *REF_LONG_COMPL, *REF_LONG_COMPLEX,
    *REF_LONG_INT, *REF_LONG_LONG_BITS, *REF_LONG_LONG_COMPL,
    *REF_LONG_LONG_COMPLEX, *REF_LONG_LONG_INT, *REF_LONG_LONG_REAL, *REF_LONG_REAL, 
    *REF_PIPE, *REF_REAL, *REF_REF_FILE, *REF_ROW_CHAR, *REF_ROW_COMPLEX, *REF_ROW_INT, 
    *REF_ROW_REAL, *REF_ROW_ROW_COMPLEX, *REF_ROW_ROW_REAL, *REF_SOUND, *REF_STRING,
    *ROW_BITS, *ROW_BOOL, *ROW_CHAR, *ROW_COMPLEX, *ROW_INT, *ROW_LONG_BITS, *ROW_LONG_LONG_BITS, 
    *ROW_REAL, *ROW_ROW_CHAR, *ROW_ROW_COMPLEX, *ROW_ROW_REAL, *ROWS, *ROW_SIMPLIN, *ROW_SIMPLOUT, 
    *ROW_STRING, *SEMA, *SIMPLIN, *SIMPLOUT, *SOUND, *SOUND_DATA, *STRING, *FLEX_ROW_CHAR, 
    *FLEX_ROW_BOOL, *UNDEFINED, *VACUUM, *VOID;
};

struct OPTIONS_T
{
  BOOL_T backtrace, brackets, check_only, clock, compile, compile_check, conservative_gc, 
    cross_reference, debug, fold, keep, license, moid_listing, no_notices, no_warnings, object_listing, 
    portcheck, pragmat_sema, pretty, quiet, reductions, regression_test, restart, rerun, run, run_script, 
    source_listing, standard_prelude_listing, statistics_listing, strict, stropping, trace, 
    tree_listing, unused, verbose, version; 
  int time_limit, opt_level, indent;
  OPTION_LIST_T *list;
  STATUS_MASK_T nodemask;
};

struct MOID_T
{
  BOOL_T has_rows, use, portable, derivate;
  int attribute, dim, number, short_id;
  MOID_T *sub, *equivalent_mode, *slice, *deflexed_mode, *name, *multiple_mode, *next, *rowed, *trim;
  NODE_T *node;
  PACK_T *pack;
  size_t digits, size, digits_compl, size_compl;
};
#define NO_MOID ((MOID_T *) NULL)

struct NODE_T
{
  GINFO_T *genie;
  int number, attribute, annotation;
  MOID_T *type;
  NODE_INFO_T *info;
  NODE_T *next, *previous, *sub, *sequence, *nest;
  PACK_T *pack;
  STATUS_MASK_T status, codex;
  TABLE_T *symbol_table, *non_local;
  TAG_T *tag, *tag_gc;
};
#define NO_NODE ((NODE_T *) NULL)

struct NODE_INFO_T
{
  char *char_in_line, *symbol, *pragment, *expr;
  int procedure_level, priority, pragment_type;
  LINE_T *line;
};

struct GINFO_T
{
  BOOL_T is_coercion, is_new_lexical_level, need_dns;
  BYTE_T *offset;
  char *compile_name;
  int level, argsize, size, compile_node;
  MOID_T *partial_proc, *partial_locale;
  NODE_T *parent;
  PROP_T propagator;
  void *constant;
};

struct OPTION_LIST_T
{
  BOOL_T processed;
  char *str;
  int scan;
  LINE_T *line;
  OPTION_LIST_T *next;
};

struct PACK_T
{
  ADDR_T offset;
  char *text;
  MOID_T *type;
  NODE_T *node;
  PACK_T *next, *previous;
  size_t size;
};

struct POSTULATE_T
{
  MOID_T *a, *b;
  POSTULATE_T *next;
};

struct REFINEMENT_T
{
  char *name;
  int applications;
  LINE_T *line_defined, *line_applied;
  NODE_T *node_defined, *begin, *end;
  REFINEMENT_T *next;
};

struct SOID_T
{
  int attribute, sort, cast;
  MOID_T *type;
  NODE_T *node;
  SOID_T *next;
};

struct LINE_T
{
  BOOL_T list;
  char marker[6], *string, *filename;
  DIAGNOSTIC_T *diagnostics;
  int number, print_status;
  LINE_T *next, *previous;
};
#define NO_LINE ((LINE_T *) NULL)

struct TABLE_T
{
  ADDR_T ap_increment;
  BOOL_T initialise_frame, initialise_anon, proc_ops;
  int num, level, nest, attribute;
  NODE_T *jump_to, *sequence;
  TABLE_T *previous, *outer;
  TAG_T *identifiers, *operators, *priority, *indicants, *labels, *anonymous;
};
#define NO_TABLE ((TABLE_T *) NULL)

struct TAG_T
{
  STATUS_MASK_T status, codex;
  ADDR_T offset;
  BOOL_T scope_assigned, use, in_proc, a68g_standenv_proc, loc_assigned, portable;
  char *value;
  GPROC *procedure;
  int priority, heap, scope, youngest_environ, number;
  MOID_T *type;
  NODE_T *node, *unit;
  size_t size;
  TABLE_T *symbol_table;
  TAG_T *next, *body;
};
#define NO_TAG ((TAG_T *) NULL)

struct TOKEN_T
{
  char *text;
  TOKEN_T *less, *more;
};

//! @struct A68G_HANDLE
//! @brief Handle for REF into the HEAP.
//! @details
//! A REF into the HEAP points at a HANDLE.
//! The HANDLE points at the actual object in the HEAP.
//! Garbage collection modifies HANDLEs, but not REFs.

struct A68G_HANDLE
{
  STATUS_MASK_T status;
  A68G_HANDLE *next, *previous;
  BYTE_T *pointer;
  MOID_T *type;
  size_t size;
} ALIGNED;

static const A68G_HANDLE nil_handle = {INIT_MASK, NO_HANDLE, NO_HANDLE, NO_BYTE, NO_MOID, 0};

//! @struct A68G_REF
//! @brief Fat A68 pointer.
//! Records dynamic scope.

struct A68G_REF
{
  STATUS_MASK_T status;
  ADDR_T offset, scope;
  A68G_HANDLE *handle;
} ALIGNED;

static const A68G_REF nil_ref = {(STATUS_MASK_T) (INIT_MASK | NIL_MASK), 0, 0, NO_HANDLE};

//! @struct A68G_ARRAY
//! @brief A68 array descriptor. 
//! @details
//! A row is an A68G_REF to an A68G_ARRAY.
//! 
//! An A68G_ARRAY is followed by one A68G_TUPLE per dimension.
//! 
//! @verbatim
//! A68G_REF row -> A68G_ARRAY ----+   ARRAY: Description of row, ref to elements.
//!                A68G_TUPLE 1    |   TUPLE: Bounds, one for every dimension.
//!                ...             |
//!                A68G_TUPLE dim  |
//!                ...             |
//!                ...             |
//!                Element 1   <---+   Sequential row elements in the heap.
//!                ... 
//!                Element n
//! @endverbatim

struct A68G_ARRAY
{
  A68G_REF array;
  ADDR_T slice_offset, field_offset;
  int dim;
  size_t elem_size;
  MOID_T *type;
} ALIGNED;

struct A68G_BITS
{
  STATUS_MASK_T status;
  UNSIGNED_T value;
} ALIGNED;

struct A68G_BYTES
{
  STATUS_MASK_T status;
  char value[A68G_BYTES_WIDTH + 1];
} ALIGNED;

struct A68G_CHANNEL
{
  STATUS_MASK_T status;
  BOOL_T reset, set, get, put, bin, draw, compress;
} ALIGNED;

struct A68G_BOOL
{
  STATUS_MASK_T status;
  BOOL_T value;
} ALIGNED;

struct A68G_CHAR
{
  STATUS_MASK_T status;
  CHAR_T value;
} ALIGNED;

struct A68G_COLLITEM
{
  STATUS_MASK_T status;
  int count;
};

struct A68G_INT
{
  STATUS_MASK_T status;
  INT_T value;
} ALIGNED;

//! @struct A68G_FORMAT
//! @brief A68 format descriptor.
//! @details
//! A format behaves very much like a procedure.

struct A68G_FORMAT
{
  STATUS_MASK_T status;
  ADDR_T fp_environ; // Frame pointer to environ.
  NODE_T *body;      // Entry point in syntax tree.
} ALIGNED;

static const A68G_FORMAT nil_format = {INIT_MASK, 0, NULL};

struct A68G_LONG_BYTES
{
  STATUS_MASK_T status;
  char value[A68G_LONG_BYTES_WIDTH + 1];
} ALIGNED;

//! @struct A68G_PROCEDURE
//! @brief A68 procedure descriptor.

struct A68G_PROCEDURE
{
  STATUS_MASK_T status;
  A68G_HANDLE *locale; // Locale for partial parametrisation.
  ADDR_T fp_environ;   // Frame pointer to environ.
  MOID_T *type;
  union
  {
    NODE_T *node;
    GPROC *procedure;
  } body;             // Entry point in syntax tree or precompiled C procedure.
} ALIGNED;

typedef A68G_REAL A68G_COMPLEX[2];

//! @struct A68G_TUPLE
//! @brief A tuple containing bounds etcetera for one dimension.

struct A68G_TUPLE
{
  INT_T upper_bound, lower_bound, k;
  size_t shift, span;
} ALIGNED;

struct A68G_UNION
{
  STATUS_MASK_T status;
  void *value;
} ALIGNED;

struct A68G_SOUND
{
  STATUS_MASK_T status;
  INT_T num_channels, sample_rate, bits_per_sample, num_samples, data_size;
  A68G_REF data;
};

struct A68G_FILE
{
  STATUS_MASK_T status;
  A68G_CHANNEL channel;
  A68G_FORMAT format;
  A68G_PROCEDURE file_end_mended, page_end_mended, line_end_mended, value_error_mended, open_error_mended, transput_error_mended, format_end_mended, format_error_mended;
  A68G_REF identification, terminator, string;
  ADDR_T frame_pointer, stack_pointer;  // Since formats open frames
  BOOL_T read_mood, write_mood, char_mood, draw_mood, opened, append, open_exclusive, end_of_file, tmp_file;
  FILE_T fd;
  int transput_buffer, strpos, file_entry;
  struct
  {
    FILE *stream;
    #if defined (HAVE_GNU_PLOTUTILS)
      plPlotter *plotter;
      plPlotterParams *plotter_params;
    #endif
    BOOL_T device_made, device_opened;
    A68G_REF device, page_size;
    int device_handle /* deprecated */ , window_x_size, window_y_size;
    REAL_T x_coord, y_coord, red, green, blue;
  }
  device;
  #if defined (HAVE_POSTGRESQL)
    #if !defined (A68G_OPTIMISE)
      PGconn *connection;
      PGresult *result;
    #endif
  #endif
};

#define M_BITS (MODE (BITS))
#define M_BOOL (MODE (BOOL))
#define M_BYTES (MODE (BYTES))
#define M_CHANNEL (MODE (CHANNEL))
#define M_CHAR (MODE (CHAR))
#define M_COLLITEM (MODE (COLLITEM))
#define M_COMPLEX (MODE (COMPLEX))
#define M_COMPL (MODE (COMPL))
#define M_C_STRING (MODE (C_STRING))
#define M_ERROR (MODE (ERROR))
#define M_FILE (MODE (FILE))
#define M_FLEX_ROW_BOOL (MODE (FLEX_ROW_BOOL))
#define M_FLEX_ROW_CHAR (MODE (FLEX_ROW_CHAR))
#define M_FORMAT (MODE (FORMAT))
#define M_HEX_NUMBER (MODE (HEX_NUMBER))
#define M_HIP (MODE (HIP))
#define M_INT (MODE (INT))
#define M_LONG_BITS (MODE (LONG_BITS))
#define M_LONG_BYTES (MODE (LONG_BYTES))
#define M_LONG_COMPLEX (MODE (LONG_COMPLEX))
#define M_LONG_COMPL (MODE (LONG_COMPL))
#define M_LONG_INT (MODE (LONG_INT))
#define M_LONG_LONG_BITS (MODE (LONG_LONG_BITS))
#define M_LONG_LONG_COMPLEX (MODE (LONG_LONG_COMPLEX))
#define M_LONG_LONG_COMPL (MODE (LONG_LONG_COMPL))
#define M_LONG_LONG_INT (MODE (LONG_LONG_INT))
#define M_LONG_LONG_REAL (MODE (LONG_LONG_REAL))
#define M_LONG_REAL (MODE (LONG_REAL))
#define M_NIL (MODE (NIL))
#define M_NUMBER (MODE (NUMBER))
#define M_PIPE (MODE (PIPE))
#define M_PROC_LONG_REAL_LONG_REAL (MODE (PROC_LONG_REAL_LONG_REAL))
#define M_PROC_REAL_REAL (MODE (PROC_REAL_REAL))
#define M_PROC_REF_FILE_BOOL (MODE (PROC_REF_FILE_BOOL))
#define M_PROC_REF_FILE_VOID (MODE (PROC_REF_FILE_VOID))
#define M_PROC_ROW_CHAR (MODE (PROC_ROW_CHAR))
#define M_PROC_STRING (MODE (PROC_STRING))
#define M_PROC_VOID (MODE (PROC_VOID))
#define M_REAL (MODE (REAL))
#define M_REF_BITS (MODE (REF_BITS))
#define M_REF_BOOL (MODE (REF_BOOL))
#define M_REF_BYTES (MODE (REF_BYTES))
#define M_REF_CHAR (MODE (REF_CHAR))
#define M_REF_COMPLEX (MODE (REF_COMPLEX))
#define M_REF_COMPL (MODE (REF_COMPL))
#define M_REF_FILE (MODE (REF_FILE))
#define M_REF_FORMAT (MODE (REF_FORMAT))
#define M_REF_INT (MODE (REF_INT))
#define M_REF_LONG_BITS (MODE (REF_LONG_BITS))
#define M_REF_LONG_BYTES (MODE (REF_LONG_BYTES))
#define M_REF_LONG_COMPLEX (MODE (REF_LONG_COMPLEX))
#define M_REF_LONG_COMPL (MODE (REF_LONG_COMPL))
#define M_REF_LONG_INT (MODE (REF_LONG_INT))
#define M_REF_LONG_LONG_BITS (MODE (REF_LONG_LONG_BITS))
#define M_REF_LONG_LONG_COMPLEX (MODE (REF_LONG_LONG_COMPLEX))
#define M_REF_LONG_LONG_COMPL (MODE (REF_LONG_LONG_COMPL))
#define M_REF_LONG_LONG_INT (MODE (REF_LONG_LONG_INT))
#define M_REF_LONG_LONG_REAL (MODE (REF_LONG_LONG_REAL))
#define M_REF_LONG_REAL (MODE (REF_LONG_REAL))
#define M_REF_PIPE (MODE (REF_PIPE))
#define M_REF_REAL (MODE (REF_REAL))
#define M_REF_REF_FILE (MODE (REF_REF_FILE))
#define M_REF_ROW_CHAR (MODE (REF_ROW_CHAR))
#define M_REF_ROW_COMPLEX (MODE (REF_ROW_COMPLEX))
#define M_REF_ROW_INT (MODE (REF_ROW_INT))
#define M_REF_ROW_REAL (MODE (REF_ROW_REAL))
#define M_REF_ROW_ROW_COMPLEX (MODE (REF_ROW_ROW_COMPLEX))
#define M_REF_ROW_ROW_REAL (MODE (REF_ROW_ROW_REAL))
#define M_REF_SOUND (MODE (REF_SOUND))
#define M_REF_STRING (MODE (REF_STRING))
#define M_ROW_BITS (MODE (ROW_BITS))
#define M_ROW_BOOL (MODE (ROW_BOOL))
#define M_ROW_CHAR (MODE (ROW_CHAR))
#define M_ROW_COMPLEX (MODE (ROW_COMPLEX))
#define M_ROW_INT (MODE (ROW_INT))
#define M_ROW_LONG_BITS (MODE (ROW_LONG_BITS))
#define M_ROW_LONG_LONG_BITS (MODE (ROW_LONG_LONG_BITS))
#define M_ROW_REAL (MODE (ROW_REAL))
#define M_ROW_ROW_CHAR (MODE (ROW_ROW_CHAR))
#define M_ROW_ROW_COMPLEX (MODE (ROW_ROW_COMPLEX))
#define M_ROW_ROW_REAL (MODE (ROW_ROW_REAL))
#define M_ROW_SIMPLIN (MODE (ROW_SIMPLIN))
#define M_ROW_SIMPLOUT (MODE (ROW_SIMPLOUT))
#define M_ROWS (MODE (ROWS))
#define M_ROW_STRING (MODE (ROW_STRING))
#define M_SEMA (MODE (SEMA))
#define M_SIMPLIN (MODE (SIMPLIN))
#define M_SIMPLOUT (MODE (SIMPLOUT))
#define M_SOUND_DATA (MODE (SOUND_DATA))
#define M_SOUND (MODE (SOUND))
#define M_STRING (MODE (STRING))
#define M_UNDEFINED (MODE (UNDEFINED))
#define M_VACUUM (MODE (VACUUM))
#define M_VOID (MODE (VOID))

#endif
