43#ifndef MLISP_TOKEN_SZ_MAX 
   44#  define MLISP_TOKEN_SZ_MAX 4096 
   47#ifndef MLISP_EXEC_TRACE_LVL 
   48#  define MLISP_EXEC_TRACE_LVL 0 
   51#ifndef MLISP_STACK_TRACE_LVL 
   52#  define MLISP_STACK_TRACE_LVL 0 
   55#define MLISP_ENV_FLAG_BUILTIN   0x02 
   58#define MLISP_ENV_FLAG_CMP_GT    0x10 
   61#define MLISP_ENV_FLAG_CMP_LT    0x20 
   64#define MLISP_ENV_FLAG_CMP_EQ    0x40 
   67#define MLISP_ENV_FLAG_ARI_ADD   0x10 
   70#define MLISP_ENV_FLAG_ARI_MUL   0x20 
   72#define MLISP_ENV_FLAG_ARI_DIV   0x40 
   74#define MLISP_ENV_FLAG_ARI_MOD   0x80 
   76#define MLISP_ENV_FLAG_ANO_OR    0x10 
   78#define MLISP_ENV_FLAG_ANO_AND   0x20 
   81#define MLISP_ENV_FLAG_DEFINE_GLOBAL   0x10 
   83#define MLISP_AUTOLOCK_EXEC_ENV     0x01 
   85#define MLISP_AUTOLOCK_CHILD_IDX    0x02 
   87#define MLISP_AUTOLOCK_VISIT_CT     0x04 
   89#define MLISP_AUTOLOCK_PARSER_AST   0x08 
   91#define MLISP_AUTOLOCK_GLOBAL_ENV   0x10 
  102#define MLISP_STACK_FLAG_PEEK    0x01 
  107#define mlisp_stack_pop( exec, o ) mlisp_stack_pop_ex( exec, o, 0 ) 
  117#define mlisp_stack_push( exec, i, ctype ) \ 
  118   (_mlisp_stack_push_ ## ctype( exec, (ctype)i )) 
  120#if defined( MLISP_DUMP_ENABLED ) || defined( DOCUMENTATION ) 
  143#if defined( MLISP_DUMP_ENABLED ) || defined( DOCUMENTATION ) 
  164   const char* token, 
size_t token_sz, uint8_t env_type, 
const void* data,
 
  165   uint8_t global, uint8_t flags );
 
  193   const char* lambda );
 
  214#define _MLISP_TYPE_TABLE_PUSH_PROTO( idx, ctype, name, const_name, fmt ) \ 
  215   MERROR_RETVAL _mlisp_stack_push_ ## ctype( \ 
  216      struct MLISP_EXEC_STATE* exec, ctype i ); 
  222#define mlisp_ast_has_ready_children( exec_child_idx, n ) \ 
  223   ((exec_child_idx) < (n)->ast_idx_children_sz) 
  227uint16_t g_mlispe_last_uid = 0;
 
  253   uint8_t mask, uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX]
 
  258   maug_mzero( autolock, MLISP_EXEC_ENV_FRAME_CT_MAX );
 
  261   if( MLISP_AUTOLOCK_EXEC_ENV == (MLISP_AUTOLOCK_EXEC_ENV & mask) ) {
 
  262      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
  263         if( !mdata_table_is_locked( &(exec->
env[env_iter]) ) ) {
 
  264#if MLISP_EXEC_TRACE_LVL > 0 
  265            debug_printf( MLISP_EXEC_TRACE_LVL,
 
  266               "%u: engaging autolock for exec env frame %d...",
 
  267               exec->uid, env_iter );
 
  269            mdata_table_lock( &(exec->
env[env_iter]) );
 
  270            autolock[env_iter] |= MLISP_AUTOLOCK_EXEC_ENV;
 
  275      MLISP_AUTOLOCK_CHILD_IDX == (MLISP_AUTOLOCK_CHILD_IDX & mask) &&
 
  278#if MLISP_EXEC_TRACE_LVL > 0 
  279      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  280         "%u: engaging autolock for exec per-node child index...", exec->uid );
 
  283      autolock[0] |= MLISP_AUTOLOCK_CHILD_IDX;
 
  286      MLISP_AUTOLOCK_VISIT_CT == (MLISP_AUTOLOCK_VISIT_CT & mask) &&
 
  289#if MLISP_EXEC_TRACE_LVL > 0 
  290      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  291         "%u: engaging autolock for per-node visit count...", exec->uid );
 
  294      autolock[0] |= MLISP_AUTOLOCK_VISIT_CT;
 
  297      MLISP_AUTOLOCK_PARSER_AST == (MLISP_AUTOLOCK_PARSER_AST & mask) &&
 
  298      !mdata_vector_is_locked( &(parser->ast) )
 
  300#if MLISP_EXEC_TRACE_LVL > 0 
  301      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  302         "%u: engaging autolock for parser AST...", exec->uid );
 
  305      autolock[0] |= MLISP_AUTOLOCK_PARSER_AST;
 
  308      MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & mask) &&
 
  309      NULL != exec->global_env &&
 
  310      0 < mdata_table_ct( exec->global_env ) &&
 
  311      !mdata_table_is_locked( exec->global_env )
 
  313#if MLISP_EXEC_TRACE_LVL > 0 
  314      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  315         "%u: engaging autolock for global env...", exec->uid );
 
  317      mdata_table_lock( exec->global_env );
 
  318      autolock[0] |= MLISP_AUTOLOCK_GLOBAL_ENV;
 
  327static void _mlisp_autounlock(
 
  329   uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX]
 
  332   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
  334         MLISP_AUTOLOCK_EXEC_ENV ==
 
  335         (MLISP_AUTOLOCK_EXEC_ENV & autolock[env_iter])
 
  337         mdata_table_unlock( &(exec->
env[env_iter]) );
 
  340   if( MLISP_AUTOLOCK_CHILD_IDX == (MLISP_AUTOLOCK_CHILD_IDX & autolock[0]) ) {
 
  343   if( MLISP_AUTOLOCK_VISIT_CT == (MLISP_AUTOLOCK_VISIT_CT & autolock[0]) ) {
 
  347      MLISP_AUTOLOCK_PARSER_AST == (MLISP_AUTOLOCK_PARSER_AST & autolock[0])
 
  352      MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & autolock[0])
 
  354      mdata_table_unlock( exec->global_env );
 
  364#ifdef MLISP_DUMP_ENABLED 
  373#  define _MLISP_TYPE_TABLE_DUMPS( idx, ctype, name, const_name, fmt ) \ 
  374      } else if( MLISP_TYPE_ ## const_name == n_stack->type ) { \ 
  375         debug_printf( MLISP_STACK_TRACE_LVL, \ 
  376            "%u: " MLISP_TRACE_SIGIL " stack " SIZE_T_FMT " (" #const_name "): " fmt, \
 
  377            exec->uid, i, n_stack->value.name );
 
  380   mdata_strpool_lock( &(parser->strpool) ); \
 
  385      if( MLISP_TYPE_STR == n_stack->type ) {
 
  387            "%u: " MLISP_TRACE_SIGIL 
" stack " SIZE_T_FMT 
" (STR): %s",
 
  388            exec->uid, i, mdata_strpool_get(
 
  389               &(parser->strpool), n_stack->value.strpool_idx ) );
 
  391      } 
else if( MLISP_TYPE_CB == n_stack->type ) {
 
  393            "%u: " MLISP_TRACE_SIGIL 
" stack " SIZE_T_FMT 
" (CB): %p",
 
  394            exec->uid, i, n_stack->value.cb );
 
  396      } 
else if( MLISP_TYPE_LAMBDA == n_stack->type ) {
 
  398            "%u: " MLISP_TRACE_SIGIL 
" stack " SIZE_T_FMT 
" (LAMBDA): " 
  400            exec->uid, i, n_stack->value.lambda );
 
  416      } 
