/* pkl-trans.h - Transformation phases for the poke compiler.  */

/* Copyright (C) 2019, 2020, 2021, 2022, 2023 Jose E. Marchesi */

/* 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/>.
 */

#ifndef PKL_TRANS_H
#define PKL_TRANS_H

#include <config.h>
#include "pkl-pass.h"
#include "pkl-ast.h"

/* The trans phases keep a stack of function contexts while they
   operate on the AST.  At any time in the pass, the "current lexical
   function", and some properties relatives to it, are available to
   the trans phase handlers on the top of this stack.

   The following struct implements each entry on the function contexts
   stack.

   NODE is the AST node corresponding to the current lexical function,
   or NULL if not in a function.

   NDROPS is the number of PVM stack values we'd need to drop before
   returning from the current function.

   NPOPES is the number of PVM exception stack handlers that we'd need
   to pope before returning from the current function.

   BACK is the current lexical depth relative to the current
   function.  */

struct pkl_trans_function_ctx
{
  pkl_ast_node node;
  int ndrops;
  int npopes;
  int back;

  struct pkl_trans_function_ctx *next;
};

/* The trans phases keep a stack of escapable entities (loops and
   try-until statements) and the corresponding `break' and `continue'
   keywords, while they operate on the AST.

   The following struct implements each entry on the breakable/continuable
   entities stack.

   NODE is the escapable entity (loop or try-until statement).

   NFRAMES is the number of frames in the body of NODE.  */

struct pkl_trans_escapable_ctx
{
  pkl_ast_node node;
  int nframes;
};

/* The following struct defines the payload of the trans phases.

   ERRORS is the number of errors detected while running the phase.

   ADD_FRAMES is the number of frames to add to lexical addresses.
   This is used in transl.

   FUNCTIONS is a stack of function contexts.

   NEXT_FUNCTION - 1 is the index for the enclosing function in
   FUNCTIONS.  NEXT_FUNCTION is 0 if not in a function.

   ENDIAN is a stack whose top indicates the endianness to be used
   when mapping and writing integral types.

   CUR_ENDIAN is the index to ENDIAN and marks the top of the stack of
   endianness.  Initially PKL_AST_ENDIAN_DFL.

   ESCAPABLES is a stack of escapables.

   NEXT_ESCAPABLE - 1 is the index for the enclosing escapable
   entity.  */

#define PKL_TRANS_MAX_FUNCTION_NEST 32
#define PKL_TRANS_MAX_ENDIAN 25
#define PKL_TRANS_MAX_COMP_STMT_NEST 32

struct pkl_trans_payload
{
  int errors;
  int add_frames;
  struct pkl_trans_function_ctx functions[PKL_TRANS_MAX_FUNCTION_NEST];
  int next_function;
  enum pkl_ast_endian endian[PKL_TRANS_MAX_ENDIAN];
  int cur_endian;
  struct pkl_trans_escapable_ctx escapables[PKL_TRANS_MAX_COMP_STMT_NEST];
  int next_escapable;
};

typedef struct pkl_trans_payload *pkl_trans_payload;

extern struct pkl_phase pkl_phase_trans1;
extern struct pkl_phase pkl_phase_trans2;
extern struct pkl_phase pkl_phase_trans3;
extern struct pkl_phase pkl_phase_trans4;

static inline void
pkl_trans_init_payload (pkl_trans_payload payload)
{
  memset (payload, 0, sizeof (struct pkl_trans_payload));
  payload->endian[0] = PKL_AST_ENDIAN_DFL;
}

#endif /* PKL_TRANS_H */
