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 );
304 mdata_vector_lock( &(parser->ast) );
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])
349 mdata_vector_unlock( &(parser->ast) );
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 );
379 mdata_vector_lock( &(exec->
stack) );
380 mdata_strpool_lock( &(parser->strpool) ); \
381 while( i < mdata_vector_ct( &(exec->
stack) ) ) {
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) );
430 mdata_vector_unlock( &(exec->
stack) );
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 ); \
477 mdata_vector_ct( &(exec->
stack) ), 0, SIZE_T_FMT, MERROR_OVERFLOW );
479 n_idx = mdata_vector_ct( &(exec->
stack) ) - 1;
482 mdata_vector_lock( &(exec->
stack) );
483 n_stack = mdata_vector_get(
485 assert( NULL != n_stack );
488 mdata_vector_unlock( &(exec->
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 ); \
509 retval = mdata_vector_remove( &(exec->
stack), n_idx );
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 );
1398 exec->
flags |= MLISP_EXEC_FLAG_DEF_TERM;
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",
1616 append_retval = mdata_vector_append(
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",
1736 i = mdata_vector_ct( &(exec->
stack) ) - 1;
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();
1950 if( MLISP_EXEC_FLAG_DEF_TERM == (MLISP_EXEC_FLAG_DEF_TERM & exec->
flags) ) {
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) ) );
2165 mdata_vector_lock( &(parser->ast) );
2168 exec->
flags &= MLISP_EXEC_FLAG_TRANSIENT_MASK;
2169 assert( 0 == mdata_vector_ct( &(exec->
lambda_trace) ) );
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) ) );
2219 mdata_vector_unlock( &(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++;
2390 append_retval = mdata_vector_append(
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 );
2405 append_retval = mdata_vector_append(
2407 if( 0 > append_retval ) {
2408 retval = mdata_retval( append_retval );
2410 maug_cleanup_if_not_ok();
2415 mdata_vector_ct( &(parser->ast) )
2419 if( 0 > append_retval ) {
2420 retval = mdata_retval( append_retval );
2422 maug_cleanup_if_not_ok();
2426 append_retval = mdata_vector_append(
2428 if( 0 > append_retval ) {
2429 retval = mdata_retval( append_retval );
2431 maug_cleanup_if_not_ok();
2436 mdata_vector_ct( &(parser->ast) )
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
")...",
2493 mdata_vector_ct( &(exec->
stack) ),
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...
#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.
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
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
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