"Fossies" - the Fresh Open Source Software Archive

Member "mlr-5.6.2/c/containers/local_stack.h" (25 Aug 2019, 9360 Bytes) of package /linux/misc/mlr-5.6.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "local_stack.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 5.2.2_vs_5.3.0.

    1 #ifndef LOCAL_STACK_H
    2 #define LOCAL_STACK_H
    3 
    4 #include "lib/mlrval.h"
    5 #include "containers/type_decl.h"
    6 #include "containers/sllv.h"
    7 #include "containers/mlhmmv.h"
    8 
    9 // ================================================================
   10 // Bound & scoped variables for use in for-loops, function bodies, and
   11 // subroutine bodies. Indices of local variables, and max-depth for top-level
   12 // statement blocks, are compted by the stack-allocator which marks up the AST
   13 // before the CST is built from it.
   14 //
   15 // A convention shared between the stack-allocator and this data structure is
   16 // that slot 0 is an absent-null which is used for reads of undefined (or
   17 // as-yet-undefined) local variables.
   18 //
   19 // Values assigned to a local-stack variable are owned by this container.
   20 // They will be freed:
   21 // * On overwrite, e.g. on 'x = oldval' then 'x = newval' the oldval
   22 //   will be freed on the newval assignment, and
   23 // * At stack-frame exit.
   24 // For this reason values assigned to locals may be passed in by reference
   25 // if they are ephemeral, i.e. if it is desired for this container to free
   26 // them. Otherwise, values should be copied before being passed in.
   27 // ================================================================
   28 
   29 // ================================================================
   30 typedef struct _local_stack_frame_entry_t {
   31     char* name; // For type-check error messages. Not strduped; the caller must ensure extent.
   32     mlhmmv_xvalue_t xvalue;
   33     int   type_mask;
   34 } local_stack_frame_entry_t;
   35 
   36 typedef struct _local_stack_frame_t {
   37     int in_use;
   38     int ephemeral;
   39     int size;
   40     int subframe_base;
   41     local_stack_frame_entry_t* pvars;
   42 } local_stack_frame_t;
   43 
   44 // ----------------------------------------------------------------
   45 // A stack is allocated for a top-level statement block: begin, end, or main, or
   46 // user-defined function/subroutine. (The latter two may be called recursively
   47 // in which case the in_use flag notes the need to allocate a new stack.)
   48 
   49 local_stack_frame_t* local_stack_frame_alloc(int size);
   50 void local_stack_frame_free(local_stack_frame_t* pframe);
   51 
   52 // ================================================================
   53 //#define LOCAL_STACK_TRACE_ENABLE
   54 //#define LOCAL_STACK_BOUNDS_CHECK_ENABLE
   55 
   56 void local_stack_bounds_check(local_stack_frame_t* pframe, char* op, int set, int vardef_frame_relative_index);
   57 #ifdef LOCAL_STACK_BOUNDS_CHECK_ENABLE
   58 #define LOCAL_STACK_BOUNDS_CHECK(pframe, op, set, vardef_frame_relative_index) \
   59     local_stack_bounds_check((pframe), (op), (set), (vardef_frame_relative_index))
   60 #else
   61 #define LOCAL_STACK_BOUNDS_CHECK(pframe, op, set, vardef_frame_relative_index)
   62 #endif
   63 
   64 #ifdef LOCAL_STACK_TRACE_ENABLE
   65 #define LOCAL_STACK_TRACE(p) p
   66 #else
   67 #define LOCAL_STACK_TRACE(p)
   68 #endif
   69 
   70 // These are unconditional. With the single added character 'X' they can be
   71 // used to focus verbosity at specific callsites for dev/debug.
   72 #define LOCAL_STACK_BOUNDS_CHECKX(pframe, op, set, vardef_frame_relative_index) \
   73     local_stack_bounds_check((pframe), (op), (set), (vardef_frame_relative_index))
   74 
   75 #define LOCAL_STACK_TRACEX(p) p
   76 
   77 // ----------------------------------------------------------------
   78 // Sets/clears the in-use flag for top-level statement blocks, and verifies the
   79 // contract for absent-null at slot 0.
   80 
   81 // For non-recursive functions/subroutines the enter method sets the in-use flag
   82 // and returns its argument; the exit method clears that flag. For recursively
   83 // invoked functions/subroutines the enter method returns another stack of the
   84 // same size, and the exit method frees that.
   85 //
   86 // The reason we don't simply always allocate is that begin/main/end statements
   87 // are never recursive, and most functions and subroutines are not recursive, so
   88 // most of the time there will be a single frame for each. We allocate that once
   89 // at startup, reuse it on every record, and free it at exit -- rather than
   90 // allocating and freeing frames on every record.
   91 
   92 local_stack_frame_t* local_stack_frame_enter(local_stack_frame_t* pframe);
   93 void local_stack_frame_exit(local_stack_frame_t* pframe);
   94 void local_stack_frame_throw_type_mismatch_for_write(local_stack_frame_entry_t* pentry, mv_t* pval);
   95 void local_stack_frame_throw_type_xmismatch_for_write(local_stack_frame_entry_t* pentry, mlhmmv_xvalue_t* pxval);
   96 void local_stack_frame_throw_type_mismatch_for_read(local_stack_frame_entry_t* pentry);
   97 void local_stack_frame_throw_type_xmismatch_for_read(local_stack_frame_entry_t* pentry);
   98 
   99 // ----------------------------------------------------------------
  100 static inline mv_t local_stack_frame_get_terminal_from_nonindexed(local_stack_frame_t* pframe, // move to reference semantics
  101     int vardef_frame_relative_index)
  102 {
  103     LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
  104     LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
  105     local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
  106     mlhmmv_xvalue_t* pvalue = &pentry->xvalue;
  107     if (pvalue != NULL && pvalue->is_terminal) {
  108         return pvalue->terminal_mlrval;
  109     } else {
  110         return mv_absent();
  111     }
  112 }
  113 
  114 // ----------------------------------------------------------------
  115 static inline void local_stack_frame_assign_terminal_nonindexed(local_stack_frame_t* pframe,
  116     int vardef_frame_relative_index, mv_t val)
  117 {
  118     LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p SET %d\n", pframe, vardef_frame_relative_index));
  119     LOCAL_STACK_BOUNDS_CHECK(pframe, "ASSIGN", TRUE, vardef_frame_relative_index);
  120     local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
  121 
  122     if (!(type_mask_from_mv(&val) & pentry->type_mask)) {
  123         local_stack_frame_throw_type_mismatch_for_write(pentry, &val);
  124     }
  125 
  126     mlhmmv_xvalue_free(&pentry->xvalue);
  127     pentry->xvalue = mlhmmv_xvalue_wrap_terminal(val); // xxx deep-copy?
  128 }
  129 
  130 // ----------------------------------------------------------------
  131 static inline mlhmmv_xvalue_t* local_stack_frame_ref_extended_from_nonindexed(local_stack_frame_t* pframe,
  132     int vardef_frame_relative_index)
  133 {
  134     LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p GET %d\n", pframe, vardef_frame_relative_index));
  135     LOCAL_STACK_BOUNDS_CHECK(pframe, "GET", FALSE, vardef_frame_relative_index);
  136 
  137     local_stack_frame_entry_t* pentry = &pframe->pvars[vardef_frame_relative_index];
  138     mlhmmv_xvalue_t* pmvalue = &pentry->xvalue;
  139 
  140     return pmvalue;
  141 }
  142 
  143 // ----------------------------------------------------------------
  144 mv_t local_stack_frame_ref_terminal_from_indexed(local_stack_frame_t* pframe,
  145     int vardef_frame_relative_index, sllmv_t* pmvkeys);
  146 
  147 mlhmmv_xvalue_t* local_stack_frame_ref_extended_from_indexed(local_stack_frame_t* pframe,
  148     int vardef_frame_relative_index, sllmv_t* pmvkeys);
  149 
  150 void local_stack_frame_define_terminal(local_stack_frame_t* pframe, char* variable_name,
  151     int vardef_frame_relative_index, int type_mask, mv_t val);
  152 
  153 void local_stack_frame_define_extended(local_stack_frame_t* pframe, char* variable_name,
  154     int vardef_frame_relative_index, int type_mask, mlhmmv_xvalue_t xval);
  155 
  156 void local_stack_frame_assign_extended_nonindexed(local_stack_frame_t* pframe,
  157     int vardef_frame_relative_index, mlhmmv_xvalue_t xval);
  158 
  159 void local_stack_frame_assign_terminal_indexed(local_stack_frame_t* pframe,
  160     int vardef_frame_relative_index, sllmv_t* pmvkeys,
  161     mv_t terminal_value);
  162 
  163 void local_stack_frame_assign_extended_indexed(local_stack_frame_t* pframe,
  164     int vardef_frame_relative_index, sllmv_t* pmvkeys,
  165     mlhmmv_xvalue_t terminal_value);
  166 
  167 // ----------------------------------------------------------------
  168 // Frames are entered/exited for each curly-braced statement block, including
  169 // the top-level block itself as well as ifs/fors/whiles.
  170 
  171 static inline void local_stack_subframe_enter(local_stack_frame_t* pframe, int count) {
  172     LOCAL_STACK_TRACE(printf("LOCAL STACK SUBFRAME %p ENTER %d->%d\n",
  173         pframe, pframe->subframe_base, pframe->subframe_base+count));
  174     local_stack_frame_entry_t* psubframe = &pframe->pvars[pframe->subframe_base];
  175     for (int i = 0; i < count; i++) {
  176         LOCAL_STACK_TRACE(printf("LOCAL STACK FRAME %p CLEAR %d\n", pframe, pframe->subframe_base+i));
  177         LOCAL_STACK_BOUNDS_CHECK(pframe, "CLEAR", FALSE, pframe->subframe_base+i);
  178         local_stack_frame_entry_t* pentry = &psubframe[i];
  179 
  180         mlhmmv_xvalue_reset(&pentry->xvalue);
  181 
  182         pentry->type_mask = TYPE_MASK_ANY;
  183     }
  184     pframe->subframe_base += count;
  185 }
  186 
  187 // ----------------------------------------------------------------
  188 static inline void local_stack_subframe_exit(local_stack_frame_t* pframe, int count) {
  189     LOCAL_STACK_TRACE(printf("LOCAL STACK SUBFRAME %p EXIT  %d->%d\n",
  190         pframe, pframe->subframe_base, pframe->subframe_base-count));
  191     pframe->subframe_base -= count;
  192     local_stack_frame_entry_t* psubframe = &pframe->pvars[pframe->subframe_base];
  193     for (int i = 0; i < count; i++) {
  194         local_stack_frame_entry_t* pentry = &psubframe[i];
  195         mlhmmv_xvalue_free(&pentry->xvalue);
  196     }
  197 }
  198 
  199 // ================================================================
  200 typedef struct _local_stack_t {
  201     sllv_t* pframes;
  202 } local_stack_t;
  203 
  204 local_stack_t* local_stack_alloc();
  205 void local_stack_free(local_stack_t* pstack);
  206 
  207 void local_stack_push(local_stack_t* pstack, local_stack_frame_t* pframe);
  208 
  209 local_stack_frame_t* local_stack_pop(local_stack_t* pstack);
  210 
  211 static inline local_stack_frame_t* local_stack_get_top_frame(local_stack_t* pstack) {
  212     return pstack->pframes->phead->pvvalue;
  213 }
  214 
  215 #endif // LOCAL_STACK_H