/**************************************************************************************
 * Chaga compiler                                                                     *
 * Copyright (C) 2026 Robert James Bruce                                              *
 *                                                                                    *
 * This file is part of the Chaga compiler.                                           *
 *                                                                                    *
 * The Chaga compiler 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.                                                                     *
 *                                                                                    *
 * The Chaga compiler 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 the Chaga compiler. If not, see <https://www.gnu.org/licenses/>.        *
 **************************************************************************************/
#include <sys/types.h>


#ifndef CHAGA_DATA_STRUCTURES
#define CHAGA_DATA_STRUCTURES 1
#endif




typedef struct token_node 
{
  char *token;                    // NULL terminated string
  int  token_type;                // describes the token 
  unsigned long long line_number; // this is the line number that the token came from. Line numbers are counted as newlines or "\n";
  struct token_node *next;
} token_node;




typedef struct string_node 
{
  char byte;
  struct string_node *next;
} string_node;




typedef struct binstr_node        // binary string
{
  unsigned char *binary_string;   // the contents of a binary string: note NULL bytes do NOT terminate a binary string. Use length to determine how many bytes to output.
  size_t binary_string_length;    // the length of the binary string (in bytes).
} binstr_node;




// ************************
// * Concrete Syntax Tree *
// ************************
typedef struct cst_node
{
  char            *token;
  int             token_type;
  unsigned char   cst_optimization_flags; // see comment below for the values
// **********************************************************************************************************************************************************************
// * cst_optimization flags:                                                                                                                                            *
// *                                                                                                                                                                    *
// * bit  0: TRUE: expression is an integer constant. Evaluate the expression at compile time and store as as constant. Example number = 123+234*99812/4321;            *
// * bit  2: UNUSED                                                                                                                                                     *
// * bit  3: UNUSED                                                                                                                                                     *
// * bit  4: UNUSED                                                                                                                                                     *
// * bit  5: UNUSED                                                                                                                                                     *
// * bit  6: UNUSED                                                                                                                                                     *
// * bit  7: UNUSED                                                                                                                                                     *
// * bit  8: UNUSED                                                                                                                                                     *
// **********************************************************************************************************************************************************************
  token_node      *token_entry;
//  token_node      *token_list;
  struct cst_node *sibling;
  struct cst_node *child;
} cst_node;




typedef enum chaga_attribute_type
{
  _function,
  _procedure,
  _datatype
} chaga_attribute_type;




typedef enum chaga_attribute_datatype
{
  _int,
  _bool,
  _char, 
  _date, 
  _file,
  _time,
  _void,
  _float,
  _string, 
  _complex,
  _pointer,
  _datetime,
  _attribute,
  _imaginary 
} chaga_attribute_datatype;




typedef enum chaga_statement_type
{
  _break,
  _case,
  _call,
  _default,
  _define,
  _declare,
  _do,
  _else,
  _for,
  _if,
  _print,
  _return,
  _set,
  _step,
  _switch,
  _then,
  _to,
  _while,
  _left_curly_brace,
  _right_curly_brace
} chaga_statement_type;




//********************************************************************************************************************************************
//* param_node is a linked list representing the datatypes passed in to a function or procedure AND datatypes returned from a function call. *
//********************************************************************************************************************************************
typedef struct param_node // param = parameter
{
  chaga_attribute_datatype datatype;
  char                     *identifier;
  struct param_node        *next;
} param_node;




// *********************************************************************************************************************************
// * symbol table node is a linked list holding all identifiers which represent the names of functions, procedures, and variables. *
// *********************************************************************************************************************************
typedef struct symtab_node
{
  char                     *identifier;             // This is the name of the variable (if it is a datatype), name of the function (if it is a function), or name of the procedure (if it is a procedure)
  chaga_attribute_type     attribute_type;          // This attribute describes what an identifier is defined as. Possible values are "FUNCTION", "PROCEDURE", or "DATATYPE".
  chaga_attribute_datatype datatype;                // This read-only attribute only applies to identifiers of type datatype. Possible values are: {bool, char, string, date, time, datetime, int, float, complex, imaginary, file, pointer}.
  param_node               *parameter_list;         // This attribute describes the canonical order of the datatypes passed in to a function or procedure. It only applies to identifiers of type "FUNCTION" or "PROCEDURE".
  param_node               *return_parameter_list;  // This attribute describes the canonical order of the datatypes returned from a function. It only applies to identifiers of type "FUNCTION".
  char                     num_array_dimensions;    // Number of dimensions in array. Possible values are 0, 1, 2, 3. A zero value means datatype is not an array.
  unsigned long long int   first_indice_size;       // If datatype is a single, double, or triple dimension array, the size of the first array dimension.
  unsigned long long int   second_indice_size;      // If datatype is a double or triple dimension array, the size of the second array dimension.
  unsigned long long int   third_indice_size;       // If datatype is a triple dimension array, the size of the third array dimension.
  unsigned long long int   scope_level;             // which scope does this datatype influence?
  int                      is_internal_use_only_variable;                      // TRUE if this variable is used internally by the compiler to evaluate expressions on-the-fly when no target variable is available to store the value. FALSE for all variables declared by the user.
  int                      internal_use_only_stores_string_number_constants;   // TRUE if this temporary variable is used internally by the compiler to hold string number constants 
  int                      internal_use_only_variable_is_available;            // TRUE if this internal-use-only variable is not storing any temporary data. FALSE if this varaible is currently unavailable for temporary use.
  struct symtab_node *next;
} symtab_node;




