bind-stack allocation iterate: label statement blocks with frame-var count

This commit is contained in:
John Kerl 2016-10-07 14:42:25 -04:00
parent 25fcca6e24
commit 24ee024fc2
7 changed files with 326 additions and 448 deletions

View file

@ -49,7 +49,9 @@ libmapping_la_SOURCES= \
mappers.h \
mlr_dsl_cst.h \
mlr_dsl_cst.c \
mlr_dsl_cst_analyze.c \
mlr_dsl_cst_stack_allocate.c \
mlr_dsl_blocked_ast.c \
mlr_dsl_blocked_ast.h \
mlr_dsl_cst_func_subr.c \
mlr_dsl_cst_keywords.c \
mlr_dsl_cst_statements.c \

View file

@ -71,11 +71,11 @@ mlr_dsl_cst_t* mlr_dsl_cst_alloc(mlr_dsl_ast_t* past, int print_ast, int type_in
mlr_dsl_cst_t* pcst = mlr_malloc_or_die(sizeof(mlr_dsl_cst_t));
pcst->paast = analyzed_ast_alloc(past);
pcst->paast = blocked_ast_alloc(past);
// xxx temp
if (print_ast && getenv("MLR_BIND_STACK_ALLOC_DEV")) {
analyzed_ast_allocate_locals(pcst->paast);
blocked_ast_allocate_locals(pcst->paast);
}
pcst->pbegin_blocks = sllv_alloc();
@ -232,7 +232,7 @@ void mlr_dsl_cst_free(mlr_dsl_cst_t* pcst) {
lhmsv_free(pcst->psubr_defsites);
}
analyzed_ast_free(pcst->paast);
blocked_ast_free(pcst->paast);
free(pcst);
}

View file

@ -6,6 +6,7 @@
#include "containers/lhmsmv.h"
#include "containers/bind_stack.h"
#include "containers/loop_stack.h"
#include "mapping/mlr_dsl_blocked_ast.h"
#include "mapping/rval_evaluators.h"
#include "mapping/function_manager.h"
#include "output/multi_out.h"
@ -52,20 +53,8 @@
// ----------------------------------------------------------------
// xxx comment
typedef struct _analyzed_ast_t {
sllv_t* pfunc_defs;
sllv_t* psubr_defs;
sllv_t* pbegin_blocks;
mlr_dsl_ast_node_t* pmain_block;
sllv_t* pend_blocks;
} analyzed_ast_t;
// This strips nodes off the raw AST and transfers them to the analyzed AST.
analyzed_ast_t* analyzed_ast_alloc(mlr_dsl_ast_t* past);
void analyzed_ast_free(analyzed_ast_t* paast);
// xxx comment
void analyzed_ast_allocate_locals(analyzed_ast_t* paast);
// xxx move to own source&header
void blocked_ast_allocate_locals(blocked_ast_t* paast);
// ----------------------------------------------------------------
// Forward references for virtual-function prototypes
@ -239,7 +228,7 @@ typedef struct _mlr_dsl_cst_t {
// The CST object retains the AST pointer (in order to reuse its strings etc. with minimal copying)
// and will free the AST in the CST destructor.
analyzed_ast_t* paast;
blocked_ast_t* paast;
} mlr_dsl_cst_t;
// ----------------------------------------------------------------

View file