else if( MLISP_TYPE_BEGIN == n_stack->type ) {
 
  418            "%u: " MLISP_TRACE_SIGIL 
" stack " SIZE_T_FMT 
" (BEGIN): " 
  420            exec->uid, i, n_stack->value.begin );
 
  425         error_printf( 
"invalid stack type: %u", n_stack->type );
 
  429   mdata_strpool_unlock( &(parser->strpool) );
 
  434   assert( mdata_strpool_is_locked( &(parser->strpool) ) );
 
  443#define _MLISP_TYPE_TABLE_PUSH( idx, ctype, name, const_name, fmt ) \ 
  444   MERROR_RETVAL _mlisp_stack_push_ ## ctype( \ 
  445      struct MLISP_EXEC_STATE* exec, ctype i \ 
  447      ssize_t stack_idx = 0; \ 
  448      struct MLISP_STACK_NODE n_stack; \ 
  449      MERROR_RETVAL retval = MERROR_OK; \ 
  450      debug_printf( MLISP_STACK_TRACE_LVL, \ 
  451         "%u: pushing " #const_name " onto stack: " fmt, exec->uid, i ); \
 
  452      n_stack.type = MLISP_TYPE_ ## const_name; \
 
  453      n_stack.value.name = i; \
 
  454      stack_idx = mdata_vector_append( \
 
  455         &(exec->stack), &n_stack, sizeof( struct MLISP_STACK_NODE ) ); \
 
  456      if( 0 > stack_idx ) { \
 
  457         retval = mdata_retval( stack_idx ); \
 
  483   n_stack = mdata_vector_get(
 
  485   assert( NULL != n_stack );
 
  490#if MLISP_STACK_TRACE_LVL > 0 
  491#  define _MLISP_TYPE_TABLE_POPD( idx, ctype, name, const_name, fmt ) \ 
  492      } else if( MLISP_TYPE_ ## const_name == o->type ) { \ 
  493         if( MLISP_STACK_FLAG_PEEK == (MLISP_STACK_FLAG_PEEK & flags) ) { \ 
  494            debug_printf( MLISP_STACK_TRACE_LVL, \ 
  495               "%u: peeking (%ut): " SSIZE_T_FMT ": " fmt, \
 
  496               exec->uid, n_idx, o->type, o->value.name ); \
 
  498            debug_printf( MLISP_STACK_TRACE_LVL, \
 
  499               "%u: popping (%ut): " SSIZE_T_FMT ": " fmt, \
 
  500               exec->uid, n_idx, o->type, o->value.name ); \
 
  523#if defined( MLISP_DUMP_ENABLED ) 
  527   void* cb_data, 
size_t cb_data_sz, 
size_t idx
 
  536#  define _MLISP_TYPE_TABLE_DUMPE( idx, ctype, name, const_name, fmt ) \ 
  537      } else if( MLISP_TYPE_ ## const_name == e->type ) { \ 
  539            "%u: " MLISP_TRACE_SIGIL " env \"%s\" (" #const_name "): " fmt, \
 
  540            exec->uid, key->string, e->value.name );
 
  542   if( MLISP_ENV_FLAG_BUILTIN == (MLISP_ENV_FLAG_BUILTIN & e->flags) ) {
 
  547   debug_printf( 1, 
"%s: %p: 0x%02x", key, e, e->type );
 
  552   } 
else if( MLISP_TYPE_STR == e->type ) {
 
  554         "%u: " MLISP_TRACE_SIGIL 
" env \"%s\" (STR): %s",
 
  556         mdata_strpool_get( &(parser.strpool), e->value.strpool_idx ) );
 
  558   } 
else if( MLISP_TYPE_CB == e->type ) {
 
  560         "%u: " MLISP_TRACE_SIGIL 
" env \"%s\" (CB): %p",
 
  561         exec->uid, key, e->value.cb );
 
  563   } 
else if( MLISP_TYPE_LAMBDA == e->type ) {
 
  565         "%u: " MLISP_TRACE_SIGIL 
" env \"%s\" (LAMBDA): " SIZE_T_FMT,
 
  566         exec->uid, key, e->value.lambda );
 
  569      error_printf( MLISP_TRACE_SIGIL 
" invalid env type: %u", e->type );
 
  582   uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
 
  584   retval = _mlisp_autolock(
 
  585      NULL, exec, MLISP_AUTOLOCK_EXEC_ENV | MLISP_AUTOLOCK_GLOBAL_ENV,
 
  587   maug_cleanup_if_not_ok();
 
  590      debug_printf( 1, 
"# global env:" );
 
  591      retval = mdata_table_iter(
 
  592         exec->global_env, _mlisp_env_dump_iter, exec, 0 );
 
  594      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
  595         debug_printf( 1, 
"# env frame %d:", env_iter );
 
  596         retval = mdata_table_iter(
 
  597            &(exec->
env[env_iter]), _mlisp_env_dump_iter, exec, 0 );
 
  598         maug_cleanup_if_not_ok();
 
  604   _mlisp_autounlock( NULL, exec, autolock );
 
  621   while( 0 <= env_iter ) {
 
  622      env = &(exec->
env[env_iter]);
 
  628      assert( mdata_table_is_locked( env ) );
 
  643   if( NULL != exec->global_env ) {
 
  644      assert( mdata_table_is_locked( exec->global_env ) );
 
  645      e = mdata_table_get( exec->global_env, key, 
struct MLISP_ENV_NODE );
 
  650   if( MERROR_OK != retval ) {
 
  664   uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
 
  670   maug_mzero( autolock, MLISP_EXEC_ENV_FRAME_CT_MAX );
 
  672   while( 0 <= env_iter ) {
 
  673#if MLISP_EXEC_TRACE_LVL > 0 
  674      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  675         "%u: attempting to undefine %s in frame %d...",
 
  676         exec->uid, token, env_iter );
 
  679      env = &(exec->
env[env_iter]);
 
  681      if( !mdata_table_is_locked( env ) ) {
 
  682         mdata_table_lock( env );
 
  683         autolock[env_iter] |= 0x02;
 
  686      retval = mdata_table_unset( env, token );
 
  691   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
  692      if( 0x02 == (0x02 & autolock[env_iter]) ) {
 
  693         env = &(exec->
env[env_iter]);
 
  694         assert( mdata_table_is_locked( env ) );
 
  695         mdata_table_unlock( env );
 
  706   const char* token, 
size_t token_sz, uint8_t env_type, 
const void* data,
 
  707   uint8_t global, uint8_t flags
 
  715      (MLISP_ENV_FLAG_BUILTIN != (MLISP_ENV_FLAG_BUILTIN & flags)) ||
 
  721      if( NULL != exec->global_env ) {
 
  722         env = exec->global_env;
 
  724         error_printf( 
"global env requested but not present!" );
 
  725         retval = MERROR_EXEC;
 
  730   if( 0 == token_sz ) {
 
  731      token_sz = maug_strlen( token );
 
  734   assert( NULL != env );
 
  735   assert( 0 < token_sz );
 
  737   assert( !mdata_table_is_locked( env ) );
 
  741   mdata_table_unset( env, token );
 
  743#if MLISP_EXEC_TRACE_LVL > 0 
  744#  define _MLISP_TYPE_TABLE_ASGN( idx, ctype, name, const_name, fmt ) \ 
  746         debug_printf( MLISP_EXEC_TRACE_LVL, \ 
  747            "%u: setting env %d: \"%s\": #" fmt, \
 
  748            exec->uid, exec->env_select, token, (ctype)*((ctype*)data) ); \
 
  749         e.value.name = *((ctype*)data); \
 
  752#  define _MLISP_TYPE_TABLE_ASGN( idx, ctype, name, const_name, fmt ) \ 
  754         e.value.name = *((ctype*)data); \ 
  761   maug_cleanup_if_not_ok();
 
  770#if MLISP_EXEC_TRACE_LVL > 0 
  771      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  772         "%u: setting env %d: \"%s\": strpool(" SSIZE_T_FMT 
")",
 
  773         exec->uid, exec->
env_select, token, *((ssize_t*)data) );
 
  775      e.value.strpool_idx = *((mdata_strpool_idx_t*)data);
 
  779#if MLISP_EXEC_TRACE_LVL > 0 
  780      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  781         "%u: setting env %d: \"%s\": 0x%p",
 
  788#if MLISP_EXEC_TRACE_LVL > 0 
  789      debug_printf( MLISP_EXEC_TRACE_LVL,
 
  790         "%u: setting env %d: \"%s\": node #" SSIZE_T_FMT,
 
  791         exec->uid, exec->
env_select, token, *((mlisp_lambda_t*)data) );
 
  793      e.value.lambda = *((mlisp_lambda_t*)data);
 
  808         "%u: underflow %s: missing lambda arg?",
 
  814      error_printf( 
"invalid type: %d", env_type );
 
  815      retval = MERROR_EXEC;
 
  819   retval = mdata_table_set( env, token, &e, 
sizeof( 
struct MLISP_ENV_NODE ) );
 
  830   size_t args_c, 
void* cb_data, uint8_t flags
 
  843   volatile int* cur_int = NULL;
 
  845   mdata_strpool_lock( &(parser->strpool) );
 
  849#if MLISP_EXEC_TRACE_LVL > 0 
  850#  define _MLISP_TYPE_TABLE_CMP( idx, ctype, name, const_name, fmt ) \ 
  851      } else if( MLISP_TYPE_ ## const_name == tmp.type ) { \ 
  852         *cur_int = (int)tmp.value.name; \ 
  853         debug_printf( MLISP_EXEC_TRACE_LVL, \ 
  854            "%u: cmp: pop " fmt " (%d)", exec->uid, tmp.value.name, *cur_int );
 
  856#  define _MLISP_TYPE_TABLE_CMP( idx, ctype, name, const_name, fmt ) \ 
  857      } else if( MLISP_TYPE_ ## const_name == tmp.type ) { \ 
  858         *cur_int = (int)tmp.value.name; 
  862   maug_cleanup_if_not_ok();
 
  864   if( MLISP_TYPE_STR == tmp.type ) {
 
  866      a_type = MLISP_TYPE_STR;
 
  870      error_printf( 
"cmp: invalid type: %d", tmp.type );
 
  871      retval = MERROR_EXEC;
 
  876   maug_cleanup_if_not_ok();
 
  878   if( MLISP_TYPE_STR == tmp.type ) {
 
  880      b_type = MLISP_TYPE_STR;
 
  884      error_printf( 
"cmp: invalid type!" );
 
  885      retval = MERROR_EXEC;
 
  890   if( MLISP_TYPE_STR == a_type || MLISP_TYPE_STR == b_type ) {
 
  899#if MLISP_EXEC_TRACE_LVL > 0 
  900      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: cmp %d > %d",
 
  901         exec->uid, a_int, b_int );
 
  903      truth = a_int > b_int;
 
  905#if MLISP_EXEC_TRACE_LVL > 0 
  906      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: cmp %d < %d",
 
  907         exec->uid, a_int, b_int );
 
  909      truth = a_int < b_int;
 
  911#if MLISP_EXEC_TRACE_LVL > 0 
  912      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: cmp %d == %d",
 
  913         exec->uid, a_int, b_int );
 
  915      truth = a_int == b_int;
 
  917      error_printf( 
"invalid parameter provided to _mlisp_env_cb_cmp()!" );
 
  918      retval = MERROR_EXEC;
 
  926   mdata_strpool_unlock( &(parser->strpool) );
 
  935   size_t args_c, 
void* cb_data, uint8_t flags
 
  943#  define _MLISP_TYPE_TABLE_ARI1( idx, ctype, name, const_name, fmt ) \ 
  944      } else if( MLISP_TYPE_ ## const_name == num.type ) { \ 
  945         num_out = num.value.name; 
  948   maug_cleanup_if_not_ok();
 
  953      error_printf( 
"arithmetic: invalid type!" );
 
  954      retval = MERROR_EXEC;
 
  958#  define _MLISP_TYPE_TABLE_ARI2( idx, ctype, name, const_name, fmt ) \ 
  960         MLISP_TYPE_ ## const_name == num.type && \ 
  961         MLISP_ENV_FLAG_ARI_ADD == (MLISP_ENV_FLAG_ARI_ADD & flags) \ 
  963         debug_printf( MLISP_EXEC_TRACE_LVL, \ 
  964            "%u: arithmetic: %d + " fmt, exec->uid, num_out, num.value.name ); \
 
  965         num_out += num.value.name; \
 
  967         MLISP_TYPE_ ## const_name == num.type && \
 
  968         MLISP_ENV_FLAG_ARI_MUL == (MLISP_ENV_FLAG_ARI_MUL & flags) \
 
  970         debug_printf( MLISP_EXEC_TRACE_LVL, \
 
  971            "%u: arithmetic: %d * " fmt, exec->uid, num_out, num.value.name ); \
 
  972         num_out *= num.value.name; \
 
  974         MLISP_TYPE_ ## const_name == num.type && \
 
  975         MLISP_ENV_FLAG_ARI_DIV == (MLISP_ENV_FLAG_ARI_DIV & flags) \
 
  977         debug_printf( MLISP_EXEC_TRACE_LVL, \
 
  978            "%u: arithmetic: %d / " fmt, exec->uid, num_out, num.value.name ); \
 
  979         num_out /= num.value.name; \
 
  981   for( i = 0 ; args_c - 1 > i ; i++ ) {
 
  983      maug_cleanup_if_not_ok();
 
  989         MLISP_TYPE_INT == num.type &&
 
  990         MLISP_ENV_FLAG_ARI_MOD == (MLISP_ENV_FLAG_ARI_MOD & flags)
 
  993         debug_printf( MLISP_EXEC_TRACE_LVL,
 
  994            "%u: arithmetic: %d %% %d", exec->uid, num_out, num.value.integer );
 
  995         num_out %= num.value.integer;
 
  997         error_printf( 
"arithmetic: invalid type!" );
 
  998         retval = MERROR_EXEC;
 
 1003   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1004      "%u: arithmetic result: %d", exec->uid, num_out );
 
 1010   mdata_strpool_unlock( &(parser->strpool) );
 
 1019   size_t args_c, 
void* cb_data, uint8_t flags
 
 1024   MAUG_MHANDLE key_tmp_h = (MAUG_MHANDLE)NULL;
 
 1025   char* key_tmp = NULL;
 
 1028#if MLISP_EXEC_TRACE_LVL > 0 
 1029   debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: entering define callback...",
 
 1034   maug_cleanup_if_not_ok();
 
 1037   maug_cleanup_if_not_ok();
 
 1039   if( MLISP_TYPE_STR != key.type ) {
 
 1042      error_printf( 
"define: invalid key type: %d", key.type );
 
 1043      retval = MERROR_EXEC;
 
 1047#if MLISP_EXEC_TRACE_LVL > 0 
 1048   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1049      "%u: extracting define term for idx: " SIZE_T_FMT,
 
 1050      exec->uid, key.value.strpool_idx );
 
 1054      &(parser->strpool), key.value.strpool_idx );
 
 1056   assert( (MAUG_MHANDLE)NULL != key_tmp_h );
 
 1058   maug_mlock( key_tmp_h, key_tmp );
 
 1059   maug_cleanup_if_null_lock( 
char*, key_tmp );
 
 1061#if MLISP_EXEC_TRACE_LVL > 0 
 1062   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1063      "%u: define \"%s\" (strpool(" SIZE_T_FMT 
"))...",
 
 1064      exec->uid, key_tmp, key.value.strpool_idx );
 
 1071#if MLISP_EXEC_TRACE_LVL > 0 
 1072      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1073         "%u: using global env...", exec->uid );
 
 1079   retval = mlisp_env_set(
 
 1080      exec, key_tmp, maug_strlen( key_tmp ), val.type, &(val.value),
 
 1082   maug_cleanup_if_not_ok();
 
 1084#if MLISP_EXEC_TRACE_LVL > 0 
 1085   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1086      "%u: setup env node: %s",
 
 1087      exec->uid, key_tmp );
 
 1092   if( NULL != key_tmp ) {
 
 1093      maug_munlock( key_tmp_h, key_tmp );
 
 1096   if( (MAUG_MHANDLE)NULL != key_tmp_h ) {
 
 1097      maug_mfree( key_tmp_h );
 
 1107   size_t args_c, 
void* cb_data, uint8_t flags
 
 1110   size_t* p_if_child_idx = NULL;
 
 1114#if MLISP_EXEC_TRACE_LVL > 0 
 1115   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1116      "%u: qrqrqrqrqr STEP IF qrqrqrqrqr", exec->uid );
 
 1121   p_if_child_idx = mdata_vector_get(
 
 1123   assert( NULL != p_if_child_idx );
 
 1124#if MLISP_EXEC_TRACE_LVL > 0 
 1125   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1126      "%u: node " SIZE_T_FMT 
" child idx: " SIZE_T_FMT,
 
 1127      exec->uid, n_idx, *p_if_child_idx );
 
 1130   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1132   if( 0 == *p_if_child_idx ) {
 
 1134#if MLISP_EXEC_TRACE_LVL > 0 
 1135      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1136         "%u: stepping into condition...", exec->uid );
 
 1138      retval = _mlisp_step_iter(
 
 1139         parser, n->ast_idx_children[*p_if_child_idx], exec );
 
 1140#if MLISP_EXEC_TRACE_LVL > 0 
 1141      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1142         "%u: ...stepped out of condition", exec->uid );
 
 1146      if( MERROR_OK == retval ) {
 
 1151         maug_cleanup_if_not_ok();
 
 1152         if( MLISP_TYPE_BOOLEAN != s.type ) {
 
 1153            error_printf( 
"(if) can only evaluate boolean type!" );
 
 1154            retval = MERROR_EXEC;
 
 1159         retval = _mlisp_preempt(
 
 1160            retval, 
"if", parser, n_idx, exec,
 
 1162            (1 - s.value.boolean) + 1 );
 
 1165   } 
else if( args_c > *p_if_child_idx ) { 
 
 1168#if MLISP_EXEC_TRACE_LVL > 0 
 1169      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1170         "%u: descending into IF path: " SIZE_T_FMT,
 
 1171         exec->uid, *p_if_child_idx );
 
 1177      retval = _mlisp_step_iter(
 
 1178         parser, n->ast_idx_children[*p_if_child_idx], exec );
 
 1179      retval = _mlisp_preempt(
 
 1180         retval, 
"if", parser, n_idx, exec, 3 );
 
 1185#if MLISP_EXEC_TRACE_LVL > 0 
 1186   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1187      "%u: qrqrqrqrqr END STEP IF qrqrqrqrqr", exec->uid );
 
 1195#ifndef MAUG_NO_RETRO 
 1201   size_t args_c, 
void* cb_data, uint8_t flags
 
 1205   int16_t random_int = 0;
 
 1208   maug_cleanup_if_not_ok();
 
 1210   if( MLISP_TYPE_INT != mod.type ) {
 
 1212      error_printf( 
"random: invalid modulus type: %d", mod.type );
 
 1213      retval = MERROR_EXEC;
 
 1217   random_int = retroflat_get_rand() % mod.value.integer;
 
 1219#if MLISP_EXEC_TRACE_LVL > 0 
 1220   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1221      "%u: random: %d", exec->uid, random_int ); 
 
 1237   size_t args_c, 
void* cb_data, uint8_t flags
 
 1241   mlisp_bool_t val_out =
 
 1242      MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ?
 
 1250   for( i = 0 ; args_c > i ; i++ ) {
 
 1252      maug_cleanup_if_not_ok();
 
 1254      if( MLISP_TYPE_BOOLEAN != val.type ) {
 
 1255         error_printf( 
"or: invalid boolean type: %d", val.type );
 
 1258      if( val.value.boolean ) {
 
 1259#if MLISP_EXEC_TRACE_LVL > 0 
 1260         debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: found TRUE in %s!",
 
 1262            MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ?
 
 1266            MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ? 1 : 0;
 
 1270   retval = _mlisp_stack_push_mlisp_bool_t( exec, val_out );
 
 1288   size_t* p_child_idx = NULL;
 
 1291   p_child_idx = mdata_vector_get(
 
 1293   assert( NULL != p_child_idx );
 
 1295   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1297   if( 0 < n->token_idx ) {
 
 1298      mdata_strpool_lock( &(parser->strpool) );
 
 1299#if MLISP_EXEC_TRACE_LVL > 0 
 1300      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1301         "%u: eval step " SSIZE_T_FMT 
" under (%s) %s...",
 
 1302         exec->uid, *p_child_idx, caller,
 
 1303         mdata_strpool_get( &(parser->strpool), n->token_idx ) );
 
 1305      mdata_strpool_unlock( &(parser->strpool) );
 
 1306#if MLISP_EXEC_TRACE_LVL > 0 
 1308      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1309         "%u: eval step " SSIZE_T_FMT 
" under (%s) (empty token)...",
 
 1310         exec->uid, *p_child_idx, caller );
 
 1314   if( MERROR_OK != retval ) {
 
 1316#if MLISP_EXEC_TRACE_LVL > 0 
 1317      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1318         "%u: not incrementing node " SIZE_T_FMT 
" child idx from " 
 1319            SIZE_T_FMT 
" (retval: 0x%x)!",
 
 1320         exec->uid, n_idx, *p_child_idx, retval );
 
 1329   (*p_child_idx) = new_idx;
 
 1330#if MLISP_EXEC_TRACE_LVL > 0 
 1331   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1332      "%u: incremented node " SIZE_T_FMT 
" child idx to: " SIZE_T_FMT,
 
 1333      exec->uid, n_idx, *p_child_idx );
 
 1338   assert( !mdata_strpool_is_locked( &(parser->strpool) ) );
 
 1349   size_t* p_child_idx = NULL;
 
 1354   p_child_idx = mdata_vector_get(
 
 1356   assert( NULL != p_child_idx );
 
 1357#if MLISP_EXEC_TRACE_LVL > 0 
 1358   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1359      "%u: node " SIZE_T_FMT 
" child idx: " SIZE_T_FMT,
 
 1360      exec->uid, n_idx, *p_child_idx );
 
 1363   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1367         MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) &&
 
 1370      MLISP_AST_FLAG_IF == (MLISP_AST_FLAG_IF & n->flags) 
 
 1379#if MLISP_EXEC_TRACE_LVL > 0 
 1380      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1381         "%u: skipping lambda children...", exec->uid );
 
 1386   if( mlisp_ast_has_ready_children( *p_child_idx, n ) ) {
 
 1390         MLISP_AST_FLAG_DEFINE == (MLISP_AST_FLAG_DEFINE & n->flags) &&
 
 1394#if MLISP_EXEC_TRACE_LVL > 0 
 1395         debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1396            "%u: setting MLISP_EXEC_FLAG_DEF_TERM!", exec->uid );
 
 1400         exec->
flags &= ~MLISP_EXEC_FLAG_DEF_TERM;
 
 1404      retval = _mlisp_step_iter(
 
 1405         parser, n->ast_idx_children[*p_child_idx], exec );
 
 1406      retval = _mlisp_preempt(
 
 1407         retval, 
"node", parser, n_idx, exec, (*p_child_idx) + 1 );
 
 1422   ssize_t arg_idx = 0;
 
 1425   MAUG_MHANDLE key_tmp_h = (MAUG_MHANDLE)NULL;
 
 1426   char* key_tmp = NULL;
 
 1428   int16_t null_val = 0;
 
 1436   if( MLISP_EXEC_ENV_FRAME_CT_MAX > exec->
env_select + 1 ) {
 
 1438#if MLISP_EXEC_TRACE_LVL > 0 
 1439      debug_printf( MLISP_EXEC_TRACE_LVL, 
"selecting env frame: %d",
 
 1442      assert( 0 == mdata_table_ct( &(exec->
env[exec->
env_select]) ) );
 
 1445      retval = mlisp_env_set(
 
 1446         exec, 
"null", 4, MLISP_TYPE_INT, &null_val, 0, 0 );
 
 1448      error_printf( 
"env frame overflow!" );
 
 1449      retval = MERROR_OVERFLOW;
 
 1454   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1457   while( 0 <= arg_idx ) {
 
 1460      maug_cleanup_if_not_ok();
 
 1462      ast_n_arg = mdata_vector_get(
 
 1463         &(parser->ast), n->ast_idx_children[arg_idx],
 
 1468         &(parser->strpool), ast_n_arg->token_idx );
 
 1470      assert( (MAUG_MHANDLE)NULL != key_tmp_h );
 
 1472      maug_mlock( key_tmp_h, key_tmp );
 
 1473      maug_cleanup_if_null_lock( 
char*, key_tmp );
 
 1475      retval = mlisp_env_set(
 
 1476         exec, key_tmp, 0, stack_n_arg.type, &(stack_n_arg.value), 0, 0 );
 
 1477      maug_cleanup_if_not_ok();
 
 1479      maug_munlock( key_tmp_h, key_tmp );
 
 1480      maug_mfree( key_tmp_h );
 
 1487   if( NULL != key_tmp ) {
 
 1488      maug_munlock( key_tmp_h, key_tmp );
 
 1491   if( (MAUG_MHANDLE)NULL != key_tmp_h ) {
 
 1492      maug_mfree( key_tmp_h );
 
 1505   size_t* p_child_idx = NULL;
 
 1506   size_t* p_visit_ct = NULL;
 
 1511   assert( mdata_vector_is_locked( &(parser->ast) ) );
 
 1514#if MLISP_EXEC_TRACE_LVL > 0 
 1515   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1516      "%u: resetting node " SIZE_T_FMT 
" child idx to 0", exec->uid, n_idx );
 
 1519   assert( NULL != p_child_idx );
 
 1522#if MLISP_EXEC_TRACE_LVL > 0 
 1523   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1524      "%u: resetting node " SIZE_T_FMT 
" visit count to 0", exec->uid, n_idx );
 
 1527   assert( NULL != p_visit_ct );
 
 1530   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1534      retval = _mlisp_reset_child_pcs( parser, n->ast_idx_children[i], exec );
 
 1535      maug_cleanup_if_not_ok();
 
 1551#if MLISP_EXEC_TRACE_LVL > 0 
 1552   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1553      "%u: resetting lambda " SIZE_T_FMT 
"...", exec->uid, n_idx );
 
 1559   assert( !mdata_table_is_locked( &(exec->
env[exec->
env_select]) ) );
 
 1565   retval = _mlisp_reset_child_pcs( parser, n_idx, exec );
 
 1578   size_t* p_lambda_child_idx = NULL;
 
 1579   size_t* p_args_child_idx = NULL;
 
 1581   size_t* p_n_last_lambda = NULL;
 
 1582   ssize_t append_retval = 0;
 
 1584#ifdef MLISP_DEBUG_TRACE 
 1585   exec->trace[exec->trace_depth++] = n_idx;
 
 1586   assert( exec->trace_depth <= MLISP_DEBUG_TRACE );
 
 1591   p_n_last_lambda = mdata_vector_get_last( &(exec->
lambda_trace), 
size_t );
 
 1593   if( NULL != p_n_last_lambda && n_idx == *p_n_last_lambda ) {
 
 1597#if MLISP_EXEC_TRACE_LVL > 0 
 1598      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: TRACE TAIL TIME!", exec->uid );
 
 1604      _mlisp_reset_lambda( parser, n_idx, exec );
 
 1605      retval = mdata_vector_remove_last( &(exec->
lambda_trace) );
 
 1606      maug_cleanup_if_not_ok();
 
 1609#if MLISP_EXEC_TRACE_LVL > 0 
 1610   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1611      "%u: xvxvxvxvxvxvx STEP LAMBDA " SIZE_T_FMT 
" xvxvxvxvxvx",
 
 1618   retval = mdata_retval( append_retval );
 
 1619   maug_cleanup_if_not_ok();
 
 1623   p_lambda_child_idx = mdata_vector_get(
 
 1625   assert( NULL != p_lambda_child_idx );
 
 1626#if MLISP_EXEC_TRACE_LVL > 0 
 1627   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1628      "%u: lambda node " SIZE_T_FMT 
" child idx: " SIZE_T_FMT,
 
 1629      exec->uid, n_idx, *p_lambda_child_idx );
 
 1632   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1638   if( 0 == *p_lambda_child_idx ) {
 
 1643      p_args_child_idx = mdata_vector_get(
 
 1645         n->ast_idx_children[*p_lambda_child_idx], 
size_t );
 
 1646      assert( NULL != p_args_child_idx );
 
 1647#if MLISP_EXEC_TRACE_LVL > 0 
 1648      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1649         "%u: child idx for args AST node " SIZE_T_FMT 
": " SIZE_T_FMT,
 
 1650         exec->uid, *p_lambda_child_idx, *p_args_child_idx );
 
 1654      retval = _mlisp_step_lambda_args(
 
 1655         parser, n->ast_idx_children[*p_lambda_child_idx], exec );
 
 1661      if( MERROR_OK == retval ) {
 
 1670         (*p_lambda_child_idx)++;
 
 1671#if MLISP_EXEC_TRACE_LVL > 0 
 1672         debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1673            "%u: incremented node " SIZE_T_FMT 
" child idx to: " SIZE_T_FMT,
 
 1674            exec->uid, n_idx, *p_lambda_child_idx );
 
 1683   } 
else if( mlisp_ast_has_ready_children( *p_lambda_child_idx, n ) ) {
 
 1691         NULL == exec->global_env ||
 
 1692         !mdata_table_is_locked( exec->global_env ) );
 
 1694      retval = _mlisp_step_iter(
 
 1695         parser, n->ast_idx_children[*p_lambda_child_idx], exec );
 
 1697      retval = _mlisp_preempt(
 
 1698         retval, 
"lambda", parser, n_idx, exec, (*p_lambda_child_idx) + 1 );
 
 1705         NULL == exec->global_env ||
 
 1706         !mdata_table_is_locked( exec->global_env ) );
 
 1707      _mlisp_reset_lambda( parser, n_idx, exec );
 
 1714#if MLISP_EXEC_TRACE_LVL > 0 
 1715   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1716      "%u: xvxvxvxvxvxvx END STEP LAMBDA " SIZE_T_FMT 
" xvxvxvxvxvx",
 
 1740      maug_cleanup_if_not_ok();
 
 1742      if( MLISP_TYPE_BEGIN == o.type && n_idx == o.value.begin ) {
 
 1766   char* strpool_token = NULL;
 
 1772      NULL == exec->global_env ||
 
 1773      mdata_table_is_locked( exec->global_env ) );
 
 1775   mdata_strpool_lock( &(parser->strpool) );
 
 1778   strpool_token = mdata_strpool_get( &(parser->strpool), token_idx );
 
 1779   assert( NULL != strpool_token );
 
 1781#if MLISP_EXEC_TRACE_LVL > 0 
 1782   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1783      "%u: eval token: \"%s\" (strlen: " SIZE_T_FMT 
"r/" SIZE_T_FMT 
"d)",
 
 1784      exec->uid, strpool_token, token_sz, maug_strlen( strpool_token ) );
 
 1786   if( 0 == strncmp( strpool_token, 
"begin", token_sz ) ) {
 
 1788      e_out->type = MLISP_TYPE_BEGIN;
 
 1790   } 
else if( NULL != (p_e = mlisp_env_get( exec, strpool_token ) ) ) {
 
 1792#if MLISP_EXEC_TRACE_LVL > 0 
 1793      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: found %s in env!",
 
 1794         exec->uid, strpool_token );
 
 1802   } 
else if( maug_is_num( strpool_token, token_sz, 10, 1 ) ) {
 
 1804#if MLISP_EXEC_TRACE_LVL > 0 
 1805      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1806         "%u: did not find %s in env, but it is a number...",
 
 1807         exec->uid, strpool_token );
 
 1809      e_out->value.integer = maug_atos32( strpool_token, token_sz );
 
 1810      e_out->type = MLISP_TYPE_INT;
 
 1812   } 
else if( maug_is_float( strpool_token, token_sz ) ) {
 
 1813#if MLISP_EXEC_TRACE_LVL > 0 
 1814      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1815         "%u: did not find %s in env, but it is a float...",
 
 1816         exec->uid, strpool_token );
 
 1819      e_out->value.floating = maug_atof( strpool_token, token_sz );
 
 1820      e_out->type = MLISP_TYPE_FLOAT;
 
 1823#if MLISP_EXEC_TRACE_LVL > 0 
 1824      error_printf( 
"%u: could not make sense of token: %s",
 
 1825         exec->uid, strpool_token );
 
 1832   if( mdata_strpool_is_locked( &(parser->strpool) ) ) {
 
 1833      mdata_strpool_unlock( &(parser->strpool) );
 
 1836#if MLISP_EXEC_TRACE_LVL > 0 
 1837      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: eval token complete!",
 
 1851   size_t* p_visit_ct = NULL;
 
 1853   uint8_t e_flags = 0;
 
 1854   mlisp_lambda_t e_lambda = 0;
 
 1855   int8_t env_iter = 0;
 
 1861   volatile mdata_strpool_idx_t node_strpool_idx = 0;
 
 1863#ifdef MLISP_DEBUG_TRACE 
 1864   exec->trace[exec->trace_depth++] = n_idx;
 
 1865   assert( exec->trace_depth <= MLISP_DEBUG_TRACE );
 
 1868   n = mdata_vector_get( &(parser->ast), n_idx, 
struct MLISP_AST_NODE );
 
 1871   p_visit_ct = mdata_vector_get(
 
 1873   assert( NULL != p_visit_ct );
 
 1875#if MLISP_EXEC_TRACE_LVL > 0 
 1876   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1877      "%u: visit count for AST node " SIZE_T_FMT 
": " SIZE_T_FMT,
 
 1878      exec->uid, n_idx, *p_visit_ct );
 
 1883      MLISP_AST_FLAG_BEGIN == (MLISP_AST_FLAG_BEGIN & n->flags) &&
 
 1887      retval = _mlisp_stack_push_mlisp_begin_t( exec, n_idx );
 
 1888      maug_cleanup_if_not_ok();
 
 1893      (retval = _mlisp_step_iter_children( parser, n_idx, exec ))
 
 1899   if( MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) ) {
 
 1915   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 1916#if MLISP_EXEC_TRACE_LVL > 0 
 1917      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1918         "%u: locking local env %d...", exec->uid, env_iter );
 
 1920      mdata_table_lock( &(exec->
env[env_iter]) );
 
 1924      NULL == exec->global_env || !mdata_table_is_locked( exec->global_env ) );
 
 1925   if( NULL != exec->global_env ) {
 
 1926      mdata_table_lock( exec->global_env );
 
 1930   retval = _mlisp_eval_token_strpool(
 
 1931      parser, exec, n->token_idx, n->token_sz, &e );
 
 1932   maug_cleanup_if_not_ok();
 
 1936#if MLISP_EXEC_TRACE_LVL > 0 
 1937      debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: acting on evaluated token...",
 
 1942#  define _MLISP_TYPE_TABLE_ENVE( idx, ctype, name, const_name, fmt ) \ 
 1943   } else if( MLISP_TYPE_ ## const_name == e.type ) { \ 
 1944      debug_printf( MLISP_EXEC_TRACE_LVL, \ 
 1945         "%u: pushing env: " fmt " to stack...", \
 
 1946         exec->uid, e.value.name ); \
 
 1947      retval = _mlisp_stack_push_ ## ctype( exec, e.value.name ); \
 
 1948      maug_cleanup_if_not_ok();
 
 1954#if MLISP_EXEC_TRACE_LVL > 0 
 1955      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1956         "%u: special case! pushing literal to stack: " SSIZE_T_FMT,
 
 1957         exec->uid, n->token_idx );
 
 1959      node_strpool_idx = n->token_idx;
 
 1960      retval = _mlisp_stack_push_mdata_strpool_idx_t( exec, node_strpool_idx );
 
 1961      maug_cleanup_if_not_ok();
 
 1962   } 
else if( MLISP_TYPE_BEGIN == e.type ) {
 
 1966#if MLISP_EXEC_TRACE_LVL > 0 
 1967      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1968         "%u: rewinding stack for begin on node " SSIZE_T_FMT,
 
 1971      retval = _mlisp_stack_cleanup( parser, n_idx, exec );
 
 1972      maug_cleanup_if_not_ok();
 
 1977      retval = _mlisp_stack_push_mlisp_begin_t( exec, n_idx );
 
 1978      maug_cleanup_if_not_ok();
 
 1980   } 
else if( MLISP_TYPE_CB == e.type ) {
 
 1986#if MLISP_EXEC_TRACE_LVL > 0 
 1987      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 1988         "%u: special case! executing callback: %p", exec->uid, e_cb );
 
 1994      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 1995         mdata_table_unlock( &(exec->
env[env_iter]) );
 
 1997      if( NULL != exec->global_env ) {
 
 1998         mdata_table_unlock( exec->global_env );
 
 2005      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2006         mdata_table_lock( &(exec->
env[env_iter]) );
 
 2008      if( NULL != exec->global_env ) {
 
 2009         mdata_table_lock( exec->global_env );
 
 2012   } 
else if( MLISP_TYPE_LAMBDA == e.type ) {
 
 2014#if MLISP_EXEC_TRACE_LVL > 0 
 2015      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2016         "%u: special case! executing lambda...", exec->uid );
 
 2024      e_lambda = e.value.lambda;
 
 2025      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2026         mdata_table_unlock( &(exec->
env[env_iter]) );
 
 2028      if( NULL != exec->global_env ) {
 
 2029         mdata_table_unlock( exec->global_env );
 
 2032      retval = _mlisp_step_lambda( parser, e_lambda, exec );
 
 2035      for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2036         mdata_table_lock( &(exec->
env[env_iter]) );
 
 2038      if( NULL != exec->global_env ) {
 
 2039         mdata_table_lock( exec->global_env );
 
 2044#if MLISP_EXEC_TRACE_LVL > 0 
 2045      debug_printf( MLISP_EXEC_TRACE_LVL, 
"pushing literal into stack" );
 
 2047      retval = _mlisp_stack_push_mdata_strpool_idx_t( exec, n->token_idx );
 
 2048      maug_cleanup_if_not_ok();
 
 2053   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2054      mdata_table_unlock( &(exec->
env[env_iter]) );
 
 2057   if( NULL != exec->global_env ) {
 
 2058      mdata_table_unlock( exec->global_env );
 
 2068   void* cb_data, 
size_t cb_data_sz, 
size_t idx
 
 2072   ssize_t* p_builtins = (ssize_t*)cb_data;
 
 2074   if( MLISP_ENV_FLAG_BUILTIN == (MLISP_ENV_FLAG_BUILTIN & e->flags) ) {
 
 2085   ssize_t builtins = 0;
 
 2088   if( 0 == mdata_table_ct( &(exec->
env[0]) ) ) {
 
 2092   if( !mdata_table_is_locked( &(exec->
env[0]) ) ) {
 
 2093      mdata_table_lock( &(exec->
env[0]) );
 
 2097   retval = mdata_table_iter(
 
 2098      &(exec->
env[0]), _mlisp_count_builtins_iter, &builtins, 0 );
 
 2102   if( MERROR_OK != retval ) {
 
 2103      builtins = merror_retval_to_sz( retval );
 
 2107      mdata_table_unlock( &(exec->
env[0]) );
 
 2121      error_printf( 
"no valid AST present; could not exec!" );
 
 2122      retval = MERROR_EXEC;
 
 2127      MLISP_EXEC_FLAG_INITIALIZED != (exec->
flags & MLISP_EXEC_FLAG_INITIALIZED)
 
 2129      retval = MERROR_EXEC;
 
 2144#ifdef MLISP_DEBUG_TRACE 
 2146   char trace_str[MLISP_DEBUG_TRACE * 5];
 
 2147   maug_ms_t ms_start = 0;
 
 2148   maug_ms_t ms_end = 0;
 
 2150   ms_start = retroflat_get_ms();
 
 2153#if MLISP_EXEC_TRACE_LVL > 0 
 2154   debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: heartbeat start", exec->uid );
 
 2162   assert( !mdata_vector_is_locked( &(parser->ast) ) );
 
 2171#ifdef MLISP_DEBUG_TRACE 
 2172   exec->trace_depth = 0;
 
 2176   retval = _mlisp_step_iter( parser, 0, exec );
 
 2180   } 
else if( MERROR_OK == retval ) {
 
 2182#if MLISP_EXEC_TRACE_LVL > 0 
 2183      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2184         "%u: execution terminated successfully", exec->uid );
 
 2186      retval = MERROR_EXEC; 
 
 2187#if MLISP_EXEC_TRACE_LVL > 0 
 2189      debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2190         "%u: execution terminated with retval: %d", exec->uid, retval );
 
 2194#ifdef MLISP_DEBUG_TRACE 
 2195   ms_end = retroflat_get_ms();
 
 2197   maug_mzero( trace_str, MLISP_DEBUG_TRACE * 5 );
 
 2198   for( i = 0 ; exec->trace_depth > i ; i++ ) {
 
 2200         &(trace_str[maug_strlen( trace_str )]),
 
 2201         (MLISP_DEBUG_TRACE * 5) - maug_strlen( trace_str ),
 
 2202         SIZE_T_FMT 
", ", exec->trace[i] );
 
 2204#if MLISP_EXEC_TRACE_LVL > 0 
 2205   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2206      "%u: " MLISP_TRACE_SIGIL 
" HBEXEC (%u): %s",
 
 2207      exec->uid, ms_end - ms_start, trace_str );
 
 2213#if MLISP_EXEC_TRACE_LVL > 0 
 2214   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2215      "%u: heartbeat end: %x", exec->uid, retval );
 
 2218   assert( mdata_vector_is_locked( &(parser->ast) ) );
 
 2234   uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
 
 2235   mlisp_lambda_t lambda_idx = 0;
 
 2237   int8_t env_iter = 0;
 
 2239   if( MERROR_OK != mlisp_check_state( parser, exec ) ) {
 
 2240      error_printf( 
"mlisp not ready!" );
 
 2241      retval = MERROR_EXEC;
 
 2245   retval = _mlisp_autolock( parser, exec, 0xff, autolock );
 
 2246   maug_cleanup_if_not_ok();
 
 2249   e = mlisp_env_get( exec, lambda );
 
 2251      error_printf( 
"lambda \"%s\" not found!", lambda );
 
 2252      retval = MERROR_OVERFLOW;
 
 2255   lambda_idx = e->value.lambda;
 
 2261   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2262      if( MLISP_AUTOLOCK_EXEC_ENV == (MLISP_AUTOLOCK_EXEC_ENV & autolock[0]) ) {
 
 2263         mdata_table_unlock( &(exec->
env[env_iter]) );
 
 2264         autolock[env_iter] &= ~MLISP_AUTOLOCK_EXEC_ENV;
 
 2268      MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & autolock[0])
 
 2270      mdata_table_unlock( exec->global_env );
 
 2271      autolock[0] &= ~MLISP_AUTOLOCK_GLOBAL_ENV;
 
 2274#if MLISP_EXEC_TRACE_LVL > 0 
 2275   debug_printf( MLISP_EXEC_TRACE_LVL, 
"%u: lambda \"%s\" is AST node idx %ld",
 
 2276      exec->uid, lambda, lambda_idx );
 
 2279   n = mdata_vector_get( &(parser->ast), lambda_idx, 
struct MLISP_AST_NODE );
 
 2280   assert( MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) );
 
 2283   retval = _mlisp_step_lambda( parser, lambda_idx, exec );
 
 2287   _mlisp_autounlock( parser, exec, autolock );
 
 2299   retval = mlisp_env_set(
 
 2300      exec, 
"gdefine", 7, MLISP_TYPE_CB, _mlisp_env_cb_define,
 
 2302   maug_cleanup_if_not_ok();
 
 2304   retval = mlisp_env_set(
 
 2305      exec, 
"and", 3, MLISP_TYPE_CB, _mlisp_env_cb_ano,
 
 2306      0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ANO_AND );
 
 2307   maug_cleanup_if_not_ok();
 
 2309   retval = mlisp_env_set(
 
 2310      exec, 
"or", 2, MLISP_TYPE_CB, _mlisp_env_cb_ano,
 
 2311      0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ANO_OR );
 
 2312   maug_cleanup_if_not_ok();
 
 2314#ifndef MAUG_NO_RETRO 
 2316   retval = mlisp_env_set(
 
 2317      exec, 
"random", 6, MLISP_TYPE_CB, _mlisp_env_cb_random,
 
 2318      0, MLISP_ENV_FLAG_BUILTIN );
 
 2319   maug_cleanup_if_not_ok();
 
 2322   retval = mlisp_env_set(
 
 2323      exec, 
"if", 2, MLISP_TYPE_CB, _mlisp_env_cb_if,
 
 2324      0, MLISP_ENV_FLAG_BUILTIN );
 
 2325   maug_cleanup_if_not_ok();
 
 2327   retval = mlisp_env_set(
 
 2328      exec, 
"define", 6, MLISP_TYPE_CB, _mlisp_env_cb_define,
 
 2329      0, MLISP_ENV_FLAG_BUILTIN );
 
 2330   maug_cleanup_if_not_ok();
 
 2332   retval = mlisp_env_set(
 
 2333      exec, 
"*", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
 
 2335   maug_cleanup_if_not_ok();
 
 2337   retval = mlisp_env_set(
 
 2338      exec, 
"+", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
 
 2340   maug_cleanup_if_not_ok();
 
 2342   retval = mlisp_env_set(
 
 2343      exec, 
"/", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
 
 2344      0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ARI_DIV );
 
 2345   maug_cleanup_if_not_ok();
 
 2347   retval = mlisp_env_set(
 
 2348      exec, 
"%", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
 
 2349      0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ARI_MOD );
 
 2350   maug_cleanup_if_not_ok();
 
 2352   retval = mlisp_env_set(
 
 2353      exec, 
"<", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
 
 2355   maug_cleanup_if_not_ok();
 
 2357   retval = mlisp_env_set(
 
 2358      exec, 
">", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
 
 2360   maug_cleanup_if_not_ok();
 
 2362   retval = mlisp_env_set(
 
 2363      exec, 
"=", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
 
 2365   maug_cleanup_if_not_ok();
 
 2378   ssize_t append_retval = 0;
 
 2380   int16_t null_val = 0;
 
 2382   assert( 0 == exec->
flags );
 
 2386   exec->
flags = flags;
 
 2387   exec->uid = g_mlispe_last_uid++;
 
 2392   if( 0 > append_retval ) {
 
 2393      retval = mdata_retval( append_retval );
 
 2395   maug_cleanup_if_not_ok();
 
 2401   retval = mlisp_env_set(
 
 2402      exec, 
"null", 4, MLISP_TYPE_INT, &null_val, 0, 0 );
 
 2407   if( 0 > append_retval ) {
 
 2408      retval = mdata_retval( append_retval );
 
 2410   maug_cleanup_if_not_ok();
 
 2419      if( 0 > append_retval ) {
 
 2420         retval = mdata_retval( append_retval );
 
 2422      maug_cleanup_if_not_ok();
 
 2428   if( 0 > append_retval ) {
 
 2429      retval = mdata_retval( append_retval );
 
 2431   maug_cleanup_if_not_ok();
 
 2440      if( 0 > append_retval ) {
 
 2441         retval = mdata_retval( append_retval );
 
 2443      maug_cleanup_if_not_ok();
 
 2446   exec->
flags |= MLISP_EXEC_FLAG_INITIALIZED;
 
 2450   retval = mlisp_exec_add_env_builtins( parser, exec );
 
 2454   if( MERROR_OK != retval ) {
 
 2455      error_printf( 
"mlisp exec initialization failed: %d", retval );
 
 2468   int16_t null_val = 0;
 
 2470   exec->global_env = global_env;
 
 2472   if( 0 == mdata_table_ct( global_env ) ) {
 
 2477      retval = mlisp_env_set(
 
 2478         exec, 
"null", 4, MLISP_TYPE_INT, &null_val, 1, 0 );
 
 2487   int8_t env_iter = 0;
 
 2489#if MLISP_EXEC_TRACE_LVL > 0 
 2490   debug_printf( MLISP_EXEC_TRACE_LVL,
 
 2491         "%u: destroying exec (stack: " SIZE_T_FMT 
", env: " SIZE_T_FMT 
")...",
 
 2498   mdata_vector_free( &(exec->
stack) );
 
 2499   for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
 
 2500      mdata_table_free( &(exec->
env[env_iter]) );
 
 2504#if MLISP_EXEC_TRACE_LVL > 0 
 2505   debug_printf( MLISP_EXEC_TRACE_LVL, 
"exec destroyed!" );
 
 2524#  define MLISP_PSTATE_TABLE_CONST( name, idx ) \ 
 2525      extern MAUG_CONST uint8_t SEG_MCONST name; 
 2527MLISP_PARSER_PSTATE_TABLE( MLISP_PSTATE_TABLE_CONST )
 
 2529#ifdef MPARSER_TRACE_NAMES 
 2530extern MAUG_CONST 
char* SEG_MCONST gc_mlisp_pstate_names[];
 
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:19
#define MERROR_PREEMPT
Indicates MLISP_AST_NODE can be executed again on next step iter pass.
Definition: merror.h:58
#define MERROR_RESET
Indicates MLISP_EXEC_STATE has reached a condition where it has run out of instructions.
Definition: merror.h:64
MAUG_MHANDLE mdata_strpool_extract(struct MDATA_STRPOOL *sp, mdata_strpool_idx_t idx)
Return a dynamically-allocated memory handle containing the contents of the string at the given index...
ssize_t mdata_vector_append(struct MDATA_VECTOR *v, const void *item, size_t item_sz)
Append an item to the specified vector.
MERROR_RETVAL mdata_vector_remove(struct MDATA_VECTOR *v, size_t idx)
Remove item at the given index, shifting subsequent items up by 1.
#define mlisp_check_ast(parser)
Macro to check if a parser contains a valid AST ready to be executed.
Definition: mlispp.h:77
MERROR_RETVAL mlisp_stack_dump(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec)
Dump the stack from the given parser/exec combination.
#define mlisp_stack_pop(exec, o)
Wrapper for mlisp_stack_pop() with no flags.
Definition: mlispe.h:107
#define MLISP_STACK_FLAG_PEEK
Flag for mlisp_stack_pop_ex() indicating the value should not be removed from the stack.
Definition: mlispe.h:102
#define mlisp_stack_push(exec, i, ctype)
Push a value onto MLISP_EXEC_STATE::stack.
Definition: mlispe.h:117
MERROR_RETVAL mlisp_stack_pop_ex(struct MLISP_EXEC_STATE *exec, struct MLISP_STACK_NODE *o, uint8_t flags)
Pop a value off of (removing from) MLISP_EXEC_STATE::stack and copy it to a provided output.
#define MLISP_TYPE_TABLE(f)
Table of other types.
Definition: mlisps.h:74
#define MLISP_NUM_TYPE_TABLE(f)
Table of numeric types.
Definition: mlisps.h:64
MERROR_RETVAL mlisp_exec_set_global_env(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec, struct MDATA_TABLE *global_env)
Set the given exec state to use the given vector as a global variable environment....
#define MLISP_ENV_FLAG_CMP_GT
Flag for _mlisp_env_cb_cmp() specifying TRUE if A > B.
Definition: mlispe.h:58
MERROR_RETVAL(* mlisp_env_cb_t)(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec, size_t n_idx, size_t args_c, uint8_t *cb_data, uint8_t flags)
A callback to attach to an mlisp command with mlisp_env_set() with MLISP_TYPE_CB.
Definition: mlisps.h:92
#define MLISP_ENV_FLAG_ARI_MUL
Flag for _mlisp_env_cb_arithmetic() specifying to multiply A * B.
Definition: mlispe.h:70
MERROR_RETVAL mlisp_step(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec)
Iterate the current exec_state() starting from the next MLISP_AST_NODE to be executed according to th...
#define MLISP_ENV_FLAG_ARI_ADD
Flag for _mlisp_env_cb_arithmetic() specifying to add A + B.
Definition: mlispe.h:67
#define MLISP_ENV_FLAG_CMP_EQ
Flag for _mlisp_env_cb_cmp() specifying TRUE if A == B.
Definition: mlispe.h:64
MERROR_RETVAL mlisp_env_dump(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec, uint8_t global)
Dump the environment from the given parser/exec combination.
MERROR_RETVAL mlisp_step_lambda(struct MLISP_PARSER *parser, struct MLISP_EXEC_STATE *exec, const char *lambda)
Iterate the current exec_state() starting from the lambda named.
#define MLISP_ENV_FLAG_CMP_LT
Flag for _mlisp_env_cb_cmp() specifying TRUE if A < B.
Definition: mlispe.h:61
#define MLISP_ENV_FLAG_DEFINE_GLOBAL
Flag for _mlisp_env_cb_define() specifying global env.
Definition: mlispe.h:81
MLISP Interpreter/Parser Structs.
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:320
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:353
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:396
size_t ast_idx_children_sz
Number of children in MLISP_AST_NODE::ast_idx_children.
Definition: mlisps.h:126
Current execution state to associate with a MLISP_PARSER.
Definition: mlisps.h:136
struct MDATA_VECTOR lambda_trace
Path through any lambdas the execution has entered during this heartbeat cycle. Used to detect tail c...
Definition: mlisps.h:184
#define MLISP_EXEC_FLAG_TRANSIENT_MASK
Mask for MLISP_EXEC_STATE::flags to block off flags that persist between steps.
Definition: mlisps.h:34
struct MDATA_VECTOR per_node_child_idx
The hild index that will be visited on next visit of each node.
Definition: mlisps.h:151
struct MDATA_VECTOR per_node_visit_ct
The number of times each node has been visited ever.
Definition: mlisps.h:143
#define MLISP_EXEC_FLAG_DEF_TERM
Flag for MLISP_EXEC_STATE::flags indicating next token is a term to be defined.
Definition: mlisps.h:41
struct MDATA_VECTOR stack
A stack of data values resulting from evaluating statements.
Definition: mlisps.h:154
uint8_t flags
Flags which dictate the behavior of this object.
Definition: mlisps.h:140
struct MDATA_TABLE env[MLISP_EXEC_ENV_FRAME_CT_MAX]
Environment in which statements are defined if ::MLISP_.
Definition: mlisps.h:171
int8_t env_select
The current topmost frame of MLISP_EXEC_STATE::env. Please see that for more information.
Definition: mlisps.h:176