// ************************
// * Abstract Syntax Tree *
// ************************
typedef struct ast_node 
{
  chaga_statement_type  statement_type;      
  char                  *token;
  int                   token_type;                     // categorizes the token 
  token_node            *token_entry;
  symtab_node           *symbol_table_entry;
  int                   is_simple_assignment_statement; // Boolean value. TRUE: optimize the assembler output for simple assignment statements such as "set num1 = num2", "set num1 = -num2", or "set num1 = 123".
  struct ast_node       *sibling;
  struct ast_node       *child;
} ast_node;






// ****************************************************************************************************************************************
// * Library flags                                                                                                                        *
// *                                                                                                                                      *
// * This data structure holds a list of all Chaga extra library dependencies needed to assemble a the user's program.                    *
// *                                                                                                                                      *
// * Example 1: If a program uses int datatypes, the Chaga stringint library must be included. The stringint library has all the internal *
// * input / output routines to manipulate string-based integer datatypes.                                                                *
// *                                                                                                                                      *
// * Example 2: If a program uses bool datatype, the Chaga boolean library must be included. The boolean library has all the internal     *
// * input / output routines to read or display Boolean datatypes.                                                                        *
// ****************************************************************************************************************************************
typedef struct libflags
{
  unsigned char requires_boolean_library;
  unsigned char requires_stringint_library;
} libflags;





// ***********************************
// * Assembler output data structure *
// ***********************************
typedef struct asmblr_node 
{
  unsigned int            program_section;         // 1 = main program, 2 = subroutine A, 3 = subroutine B, 4 = subroutince C, etc. 
  ast_node                *abstract_syntax_tree;   // refers to the AST statement which is being converted to assembler output
  unsigned long long int  label;                   // this is a unique number to label this assembler section.
  unsigned char           *data_section_contents;  // Applicable to data sections only, this is the contents of the data section in hex bytes. It is NULL if not a data section.
  unsigned char           *code_section_contents;  // assembly instructions for for a general Chaga language statement. 
  struct asmblr_node      *next;
} asmblr_node;




// *******************************************************************************************************************
// * This structure cross-references symbol table entries with locations on the stack frame in the assembler output. *
// *******************************************************************************************************************
typedef struct stackframe_node 
{
  size_t                 stackframe_offset;        // this number refers to the offset relative to stack pointer for location of a given parameter (the same parameter cross-referenced in the symbol table.
  symtab_node            *symbol_table_entry;
  size_t                 storage_size_in_bytes;    // storage size to allocate this variable in a stack frame. Example: pointer datatype needs 8 bytes for storage (to store a 64-bit address).
  struct stackframe_node *next;
} stackframe_node;




// ********************************************************************************************************
// * This structure is used as a temporary storage space to convert infix notation expressions to postfix *
// * notation using Dijkstra's Shunting Yard algorithm. This structure is also used to evaluate numerical *
// *  expressions that are already in postfix notation.                                                   *
// ********************************************************************************************************
typedef struct expression_stack_node 
{
  char                         *token;
  int                          token_type;                     // categorizes the token 
  unsigned char                *temporary_variable_identifier; // Internal use only to manage temporary variables used for computation
  stackframe_node              *stackframe_table_entry;
  struct expression_stack_node *next;
} expression_stack_node;




// ******************************************************************************************************************************************************************************************
// * The statement_stack_node is useful for determining which statement block (encapsulated by curly-braces) is associated with which statement. The types of statements are listed below.  *
// * This data structure is necesssary to keep track of embedded statements within statements. For example, how would one know which IF-THEN statement is associated with a given ELSE      *
// * statement?                                                                                                                                                                             *
// *                                                                                                                                                                                        *
// * Hint: search the statement stack to find the last IF-THEN statement pushed on the stack.                                                                                               *
// ******************************************************************************************************************************************************************************************
typedef struct statement_stack_node
{
  chaga_statement_type   statement_type;      // The type of statement that encapsulates this statement block. 0 = DEFINE statement, 1 = IF-THEN statement, 2 = ELSE statement, 3 = SWITCH, 4 = FOR-DO, 5 = WHILE-DO, 6 = DO-UNTIL,  
  unsigned long long int left_curly_brace_count_before_this_statement;
  struct statement_stack_node *next;
} statement_stack_node;