@ -1,76 +1,86 @@
#include <stdlib.h>
#include "lib/mlr_globals.h"
#include "lib/mlrutil.h"
#include "mlr_dsl_cst.h"
#include "context_flags.h"
#include "containers/free_flags.h"
#include "containers/lhmsi.h"
#include "mapping/mlr_dsl_blocked_ast.h"
#include "mapping/context_flags.h"
// ================================================================
// xxx make a summary comment here
// ================================================================
// ----------------------------------------------------------------
// xxx have ast freed back where it was (for callsite-balance) but w/ has-been-exfoliated comment
analyzed_ast_t* analyzed_ast_alloc(mlr_dsl_ast_t* past) {
analyzed_ast_t* paast = mlr_malloc_or_die(sizeof(analyzed_ast_t));
// xxx to do:
paast->pfunc_defs = sllv_alloc();
paast->psubr_defs = sllv_alloc();
paast->pbegin_blocks = sllv_alloc();
paast->pmain_block = mlr_dsl_ast_node_alloc_zary("main_block", MD_AST_NODE_TYPE_STATEMENT_BLOCK);
paast->pend_blocks = sllv_alloc();
// xxx put 'pass_1' and 'pass_2' in the function names
if (past->proot->type != MD_AST_NODE_TYPE_STATEMENT_BLOCK) {
fprintf(stderr, "%s: internal coding error detected in file %s at line %d:\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
fprintf(stderr,
"expected root node type %s but found %s.\n",
mlr_dsl_ast_node_describe_type(MD_AST_NODE_TYPE_STATEMENT_BLOCK),
mlr_dsl_ast_node_describe_type(past->proot->type));
exit(1);
}
// * maybe move ast from containers to mapping?
sllv_t* pnodelist = past->proot->pchildren;
while (pnodelist->phead) {
mlr_dsl_ast_node_t* pnode = sllv_pop(pnodelist);
switch (pnode->type) {
case MD_AST_NODE_TYPE_FUNC_DEF:
sllv_append(paast->pfunc_defs, pnode);
break;
case MD_AST_NODE_TYPE_SUBR_DEF:
sllv_append(paast->psubr_defs, pnode);
break;
case MD_AST_NODE_TYPE_BEGIN:
sllv_append(paast->pbegin_blocks, pnode);
break;
case MD_AST_NODE_TYPE_END:
sllv_append(paast->pend_blocks, pnode);
break;
default:
sllv_append(paast->pmain_block->pchildren, pnode);
break;
}
}
// * make a separate file for tree-reorg part into top-level blocks
return paast;
}
// * 'semantic analysis': use this to describe CST-build-time checks
// * 'object binding': use this to describe linking func/subr defs and callsites
// * separate verbosity for allocator? and invoke it in UT cases specific to this?
// -> (note allocation marks in the AST will be printed regardless)
// * nodestash:
// @ localvar: fridx & upcount; then frgridx
// @ statement block: frct; then maxdepth (default #def NONESUCH @ ctor; respect @ ast-node printer)
// pass 1:
// @localvar put fridx & upcount
// @exit from statement block put frct
// pass 2:
// @localvar map fridx & upcount to relidx (>=0 for in-frame, <0 for upframe)
// @base put maxdepth
// 1 frame_relative_index
// 1 upstack_frame_count
// 2 frame_var_count
// 2 recursive_max_var_count
// 2 absolute_index
// ================================================================
typedef struct _stkalc_frame_t {
long long index_count;
lhmsi_t* pnames_to_indices;
} stkalc_frame_t;
static stkalc_frame_t* stkalc_frame_alloc();
static void stkalc_frame_free(stkalc_frame_t* pframe);
static int stkalc_frame_has(stkalc_frame_t* pframe, char* name);
static int stkalc_frame_get(stkalc_frame_t* pframe, char* name);
static void stkalc_frame_add(stkalc_frame_t* pframe, char* desc, char* name, int depth, int verbose);
// ----------------------------------------------------------------
void analyzed_ast_free(analyzed_ast_t* paast) {
for (sllve_t* pe = paast->pfunc_defs->phead; pe != NULL; pe = pe->pnext)
mlr_dsl_ast_node_free(pe->pvvalue);
for (sllve_t* pe = paast->psubr_defs->phead; pe != NULL; pe = pe->pnext)
mlr_dsl_ast_node_free(pe->pvvalue);
for (sllve_t* pe = paast->pbegin_blocks->phead; pe != NULL; pe = pe->pnext)
mlr_dsl_ast_node_free(pe->pvvalue);
mlr_dsl_ast_node_free(paast->pmain_block);
for (sllve_t* pe = paast->pend_blocks->phead; pe != NULL; pe = pe->pnext)
mlr_dsl_ast_node_free(pe->pvvalue);
typedef struct _stkalc_frame_group_t {
sllv_t* plist;
} stkalc_frame_group_t;
sllv_free(paast->pfunc_defs);
sllv_free(paast->psubr_defs);
sllv_free(paast->pbegin_blocks);
sllv_free(paast->pend_blocks);
free(paast);
static stkalc_frame_group_t* stkalc_frame_group_alloc(stkalc_frame_t* pframe);
static void stkalc_frame_group_free(stkalc_frame_group_t* pframe_group);
static void stkalc_frame_group_push(stkalc_frame_group_t* pframe_group, stkalc_frame_t* pframe);
static stkalc_frame_t* stkalc_frame_group_pop(stkalc_frame_group_t* pframe_group);
}
static void stkalc_frame_group_mark_for_define(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
static void stkalc_frame_group_mark_for_write(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
static void stkalc_frame_group_mark_for_read(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_func_subr_block(mlr_dsl_ast_node_t* pnode);
static void blocked_ast_allocate_locals_for_begin_end_block(mlr_dsl_ast_node_t* pnode);
static void blocked_ast_allocate_locals_for_main_block(mlr_dsl_ast_node_t* pnode);
static void blocked_ast_allocate_locals_for_statement_block(mlr_dsl_ast_node_t* pnode,
stkalc_frame_group_t* pframe_group);
static void blocked_ast_allocate_locals_for_node(mlr_dsl_ast_node_t* pnode,
stkalc_frame_group_t* pframe_group);
// ================================================================
// xxx under construction
@ -157,169 +167,291 @@ void analyzed_ast_free(analyzed_ast_t* paast) {
// nothing to do here.
// ----------------------------------------------------------------
// func f(a,b) {
// return a+b;
// }
// subr s(n) {
// print n;
// }
// begin {
// local x = 1;
// }
// end {
// local z = 3;
// }
// local y = 2;
// ----------------------------------------------------------------
// xxx rename
void blocked_ast_allocate_locals(blocked_ast_t* paast) {
printf("\n"); // xxx temp
for (sllve_t* pe = paast->pfunc_defs->phead; pe != NULL; pe = pe->pnext) {
blocked_ast_allocate_locals_for_func_subr_block(pe->pvvalue);
}
for (sllve_t* pe = paast->psubr_defs->phead; pe != NULL; pe = pe->pnext) {
blocked_ast_allocate_locals_for_func_subr_block(pe->pvvalue);
}
for (sllve_t* pe = paast->pbegin_blocks->phead; pe != NULL; pe = pe->pnext) {
blocked_ast_allocate_locals_for_begin_end_block(pe->pvvalue);
}
blocked_ast_allocate_locals_for_main_block(paast->pmain_block);
for (sllve_t* pe = paast->pend_blocks->phead; pe != NULL; pe = pe->pnext) {
blocked_ast_allocate_locals_for_begin_end_block(pe->pvvalue);
}
}
// ANALYZED AST:
//
// FUNCTION DEFINITION:
// text="f", type=FUNC_DEF:
// text="f", type=NON_SIGIL_NAME:
// text="a", type=NON_SIGIL_NAME.
// text="b", type=NON_SIGIL_NAME.
// text="list", type=STATEMENT_BLOCK:
// text="return_value", type=RETURN_VALUE:
// text="+", type=OPERATOR:
// text="a", type=BOUND_VARIABLE.
// text="b", type=BOUND_VARIABLE.
//
// SUBROUTINE DEFINITION:
// text="s", type=SUBR_DEF:
// text="s", type=NON_SIGIL_NAME:
// text="n", type=NON_SIGIL_NAME.
// text="list", type=STATEMENT_BLOCK:
// text="print", type=PRINT:
// text="n", type=BOUND_VARIABLE.
// text=">", type=FILE_WRITE:
// text="stdout", type=STDOUT:
//
// BEGIN-BLOCK:
// text="begin", type=BEGIN:
// text="list", type=STATEMENT_BLOCK:
// text="local", type=LOCAL:
// text="x", type=BOUND_VARIABLE.
// text="1", type=STRNUM_LITERAL.
//
// END-BLOCK:
// text="end", type=END:
// text="list", type=STATEMENT_BLOCK:
// text="local", type=LOCAL:
// text="z", type=BOUND_VARIABLE.
// text="3", type=STRNUM_LITERAL.
//
// MAIN BLOCK:
// text="main_block", type=STATEMENT_BLOCK:
// text="local", type=LOCAL:
// text="y", type=BOUND_VARIABLE.
// text="2", type=STRNUM_LITERAL.
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_func_subr_block(mlr_dsl_ast_node_t* pnode) {
// xxx make a keystroke-saver, use it here, & use it from the cst builder as well
if (pnode->type != MD_AST_NODE_TYPE_SUBR_DEF && pnode->type != MD_AST_NODE_TYPE_FUNC_DEF) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
// xxx assert two children of desired type
stkalc_frame_t* pframe = stkalc_frame_alloc();
stkalc_frame_group_t* pframe_group = stkalc_frame_group_alloc(pframe);
printf("\n");
printf("ALLOCATING LOCALS FOR DEFINITION BLOCK [%s]\n", pnode->text);
mlr_dsl_ast_node_t* pdef_name_node = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* plist_node = pnode->pchildren->phead->pnext->pvvalue;
for (sllve_t* pe = pdef_name_node->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pparameter_node = pe->pvvalue;
stkalc_frame_group_mark_for_define(pframe_group, pparameter_node, "PARAMETER", TRUE/*xxx temp*/);
}
blocked_ast_allocate_locals_for_statement_block(plist_node, pframe_group);
pnode->frame_var_count = pframe->index_count;
printf("BLK %s frct=%d\n", pnode->text, pnode->frame_var_count);
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
stkalc_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_begin_end_block(mlr_dsl_ast_node_t* pnode) {
if (pnode->type != MD_AST_NODE_TYPE_BEGIN && pnode->type != MD_AST_NODE_TYPE_END) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
printf("\n");
printf("ALLOCATING LOCALS FOR %s BLOCK\n", pnode->text);
stkalc_frame_t* pframe = stkalc_frame_alloc();
stkalc_frame_group_t* pframe_group = stkalc_frame_group_alloc(pframe);
blocked_ast_allocate_locals_for_statement_block(pnode->pchildren->phead->pvvalue, pframe_group);
pnode->frame_var_count = pframe->index_count;
printf("BLK %s frct=%d\n", pnode->text, pnode->frame_var_count); // xxx fix name
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
stkalc_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_main_block(mlr_dsl_ast_node_t* pnode) {
// xxx assert node type
printf("\n");
printf("ALLOCATING LOCALS FOR MAIN BLOCK\n");
// xxx make this a one-liner
stkalc_frame_t* pframe = stkalc_frame_alloc();
stkalc_frame_group_t* pframe_group = stkalc_frame_group_alloc(pframe);
blocked_ast_allocate_locals_for_statement_block(pnode, pframe_group);
pnode->frame_var_count = pframe->index_count;
printf("BLK %s frct=%d\n", pnode->text, pnode->frame_var_count); // xxx fix name
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
stkalc_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_statement_block(mlr_dsl_ast_node_t* pnode,
stkalc_frame_group_t* pframe_group)
{
if (pnode->type != MD_AST_NODE_TYPE_STATEMENT_BLOCK) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
blocked_ast_allocate_locals_for_node(pchild, pframe_group);
}
}
// ----------------------------------------------------------------
static void blocked_ast_allocate_locals_for_node(mlr_dsl_ast_node_t* pnode,
stkalc_frame_group_t* pframe_group)
{
// xxx make separate functions
if (pnode->type == MD_AST_NODE_TYPE_FOR_SREC) { // xxx comment
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pnode->text);
stkalc_frame_t* pnext_frame = stkalc_frame_alloc();
stkalc_frame_group_push(pframe_group, pnext_frame);
mlr_dsl_ast_node_t* pvarsnode = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pblocknode = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pknode = pvarsnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pvnode = pvarsnode->pchildren->phead->pnext->pvvalue;
stkalc_frame_group_mark_for_define(pframe_group, pknode, "FOR-BIND", TRUE/*xxx temp*/);
stkalc_frame_group_mark_for_define(pframe_group, pvnode, "FOR-BIND", TRUE/*xxx temp*/);
blocked_ast_allocate_locals_for_statement_block(pblocknode, pframe_group);
pblocknode->frame_var_count = pnext_frame->index_count;
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s frct=%d\n", pnode->text, pblocknode->frame_var_count);
} else if (pnode->type == MD_AST_NODE_TYPE_FOR_OOSVAR) { // xxx comment
mlr_dsl_ast_node_t* pvarsnode = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pkeylistnode = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pblocknode = pnode->pchildren->phead->pnext->pnext->pvvalue;
mlr_dsl_ast_node_t* pkeysnode = pvarsnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pvalnode = pvarsnode->pchildren->phead->pnext->pvvalue;
// xxx note keylistnode is outside the block binding. in particular if there are any localvar reads
// in there they shouldn't read from forloop boundvars.
for (sllve_t* pe = pkeylistnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
blocked_ast_allocate_locals_for_node(pchild, pframe_group);
}
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pnode->text);
stkalc_frame_t* pnext_frame = stkalc_frame_alloc();
stkalc_frame_group_push(pframe_group, pnext_frame);
for (sllve_t* pe = pkeysnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
stkalc_frame_group_mark_for_define(pframe_group, pkeynode, "FOR-BIND", TRUE/*xxx temp*/);
}
stkalc_frame_group_mark_for_define(pframe_group, pvalnode, "FOR-BIND", TRUE/*xxx temp*/);
blocked_ast_allocate_locals_for_statement_block(pblocknode, pframe_group);
// xxx make accessor ...
pblocknode->frame_var_count = pnext_frame->index_count;
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s frct=%d\n", pnode->text, pblocknode->frame_var_count);
} else if (pnode->type == MD_AST_NODE_TYPE_LOCAL_DEFINITION) {
// xxx decide on preorder vs. postorder
mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pvvalue;
stkalc_frame_group_mark_for_define(pframe_group, pnamenode, "DEFINE", TRUE/*xxx temp*/);
mlr_dsl_ast_node_t* pvaluenode = pnode->pchildren->phead->pnext->pvvalue;
blocked_ast_allocate_locals_for_node(pvaluenode, pframe_group);
} else if (pnode->type == MD_AST_NODE_TYPE_LOCAL_ASSIGNMENT) { // xxx rename
mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pvvalue;
stkalc_frame_group_mark_for_write(pframe_group, pnamenode, "WRITE", TRUE/*xxx temp*/);
mlr_dsl_ast_node_t* pvaluenode = pnode->pchildren->phead->pnext->pvvalue;
blocked_ast_allocate_locals_for_node(pvaluenode, pframe_group);
} else if (pnode->type == MD_AST_NODE_TYPE_BOUND_VARIABLE) {
stkalc_frame_group_mark_for_read(pframe_group, pnode, "READ", TRUE/*xxx temp*/);
} else if (pnode->pchildren != NULL) {
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
if (pchild->type == MD_AST_NODE_TYPE_STATEMENT_BLOCK) {
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pchild->text);
stkalc_frame_t* pnext_frame = stkalc_frame_alloc();
stkalc_frame_group_push(pframe_group, pnext_frame);
blocked_ast_allocate_locals_for_statement_block(pchild, pframe_group);
pchild->frame_var_count = pnext_frame->index_count;
stkalc_frame_free(stkalc_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s frct=%d\n", pnode->text, pchild->frame_var_count);
} else {
blocked_ast_allocate_locals_for_node(pchild, pframe_group);
}
}
}
}
// ================================================================
// xxx move to separate file
// xxx analysis -> stack_allocation; saf & safg acronyms
// xxx put 'pass_1' and 'pass_2' in the function names
// ================================================================
typedef struct _analysis_frame_t {
long long index_count;
lhmsi_t* pnames_to_indices;
} analysis_frame_t;
static analysis_frame_t* analysis_frame_alloc();
static void analysis_frame_free(analysis_frame_t* pframe);
static int analysis_frame_has(analysis_frame_t* pframe, char* name);
static int analysis_frame_get(analysis_frame_t* pframe, char* name);
static void analysis_frame_add(analysis_frame_t* pframe, char* desc, char* name, int depth, int verbose);
static analysis_frame_t* analysis_frame_alloc() {
analysis_frame_t* pframe = mlr_malloc_or_die(sizeof(analysis_frame_t));
static stkalc_frame_t* stkalc_frame_alloc() {
stkalc_frame_t* pframe = mlr_malloc_or_die(sizeof(stkalc_frame_t));
pframe->index_count = 0;
pframe->pnames_to_indices = lhmsi_alloc();
return pframe;
}
static void analysis_frame_free(analysis_frame_t* pframe) {
static void stkalc_frame_free(stkalc_frame_t* pframe) {
if (pframe == NULL)
return;
lhmsi_free(pframe->pnames_to_indices);
free(pframe);
}
static int analysis_frame_has(analysis_frame_t* pframe, char* name) {
static int stkalc_frame_has(stkalc_frame_t* pframe, char* name) {
return lhmsi_has_key(pframe->pnames_to_indices, name);
}
static int analysis_frame_get(analysis_frame_t* pframe, char* name) {
static int stkalc_frame_get(stkalc_frame_t* pframe, char* name) {
return lhmsi_get(pframe->pnames_to_indices, name);
}
static void analysis_frame_add(analysis_frame_t* pframe, char* desc, char* name, int depth, int verbose) {
static void stkalc_frame_add(stkalc_frame_t* pframe, char* desc, char* name, int depth, int verbose) {
lhmsi_put(pframe->pnames_to_indices, name, pframe->index_count, NO_FREE);
pframe->index_count++;
}
// ================================================================
typedef struct _analysis_frame_group_t {
sllv_t* plist;
} analysis_frame_group_t;
static analysis_frame_group_t* analysis_frame_group_alloc(analysis_frame_t* pframe);
static void analysis_frame_group_free(analysis_frame_group_t* pframe_group);
static void analysis_frame_group_push(analysis_frame_group_t* pframe_group, analysis_frame_t* pframe);
static analysis_frame_t* analysis_frame_group_pop(analysis_frame_group_t* pframe_group);
// xxx shorten names by a lot -- e.g. "af_" and "afg_".
static void analysis_frame_group_mark_for_define(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
static void analysis_frame_group_mark_for_write(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
static void analysis_frame_group_mark_for_read(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose);
static analysis_frame_group_t* analysis_frame_group_alloc(analysis_frame_t* pframe) {
analysis_frame_group_t* pframe_group = mlr_malloc_or_die(sizeof(analysis_frame_group_t));
static stkalc_frame_group_t* stkalc_frame_group_alloc(stkalc_frame_t* pframe) {
stkalc_frame_group_t* pframe_group = mlr_malloc_or_die(sizeof(stkalc_frame_group_t));
pframe_group->plist = sllv_alloc();
sllv_prepend(pframe_group->plist, pframe);
return pframe_group;
}
static void analysis_frame_group_free(analysis_frame_group_t* pframe_group) {
static void stkalc_frame_group_free(stkalc_frame_group_t* pframe_group) {
if (pframe_group == NULL)
return;
while (pframe_group->plist->phead != NULL) {
analysis_frame_free(sllv_pop(pframe_group->plist));
stkalc_frame_free(sllv_pop(pframe_group->plist));
}
sllv_free(pframe_group->plist);
free(pframe_group);
}
static void analysis_frame_group_push(analysis_frame_group_t* pframe_group, analysis_frame_t* pframe) {
static void stkalc_frame_group_push(stkalc_frame_group_t* pframe_group, stkalc_frame_t* pframe) {
sllv_prepend(pframe_group->plist, pframe);
}
static analysis_frame_t* analysis_frame_group_pop(analysis_frame_group_t* pframe_group) {
static stkalc_frame_t* stkalc_frame_group_pop(stkalc_frame_group_t* pframe_group) {
return sllv_pop(pframe_group->plist);
}
static void analysis_frame_group_mark_for_define(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
static void stkalc_frame_group_mark_for_define(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose)
{
char* op = "REUSE";
analysis_frame_t* pframe = pframe_group->plist->phead->pvvalue;
if (!analysis_frame_has(pframe, pnode->text)) {
analysis_frame_add(pframe, desc, pnode->text, pframe_group->plist->length, verbose);
stkalc_frame_t* pframe = pframe_group->plist->phead->pvvalue;
if (!stkalc_frame_has(pframe, pnode->text)) {
stkalc_frame_add(pframe, desc, pnode->text, pframe_group->plist->length, verbose);
op = "ADD";
}
pnode->upstack_frame_count = 0;
pnode->frame_relative_index = analysis_frame_get(pframe, pnode->text);
pnode->frame_relative_index = stkalc_frame_get(pframe, pnode->text);
if (verbose) {
for (int i = 1; i < pframe_group->plist->length; i++) {
printf(":: ");
@ -329,7 +461,7 @@ static void analysis_frame_group_mark_for_define(analysis_frame_group_t* pframe_
}
}
static void analysis_frame_group_mark_for_write(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
static void stkalc_frame_group_mark_for_write(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose)
{
char* op = "REUSE";
@ -337,18 +469,18 @@ static void analysis_frame_group_mark_for_write(analysis_frame_group_t* pframe_g
// xxx loop. if not found, fall back to top frame.
pnode->upstack_frame_count = 0;
for (sllve_t* pe = pframe_group->plist->phead; pe != NULL; pe = pe->pnext, pnode->upstack_frame_count++) {
analysis_frame_t* pframe = pe->pvvalue;
if (analysis_frame_has(pframe, pnode->text)) {
stkalc_frame_t* pframe = pe->pvvalue;
if (stkalc_frame_has(pframe, pnode->text)) {
found = TRUE; // xxx dup
pnode->frame_relative_index = analysis_frame_get(pframe, pnode->text);
pnode->frame_relative_index = stkalc_frame_get(pframe, pnode->text);
break;
}
}
if (!found) {
pnode->upstack_frame_count = 0;
analysis_frame_t* pframe = pframe_group->plist->phead->pvvalue;
analysis_frame_add(pframe, desc, pnode->text, pnode->upstack_frame_count, verbose);
stkalc_frame_t* pframe = pframe_group->plist->phead->pvvalue;
stkalc_frame_add(pframe, desc, pnode->text, pnode->upstack_frame_count, verbose);
// xxx temp
pnode->frame_relative_index = pframe->index_count;
op = "ADD";
@ -363,17 +495,17 @@ static void analysis_frame_group_mark_for_write(analysis_frame_group_t* pframe_g
}
}
static void analysis_frame_group_mark_for_read(analysis_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
static void stkalc_frame_group_mark_for_read(stkalc_frame_group_t* pframe_group, mlr_dsl_ast_node_t* pnode,
char* desc, int verbose)
{
int found = FALSE;
// xxx loop. if not found, fall back to top frame.
pnode->upstack_frame_count = 0;
for (sllve_t* pe = pframe_group->plist->phead; pe != NULL; pe = pe->pnext, pnode->upstack_frame_count++) {
analysis_frame_t* pframe = pe->pvvalue;
if (analysis_frame_has(pframe, pnode->text)) {
stkalc_frame_t* pframe = pe->pvvalue;
if (stkalc_frame_has(pframe, pnode->text)) {
found = TRUE; // xxx dup
pnode->frame_relative_index = analysis_frame_get(pframe, pnode->text);
pnode->frame_relative_index = stkalc_frame_get(pframe, pnode->text);
break;
}
}
@ -394,248 +526,3 @@ static void analysis_frame_group_mark_for_read(analysis_frame_group_t* pframe_gr
}
}
}
// ================================================================
static void analyzed_ast_allocate_locals_for_func_subr_block(mlr_dsl_ast_node_t* pnode);
static void analyzed_ast_allocate_locals_for_begin_end_block(mlr_dsl_ast_node_t* pnode);
static void analyzed_ast_allocate_locals_for_main_block(mlr_dsl_ast_node_t* pnode);
static void analyzed_ast_allocate_locals_for_statement_block(mlr_dsl_ast_node_t* pnode,
analysis_frame_group_t* pframe_group);
static void analyzed_ast_allocate_locals_for_node(mlr_dsl_ast_node_t* pnode,
analysis_frame_group_t* pframe_group);
// ----------------------------------------------------------------
void analyzed_ast_allocate_locals(analyzed_ast_t* paast) {
printf("\n"); // xxx temp
for (sllve_t* pe = paast->pfunc_defs->phead; pe != NULL; pe = pe->pnext) {
analyzed_ast_allocate_locals_for_func_subr_block(pe->pvvalue);
}
for (sllve_t* pe = paast->psubr_defs->phead; pe != NULL; pe = pe->pnext) {
analyzed_ast_allocate_locals_for_func_subr_block(pe->pvvalue);
}
for (sllve_t* pe = paast->pbegin_blocks->phead; pe != NULL; pe = pe->pnext) {
analyzed_ast_allocate_locals_for_begin_end_block(pe->pvvalue);
}
analyzed_ast_allocate_locals_for_main_block(paast->pmain_block);
for (sllve_t* pe = paast->pend_blocks->phead; pe != NULL; pe = pe->pnext) {
analyzed_ast_allocate_locals_for_begin_end_block(pe->pvvalue);
}
}
// ----------------------------------------------------------------
static void analyzed_ast_allocate_locals_for_func_subr_block(mlr_dsl_ast_node_t* pnode) {
// xxx make a keystroke-saver, use it here, & use it from the cst builder as well
if (pnode->type != MD_AST_NODE_TYPE_SUBR_DEF && pnode->type != MD_AST_NODE_TYPE_FUNC_DEF) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
// xxx assert two children of desired type
analysis_frame_t* pframe = analysis_frame_alloc();
analysis_frame_group_t* pframe_group = analysis_frame_group_alloc(pframe);
printf("\n");
printf("ALLOCATING LOCALS FOR DEFINITION BLOCK [%s]\n", pnode->text);
mlr_dsl_ast_node_t* pdef_name_node = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* plist_node = pnode->pchildren->phead->pnext->pvvalue;
for (sllve_t* pe = pdef_name_node->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pparameter_node = pe->pvvalue;
analysis_frame_group_mark_for_define(pframe_group, pparameter_node, "PARAMETER", TRUE/*xxx temp*/);
}
analyzed_ast_allocate_locals_for_statement_block(plist_node, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
analysis_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void analyzed_ast_allocate_locals_for_begin_end_block(mlr_dsl_ast_node_t* pnode) {
if (pnode->type != MD_AST_NODE_TYPE_BEGIN && pnode->type != MD_AST_NODE_TYPE_END) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
printf("\n");
printf("ALLOCATING LOCALS FOR %s BLOCK\n", pnode->text);
analysis_frame_t* pframe = analysis_frame_alloc();
analysis_frame_group_t* pframe_group = analysis_frame_group_alloc(pframe);
analyzed_ast_allocate_locals_for_statement_block(pnode->pchildren->phead->pvvalue, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
analysis_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void analyzed_ast_allocate_locals_for_main_block(mlr_dsl_ast_node_t* pnode) {
// xxx assert node type
printf("\n");
printf("ALLOCATING LOCALS FOR MAIN BLOCK\n");
// xxx make this a one-liner
analysis_frame_t* pframe = analysis_frame_alloc();
analysis_frame_group_t* pframe_group = analysis_frame_group_alloc(pframe);
analyzed_ast_allocate_locals_for_statement_block(pnode, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
analysis_frame_group_free(pframe_group);
}
// ----------------------------------------------------------------
static void analyzed_ast_allocate_locals_for_statement_block(mlr_dsl_ast_node_t* pnode,
analysis_frame_group_t* pframe_group)
{
if (pnode->type != MD_AST_NODE_TYPE_STATEMENT_BLOCK) {
fprintf(stderr,
"%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
analyzed_ast_allocate_locals_for_node(pchild, pframe_group);
}
}
static void analyzed_ast_allocate_locals_for_node(mlr_dsl_ast_node_t* pnode,
analysis_frame_group_t* pframe_group)
{
// xxx make separate functions
if (pnode->type == MD_AST_NODE_TYPE_FOR_SREC) { // xxx comment
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pnode->text);
analysis_frame_t* pnext_frame = analysis_frame_alloc();
analysis_frame_group_push(pframe_group, pnext_frame);
mlr_dsl_ast_node_t* pvarsnode = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pblocknode = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pknode = pvarsnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pvnode = pvarsnode->pchildren->phead->pnext->pvvalue;
analysis_frame_group_mark_for_define(pframe_group, pknode, "FOR-BIND", TRUE/*xxx temp*/);
analysis_frame_group_mark_for_define(pframe_group, pvnode, "FOR-BIND", TRUE/*xxx temp*/);
analyzed_ast_allocate_locals_for_statement_block(pblocknode, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s\n", pnode->text);
} else if (pnode->type == MD_AST_NODE_TYPE_FOR_OOSVAR) { // xxx comment
mlr_dsl_ast_node_t* pvarsnode = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pkeylistnode = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pblocknode = pnode->pchildren->phead->pnext->pnext->pvvalue;
mlr_dsl_ast_node_t* pkeysnode = pvarsnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pvalnode = pvarsnode->pchildren->phead->pnext->pvvalue;
// xxx note keylistnode is outside the block binding. in particular if there are any localvar reads
// in there they shouldn't read from forloop boundvars.
for (sllve_t* pe = pkeylistnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
analyzed_ast_allocate_locals_for_node(pchild, pframe_group);
}
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pnode->text);
analysis_frame_t* pnext_frame = analysis_frame_alloc();
analysis_frame_group_push(pframe_group, pnext_frame);
for (sllve_t* pe = pkeysnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
analysis_frame_group_mark_for_define(pframe_group, pkeynode, "FOR-BIND", TRUE/*xxx temp*/);
}
analysis_frame_group_mark_for_define(pframe_group, pvalnode, "FOR-BIND", TRUE/*xxx temp*/);
analyzed_ast_allocate_locals_for_statement_block(pblocknode, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s\n", pnode->text);
} else if (pnode->type == MD_AST_NODE_TYPE_LOCAL_DEFINITION) {
// xxx decide on preorder vs. postorder
mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pvvalue;
analysis_frame_group_mark_for_define(pframe_group, pnamenode, "DEFINE", TRUE/*xxx temp*/);
mlr_dsl_ast_node_t* pvaluenode = pnode->pchildren->phead->pnext->pvvalue;
analyzed_ast_allocate_locals_for_node(pvaluenode, pframe_group);
} else if (pnode->type == MD_AST_NODE_TYPE_LOCAL_ASSIGNMENT) { // xxx rename
mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pvvalue;
analysis_frame_group_mark_for_write(pframe_group, pnamenode, "WRITE", TRUE/*xxx temp*/);
mlr_dsl_ast_node_t* pvaluenode = pnode->pchildren->phead->pnext->pvvalue;
analyzed_ast_allocate_locals_for_node(pvaluenode, pframe_group);
} else if (pnode->type == MD_AST_NODE_TYPE_BOUND_VARIABLE) {
analysis_frame_group_mark_for_read(pframe_group, pnode, "READ", TRUE/*xxx temp*/);
} else if (pnode->pchildren != NULL) {
for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pchild = pe->pvvalue;
if (pchild->type == MD_AST_NODE_TYPE_STATEMENT_BLOCK) {
for (int i = 0; i < pframe_group->plist->length; i++) // xxx temp
printf(":: ");
printf("PUSH FRAME %s\n", pchild->text);
analysis_frame_t* pnext_frame = analysis_frame_alloc();
analysis_frame_group_push(pframe_group, pnext_frame);
analyzed_ast_allocate_locals_for_statement_block(pchild, pframe_group);
analysis_frame_free(analysis_frame_group_pop(pframe_group));
for (int i = 0; i < pframe_group->plist->length; i++)
printf(":: ");
printf("POP FRAME %s\n", pchild->text);
} else {
analyzed_ast_allocate_locals_for_node(pchild, pframe_group);
}
}
}
}
// xxx to do:
// * make a separate file for tree-reorg part into top-level blocks
// * rename entire file; also 'analysis' & its acronyms
// ->maybe blocked_asts? vs. raw_ast?
// * 'semantic analysis': use this to describe CST-build-time checks
// * 'object binding': use this to describe linking func/subr defs and callsites
// * separate verbosity for allocator? and invoke it in UT cases specific to this?
// -> (note allocation marks in the AST will be printed regardless)
// * nodestash:
// @ localvar: fridx & upcount; then frgridx
// @ statement block: frct; then maxdepth (default #def NONESUCH @ ctor; respect @ ast-node printer)
// pass 1:
// @localvar put fridx & upcount
// @exit from statement block put frct
// pass 2:
// @localvar map fridx & upcount to relidx (>=0 for in-frame, <0 for upframe)
// @base put maxdepth
// 1 frame_relative_index
// 1 upstack_frame_count
// 2 frame_var_count
// 2 recursive_max_var_count
// 2 absolute_index

View file

@ -1871,7 +1871,7 @@ SEE ALSO
2016-10-05 MILLER(1)
2016-10-07 MILLER(1)
</pre>
</div>
<p/>

View file

@ -1724,4 +1724,4 @@ SEE ALSO
2016-10-05 MILLER(1)
2016-10-07 MILLER(1)

View file

@ -2,12 +2,12 @@
.\" Title: mlr
.\" Author: [see the "AUTHOR" section]
.\" Generator: ./mkman.rb
.\" Date: 2016-10-05
.\" Date: 2016-10-07
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
.TH "MILLER" "1" "2016-10-05" "\ \&" "\ \&"
.TH "MILLER" "1" "2016-10-07" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Portability definitions
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~