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 )
146#if defined( MLISP_DUMP_ENABLED ) || defined( DOCUMENTATION )
167 const char* token,
size_t token_sz, uint8_t env_type,
const void* data,
168 uint8_t global, uint8_t flags );
196 const char* lambda );
217#define _MLISP_TYPE_TABLE_PUSH_PROTO( idx, ctype, name, const_name, fmt ) \
218 MERROR_RETVAL _mlisp_stack_push_ ## ctype( \
219 struct MLISP_EXEC_STATE* exec, ctype i );
225#define mlisp_ast_has_ready_children( exec_child_idx, n ) \
226 ((exec_child_idx) < (n)->ast_idx_children_sz)
230uint16_t g_mlispe_last_uid = 0;
256 uint8_t mask, uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX]
261 maug_mzero( autolock, MLISP_EXEC_ENV_FRAME_CT_MAX );
264 if( MLISP_AUTOLOCK_EXEC_ENV == (MLISP_AUTOLOCK_EXEC_ENV & mask) ) {
265 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
266 if( !mdata_table_is_locked( &(exec->
env[env_iter]) ) ) {
267#if MLISP_EXEC_TRACE_LVL > 0
268 debug_printf( MLISP_EXEC_TRACE_LVL,
269 "%u: engaging autolock for exec env frame %d...",
270 exec->uid, env_iter );
272 mdata_table_lock( &(exec->
env[env_iter]) );
273 autolock[env_iter] |= MLISP_AUTOLOCK_EXEC_ENV;
278 MLISP_AUTOLOCK_CHILD_IDX == (MLISP_AUTOLOCK_CHILD_IDX & mask) &&
281#if MLISP_EXEC_TRACE_LVL > 0
282 debug_printf( MLISP_EXEC_TRACE_LVL,
283 "%u: engaging autolock for exec per-node child index...", exec->uid );
286 autolock[0] |= MLISP_AUTOLOCK_CHILD_IDX;
289 MLISP_AUTOLOCK_VISIT_CT == (MLISP_AUTOLOCK_VISIT_CT & mask) &&
292#if MLISP_EXEC_TRACE_LVL > 0
293 debug_printf( MLISP_EXEC_TRACE_LVL,
294 "%u: engaging autolock for per-node visit count...", exec->uid );
297 autolock[0] |= MLISP_AUTOLOCK_VISIT_CT;
300 MLISP_AUTOLOCK_PARSER_AST == (MLISP_AUTOLOCK_PARSER_AST & mask) &&
301 !mdata_vector_is_locked( &(parser->ast) )
303#if MLISP_EXEC_TRACE_LVL > 0
304 debug_printf( MLISP_EXEC_TRACE_LVL,
305 "%u: engaging autolock for parser AST...", exec->uid );
307 mdata_vector_lock( &(parser->ast) );
308 autolock[0] |= MLISP_AUTOLOCK_PARSER_AST;
311 MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & mask) &&
312 NULL != exec->global_env &&
313 0 < mdata_table_ct( exec->global_env ) &&
314 !mdata_table_is_locked( exec->global_env )
316#if MLISP_EXEC_TRACE_LVL > 0
317 debug_printf( MLISP_EXEC_TRACE_LVL,
318 "%u: engaging autolock for global env...", exec->uid );
320 mdata_table_lock( exec->global_env );
321 autolock[0] |= MLISP_AUTOLOCK_GLOBAL_ENV;
330static void _mlisp_autounlock(
332 uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX]
335 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
337 MLISP_AUTOLOCK_EXEC_ENV ==
338 (MLISP_AUTOLOCK_EXEC_ENV & autolock[env_iter])
340 mdata_table_unlock( &(exec->
env[env_iter]) );
343 if( MLISP_AUTOLOCK_CHILD_IDX == (MLISP_AUTOLOCK_CHILD_IDX & autolock[0]) ) {
346 if( MLISP_AUTOLOCK_VISIT_CT == (MLISP_AUTOLOCK_VISIT_CT & autolock[0]) ) {
350 MLISP_AUTOLOCK_PARSER_AST == (MLISP_AUTOLOCK_PARSER_AST & autolock[0])
352 mdata_vector_unlock( &(parser->ast) );
355 MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & autolock[0])
357 mdata_table_unlock( exec->global_env );
367#ifdef MLISP_DUMP_ENABLED
376# define _MLISP_TYPE_TABLE_DUMPS( idx, ctype, name, const_name, fmt ) \
377 } else if( MLISP_TYPE_ ## const_name == n_stack->type ) { \
378 debug_printf( MLISP_STACK_TRACE_LVL, \
379 "%u: " MLISP_TRACE_SIGIL " stack " SIZE_T_FMT " (" #const_name "): " fmt, \
380 exec->uid, i, n_stack->value.name );
382 mdata_vector_lock( &(exec->
stack) );
383 mdata_strpool_lock( &(parser->strpool) ); \
384 while( i < mdata_vector_ct( &(exec->
stack) ) ) {
388 if( MLISP_TYPE_STR == n_stack->type ) {
390 "%u: " MLISP_TRACE_SIGIL
" stack " SIZE_T_FMT
" (STR): %s",
391 exec->uid, i, mdata_strpool_get(
392 &(parser->strpool), n_stack->value.strpool_idx ) );
394 }
else if( MLISP_TYPE_CB == n_stack->type ) {
396 "%u: " MLISP_TRACE_SIGIL
" stack " SIZE_T_FMT
" (CB): %p",
397 exec->uid, i, n_stack->value.cb );
399 }
else if( MLISP_TYPE_LAMBDA == n_stack->type ) {
401 "%u: " MLISP_TRACE_SIGIL
" stack " SIZE_T_FMT
" (LAMBDA): "
403 exec->uid, i, n_stack->value.lambda );
419 }
else if( MLISP_TYPE_BEGIN == n_stack->type ) {
421 "%u: " MLISP_TRACE_SIGIL
" stack " SIZE_T_FMT
" (BEGIN): "
423 exec->uid, i, n_stack->value.begin );
428 error_printf(
"invalid stack type: %u", n_stack->type );
432 mdata_strpool_unlock( &(parser->strpool) );
433 mdata_vector_unlock( &(exec->
stack) );
437 assert( mdata_strpool_is_locked( &(parser->strpool) ) );
446#define _MLISP_TYPE_TABLE_PUSH( idx, ctype, name, const_name, fmt ) \
447 MERROR_RETVAL _mlisp_stack_push_ ## ctype( \
448 struct MLISP_EXEC_STATE* exec, ctype i \
450 struct MLISP_STACK_NODE n_stack; \
451 MERROR_RETVAL retval = MERROR_OK; \
452 debug_printf( MLISP_STACK_TRACE_LVL, \
453 "%u: pushing " #const_name " onto stack: " fmt, exec->uid, i ); \
454 n_stack.type = MLISP_TYPE_ ## const_name; \
455 n_stack.value.name = i; \
456 retval = mdata_vector_append( \
457 &(exec->stack), &n_stack, sizeof( struct MLISP_STACK_NODE ) ); \
459 retval = mdata_retval( retval ); \
478 if( mdata_vector_ct( &(exec->
stack) ) == 0 ) {
479 error_printf(
"stack underflow!" );
480 retval = MERROR_OVERFLOW;
484 n_idx = mdata_vector_ct( &(exec->
stack) ) - 1;
487 mdata_vector_lock( &(exec->
stack) );
488 n_stack = mdata_vector_get(
490 assert( NULL != n_stack );
493 mdata_vector_unlock( &(exec->
stack) );
495#if MLISP_STACK_TRACE_LVL > 0
496# define _MLISP_TYPE_TABLE_POPD( idx, ctype, name, const_name, fmt ) \
497 } else if( MLISP_TYPE_ ## const_name == o->type ) { \
498 if( MLISP_STACK_FLAG_PEEK == (MLISP_STACK_FLAG_PEEK & flags) ) { \
499 debug_printf( MLISP_STACK_TRACE_LVL, \
500 "%u: peeking (%ut): " SSIZE_T_FMT ": " fmt, \
501 exec->uid, n_idx, o->type, o->value.name ); \
503 debug_printf( MLISP_STACK_TRACE_LVL, \
504 "%u: popping (%ut): " SSIZE_T_FMT ": " fmt, \
505 exec->uid, n_idx, o->type, o->value.name ); \
514 retval = mdata_vector_remove( &(exec->
stack), n_idx );
528#if defined( MLISP_DUMP_ENABLED )
532 void* cb_data,
size_t cb_data_sz,
size_t idx
541# define _MLISP_TYPE_TABLE_DUMPE( idx, ctype, name, const_name, fmt ) \
542 } else if( MLISP_TYPE_ ## const_name == e->type ) { \
544 "%u: " MLISP_TRACE_SIGIL " env \"%s\" (" #const_name "): " fmt, \
545 exec->uid, key->string, e->value.name );
547 if( MLISP_ENV_FLAG_BUILTIN == (MLISP_ENV_FLAG_BUILTIN & e->flags) ) {
552 debug_printf( 1,
"%s: %p: 0x%02x", key, e, e->type );
557 }
else if( MLISP_TYPE_STR == e->type ) {
559 "%u: " MLISP_TRACE_SIGIL
" env \"%s\" (STR): %s",
561 mdata_strpool_get( &(parser.strpool), e->value.strpool_idx ) );
563 }
else if( MLISP_TYPE_CB == e->type ) {
565 "%u: " MLISP_TRACE_SIGIL
" env \"%s\" (CB): %p",
566 exec->uid, key, e->value.cb );
568 }
else if( MLISP_TYPE_LAMBDA == e->type ) {
570 "%u: " MLISP_TRACE_SIGIL
" env \"%s\" (LAMBDA): " SIZE_T_FMT,
571 exec->uid, key, e->value.lambda );
574 error_printf( MLISP_TRACE_SIGIL
" invalid env type: %u", e->type );
587 uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
589 retval = _mlisp_autolock(
590 NULL, exec, MLISP_AUTOLOCK_EXEC_ENV | MLISP_AUTOLOCK_GLOBAL_ENV,
592 maug_cleanup_if_not_ok();
595 debug_printf( 1,
"# global env:" );
596 retval = mdata_table_iter(
597 exec->global_env, _mlisp_env_dump_iter, exec, 0 );
599 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
600 debug_printf( 1,
"# env frame %d:", env_iter );
601 retval = mdata_table_iter(
602 &(exec->
env[env_iter]), _mlisp_env_dump_iter, exec, 0 );
603 maug_cleanup_if_not_ok();
609 _mlisp_autounlock( NULL, exec, autolock );
626 while( 0 <= env_iter ) {
627 env = &(exec->
env[env_iter]);
633 assert( mdata_table_is_locked( env ) );
648 if( NULL != exec->global_env ) {
649 assert( mdata_table_is_locked( exec->global_env ) );
650 e = mdata_table_get( exec->global_env, key,
struct MLISP_ENV_NODE );
655 if( MERROR_OK != retval ) {
669 uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
675 maug_mzero( autolock, MLISP_EXEC_ENV_FRAME_CT_MAX );
677 while( 0 <= env_iter ) {
678#if MLISP_EXEC_TRACE_LVL > 0
679 debug_printf( MLISP_EXEC_TRACE_LVL,
680 "%u: attempting to undefine %s in frame %d...",
681 exec->uid, token, env_iter );
684 env = &(exec->
env[env_iter]);
686 if( !mdata_table_is_locked( env ) ) {
687 mdata_table_lock( env );
688 autolock[env_iter] |= 0x02;
691 retval = mdata_table_unset( env, token );
696 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
697 if( 0x02 == (0x02 & autolock[env_iter]) ) {
698 env = &(exec->
env[env_iter]);
699 assert( mdata_table_is_locked( env ) );
700 mdata_table_unlock( env );
711 const char* token,
size_t token_sz, uint8_t env_type,
const void* data,
712 uint8_t global, uint8_t flags
720 (MLISP_ENV_FLAG_BUILTIN != (MLISP_ENV_FLAG_BUILTIN & flags)) ||
726 if( NULL != exec->global_env ) {
727 env = exec->global_env;
729 error_printf(
"global env requested but not present!" );
730 retval = MERROR_EXEC;
735 if( 0 == token_sz ) {
736 token_sz = maug_strlen( token );
739 assert( NULL != env );
740 assert( 0 < token_sz );
742 assert( !mdata_table_is_locked( env ) );
746 mdata_table_unset( env, token );
748#if MLISP_EXEC_TRACE_LVL > 0
749# define _MLISP_TYPE_TABLE_ASGN( idx, ctype, name, const_name, fmt ) \
751 debug_printf( MLISP_EXEC_TRACE_LVL, \
752 "%u: setting env %d: \"%s\": #" fmt, \
753 exec->uid, exec->env_select, token, (ctype)*((ctype*)data) ); \
754 e.value.name = *((ctype*)data); \
757# define _MLISP_TYPE_TABLE_ASGN( idx, ctype, name, const_name, fmt ) \
759 e.value.name = *((ctype*)data); \
766 maug_cleanup_if_not_ok();
775#if MLISP_EXEC_TRACE_LVL > 0
776 debug_printf( MLISP_EXEC_TRACE_LVL,
777 "%u: setting env %d: \"%s\": strpool(" SSIZE_T_FMT
")",
778 exec->uid, exec->
env_select, token, *((ssize_t*)data) );
780 e.value.strpool_idx = *((mdata_strpool_idx_t*)data);
784#if MLISP_EXEC_TRACE_LVL > 0
785 debug_printf( MLISP_EXEC_TRACE_LVL,
786 "%u: setting env %d: \"%s\": 0x%p",
793#if MLISP_EXEC_TRACE_LVL > 0
794 debug_printf( MLISP_EXEC_TRACE_LVL,
795 "%u: setting env %d: \"%s\": node #" SSIZE_T_FMT,
796 exec->uid, exec->
env_select, token, *((mlisp_lambda_t*)data) );
798 e.value.lambda = *((mlisp_lambda_t*)data);
813 "%u: underflow %s: missing lambda arg?",
819 error_printf(
"invalid type: %d", env_type );
820 retval = MERROR_EXEC;
824 retval = mdata_table_set( env, token, &e,
sizeof(
struct MLISP_ENV_NODE ) );
835 size_t args_c,
void* cb_data, uint8_t flags
846 mdata_strpool_lock( &(parser->strpool) );
850#if MLISP_EXEC_TRACE_LVL > 0
851# define _MLISP_TYPE_TABLE_CMP( idx, ctype, name, const_name, fmt ) \
852 } else if( MLISP_TYPE_ ## const_name == tmp.type ) { \
853 *cur_int = (int)tmp.value.name; \
854 debug_printf( MLISP_EXEC_TRACE_LVL, \
855 "%u: cmp: pop " fmt " (%d)", exec->uid, tmp.value.name, *cur_int );
857# define _MLISP_TYPE_TABLE_CMP( idx, ctype, name, const_name, fmt ) \
858 } else if( MLISP_TYPE_ ## const_name == tmp.type ) { \
859 *cur_int = (int)tmp.value.name;
863 maug_cleanup_if_not_ok();
865 if( MLISP_TYPE_STR == tmp.type ) {
867 a_type = MLISP_TYPE_STR;
871 error_printf(
"cmp: invalid type: %d", tmp.type );
872 retval = MERROR_EXEC;
877 maug_cleanup_if_not_ok();
879 if( MLISP_TYPE_STR == tmp.type ) {
881 b_type = MLISP_TYPE_STR;
885 error_printf(
"cmp: invalid type!" );
886 retval = MERROR_EXEC;
891 if( MLISP_TYPE_STR == a_type || MLISP_TYPE_STR == b_type ) {
900#if MLISP_EXEC_TRACE_LVL > 0
901 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: cmp %d > %d",
902 exec->uid, a_int, b_int );
904 truth = a_int > b_int;
906#if MLISP_EXEC_TRACE_LVL > 0
907 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: cmp %d < %d",
908 exec->uid, a_int, b_int );
910 truth = a_int < b_int;
912#if MLISP_EXEC_TRACE_LVL > 0
913 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: cmp %d == %d",
914 exec->uid, a_int, b_int );
916 truth = a_int == b_int;
918 error_printf(
"invalid parameter provided to _mlisp_env_cb_cmp()!" );
919 retval = MERROR_EXEC;
927 mdata_strpool_unlock( &(parser->strpool) );
936 size_t args_c,
void* cb_data, uint8_t flags
944# define _MLISP_TYPE_TABLE_ARI1( idx, ctype, name, const_name, fmt ) \
945 } else if( MLISP_TYPE_ ## const_name == num.type ) { \
946 num_out = num.value.name;
949 maug_cleanup_if_not_ok();
954 error_printf(
"arithmetic: invalid type!" );
955 retval = MERROR_EXEC;
959# define _MLISP_TYPE_TABLE_ARI2( idx, ctype, name, const_name, fmt ) \
961 MLISP_TYPE_ ## const_name == num.type && \
962 MLISP_ENV_FLAG_ARI_ADD == (MLISP_ENV_FLAG_ARI_ADD & flags) \
964 debug_printf( MLISP_EXEC_TRACE_LVL, \
965 "%u: arithmetic: %d + " fmt, exec->uid, num_out, num.value.name ); \
966 num_out += num.value.name; \
968 MLISP_TYPE_ ## const_name == num.type && \
969 MLISP_ENV_FLAG_ARI_MUL == (MLISP_ENV_FLAG_ARI_MUL & flags) \
971 debug_printf( MLISP_EXEC_TRACE_LVL, \
972 "%u: arithmetic: %d * " fmt, exec->uid, num_out, num.value.name ); \
973 num_out *= num.value.name; \
975 MLISP_TYPE_ ## const_name == num.type && \
976 MLISP_ENV_FLAG_ARI_DIV == (MLISP_ENV_FLAG_ARI_DIV & flags) \
978 debug_printf( MLISP_EXEC_TRACE_LVL, \
979 "%u: arithmetic: %d / " fmt, exec->uid, num_out, num.value.name ); \
980 num_out /= num.value.name; \
982 for( i = 0 ; args_c - 1 > i ; i++ ) {
984 maug_cleanup_if_not_ok();
990 MLISP_TYPE_INT == num.type &&
991 MLISP_ENV_FLAG_ARI_MOD == (MLISP_ENV_FLAG_ARI_MOD & flags)
994 debug_printf( MLISP_EXEC_TRACE_LVL,
995 "%u: arithmetic: %d %% %d", exec->uid, num_out, num.value.integer );
996 num_out %= num.value.integer;
998 error_printf(
"arithmetic: invalid type!" );
999 retval = MERROR_EXEC;
1004 debug_printf( MLISP_EXEC_TRACE_LVL,
1005 "%u: arithmetic result: %d", exec->uid, num_out );
1011 mdata_strpool_unlock( &(parser->strpool) );
1020 size_t args_c,
void* cb_data, uint8_t flags
1025 MAUG_MHANDLE key_tmp_h = (MAUG_MHANDLE)NULL;
1026 char* key_tmp = NULL;
1030 maug_cleanup_if_not_ok();
1033 maug_cleanup_if_not_ok();
1035 if( MLISP_TYPE_STR != key.type ) {
1038 error_printf(
"define: invalid key type: %d", key.type );
1039 retval = MERROR_EXEC;
1044 &(parser->strpool), key.value.strpool_idx );
1046 assert( (MAUG_MHANDLE)NULL != key_tmp_h );
1048 maug_mlock( key_tmp_h, key_tmp );
1049 maug_cleanup_if_null_lock(
char*, key_tmp );
1051#if MLISP_EXEC_TRACE_LVL > 0
1052 debug_printf( MLISP_EXEC_TRACE_LVL,
1053 "%u: define \"%s\" (strpool(" SIZE_T_FMT
"))...",
1054 exec->uid, key_tmp, key.value.strpool_idx );
1061#if MLISP_EXEC_TRACE_LVL > 0
1062 debug_printf( MLISP_EXEC_TRACE_LVL,
1063 "%u: using global env...", exec->uid );
1069 retval = mlisp_env_set(
1070 exec, key_tmp, maug_strlen( key_tmp ), val.type, &(val.value),
1072 maug_cleanup_if_not_ok();
1074#if MLISP_EXEC_TRACE_LVL > 0
1075 debug_printf( MLISP_EXEC_TRACE_LVL,
1076 "%u: setup env node: %s",
1077 exec->uid, key_tmp );
1082 if( NULL != key_tmp ) {
1083 maug_munlock( key_tmp_h, key_tmp );
1086 if( (MAUG_MHANDLE)NULL != key_tmp_h ) {
1087 maug_mfree( key_tmp_h );
1097 size_t args_c,
void* cb_data, uint8_t flags
1100 size_t* p_if_child_idx = NULL;
1104#if MLISP_EXEC_TRACE_LVL > 0
1105 debug_printf( MLISP_EXEC_TRACE_LVL,
1106 "%u: qrqrqrqrqr STEP IF qrqrqrqrqr", exec->uid );
1111 p_if_child_idx = mdata_vector_get(
1113 assert( NULL != p_if_child_idx );
1114#if MLISP_EXEC_TRACE_LVL > 0
1115 debug_printf( MLISP_EXEC_TRACE_LVL,
1116 "%u: node " SIZE_T_FMT
" child idx: " SIZE_T_FMT,
1117 exec->uid, n_idx, *p_if_child_idx );
1120 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1122 if( 0 == *p_if_child_idx ) {
1124#if MLISP_EXEC_TRACE_LVL > 0
1125 debug_printf( MLISP_EXEC_TRACE_LVL,
1126 "%u: stepping into condition...", exec->uid );
1128 retval = _mlisp_step_iter(
1129 parser, n->ast_idx_children[*p_if_child_idx], exec );
1130#if MLISP_EXEC_TRACE_LVL > 0
1131 debug_printf( MLISP_EXEC_TRACE_LVL,
1132 "%u: ...stepped out of condition", exec->uid );
1136 if( MERROR_OK == retval ) {
1141 maug_cleanup_if_not_ok();
1142 if( MLISP_TYPE_BOOLEAN != s.type ) {
1143 error_printf(
"(if) can only evaluate boolean type!" );
1144 retval = MERROR_EXEC;
1149 retval = _mlisp_preempt(
1150 retval,
"if", parser, n_idx, exec,
1152 (1 - s.value.boolean) + 1 );
1155 }
else if( args_c > *p_if_child_idx ) {
1158#if MLISP_EXEC_TRACE_LVL > 0
1159 debug_printf( MLISP_EXEC_TRACE_LVL,
1160 "%u: descending into IF path: " SIZE_T_FMT,
1161 exec->uid, *p_if_child_idx );
1167 retval = _mlisp_step_iter(
1168 parser, n->ast_idx_children[*p_if_child_idx], exec );
1169 retval = _mlisp_preempt(
1170 retval,
"if", parser, n_idx, exec, 3 );
1175#if MLISP_EXEC_TRACE_LVL > 0
1176 debug_printf( MLISP_EXEC_TRACE_LVL,
1177 "%u: qrqrqrqrqr END STEP IF qrqrqrqrqr", exec->uid );
1185#ifndef MAUG_NO_RETRO
1191 size_t args_c,
void* cb_data, uint8_t flags
1195 int16_t random_int = 0;
1198 maug_cleanup_if_not_ok();
1200 if( MLISP_TYPE_INT != mod.type ) {
1202 error_printf(
"random: invalid modulus type: %d", mod.type );
1203 retval = MERROR_EXEC;
1207 random_int = retroflat_get_rand() % mod.value.integer;
1209#if MLISP_EXEC_TRACE_LVL > 0
1210 debug_printf( MLISP_EXEC_TRACE_LVL,
1211 "%u: random: %d", exec->uid, random_int );
1227 size_t args_c,
void* cb_data, uint8_t flags
1231 mlisp_bool_t val_out =
1232 MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ?
1240 for( i = 0 ; args_c > i ; i++ ) {
1242 maug_cleanup_if_not_ok();
1244 if( MLISP_TYPE_BOOLEAN != val.type ) {
1245 error_printf(
"or: invalid boolean type: %d", val.type );
1248 if( val.value.boolean ) {
1249#if MLISP_EXEC_TRACE_LVL > 0
1250 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: found TRUE in %s!",
1252 MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ?
1256 MLISP_ENV_FLAG_ANO_OR == (MLISP_ENV_FLAG_ANO_OR & flags) ? 1 : 0;
1260 retval = _mlisp_stack_push_mlisp_bool_t( exec, val_out );
1278 size_t* p_child_idx = NULL;
1281 p_child_idx = mdata_vector_get(
1283 assert( NULL != p_child_idx );
1285 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1287 if( 0 <= n->token_idx ) {
1288 mdata_strpool_lock( &(parser->strpool) );
1289#if MLISP_EXEC_TRACE_LVL > 0
1290 debug_printf( MLISP_EXEC_TRACE_LVL,
1291 "%u: eval step " SSIZE_T_FMT
" under (%s) %s...",
1292 exec->uid, *p_child_idx, caller,
1293 mdata_strpool_get( &(parser->strpool), n->token_idx ) );
1295 mdata_strpool_unlock( &(parser->strpool) );
1296#if MLISP_EXEC_TRACE_LVL > 0
1298 debug_printf( MLISP_EXEC_TRACE_LVL,
1299 "%u: eval step " SSIZE_T_FMT
" under (%s) (empty token)...",
1300 exec->uid, *p_child_idx, caller );
1304 if( MERROR_OK != retval ) {
1306#if MLISP_EXEC_TRACE_LVL > 0
1307 debug_printf( MLISP_EXEC_TRACE_LVL,
1308 "%u: not incrementing node " SIZE_T_FMT
" child idx from "
1309 SIZE_T_FMT
" (retval: 0x%x)!",
1310 exec->uid, n_idx, *p_child_idx, retval );
1319 (*p_child_idx) = new_idx;
1320#if MLISP_EXEC_TRACE_LVL > 0
1321 debug_printf( MLISP_EXEC_TRACE_LVL,
1322 "%u: incremented node " SIZE_T_FMT
" child idx to: " SIZE_T_FMT,
1323 exec->uid, n_idx, *p_child_idx );
1328 assert( !mdata_strpool_is_locked( &(parser->strpool) ) );
1339 size_t* p_child_idx = NULL;
1344 p_child_idx = mdata_vector_get(
1346 assert( NULL != p_child_idx );
1347#if MLISP_EXEC_TRACE_LVL > 0
1348 debug_printf( MLISP_EXEC_TRACE_LVL,
1349 "%u: node " SIZE_T_FMT
" child idx: " SIZE_T_FMT,
1350 exec->uid, n_idx, *p_child_idx );
1353 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1357 MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) &&
1360 MLISP_AST_FLAG_IF == (MLISP_AST_FLAG_IF & n->flags)
1369#if MLISP_EXEC_TRACE_LVL > 0
1370 debug_printf( MLISP_EXEC_TRACE_LVL,
1371 "%u: skipping lambda children...", exec->uid );
1376 if( mlisp_ast_has_ready_children( *p_child_idx, n ) ) {
1380 MLISP_AST_FLAG_DEFINE == (MLISP_AST_FLAG_DEFINE & n->flags) &&
1384#if MLISP_EXEC_TRACE_LVL > 0
1385 debug_printf( MLISP_EXEC_TRACE_LVL,
1386 "%u: setting MLISP_EXEC_FLAG_DEF_TERM!", exec->uid );
1388 exec->
flags |= MLISP_EXEC_FLAG_DEF_TERM;
1390 exec->
flags &= ~MLISP_EXEC_FLAG_DEF_TERM;
1394 retval = _mlisp_step_iter(
1395 parser, n->ast_idx_children[*p_child_idx], exec );
1396 retval = _mlisp_preempt(
1397 retval,
"node", parser, n_idx, exec, (*p_child_idx) + 1 );
1412 ssize_t arg_idx = 0;
1415 MAUG_MHANDLE key_tmp_h = (MAUG_MHANDLE)NULL;
1416 char* key_tmp = NULL;
1418 int16_t null_val = 0;
1426 if( MLISP_EXEC_ENV_FRAME_CT_MAX > exec->
env_select + 1 ) {
1428#if MLISP_EXEC_TRACE_LVL > 0
1429 debug_printf( MLISP_EXEC_TRACE_LVL,
"selecting env frame: %d",
1432 assert( 0 == mdata_table_ct( &(exec->
env[exec->
env_select]) ) );
1435 retval = mlisp_env_set(
1436 exec,
"null", 4, MLISP_TYPE_INT, &null_val, 0, 0 );
1438 error_printf(
"env frame overflow!" );
1439 retval = MERROR_OVERFLOW;
1444 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1447 while( 0 <= arg_idx ) {
1450 maug_cleanup_if_not_ok();
1452 ast_n_arg = mdata_vector_get(
1453 &(parser->ast), n->ast_idx_children[arg_idx],
1458 &(parser->strpool), ast_n_arg->token_idx );
1460 assert( (MAUG_MHANDLE)NULL != key_tmp_h );
1462 maug_mlock( key_tmp_h, key_tmp );
1463 maug_cleanup_if_null_lock(
char*, key_tmp );
1465 retval = mlisp_env_set(
1466 exec, key_tmp, 0, stack_n_arg.type, &(stack_n_arg.value), 0, 0 );
1467 maug_cleanup_if_not_ok();
1469 maug_munlock( key_tmp_h, key_tmp );
1470 maug_mfree( key_tmp_h );
1477 if( NULL != key_tmp ) {
1478 maug_munlock( key_tmp_h, key_tmp );
1481 if( (MAUG_MHANDLE)NULL != key_tmp_h ) {
1482 maug_mfree( key_tmp_h );
1495 size_t* p_child_idx = NULL;
1496 size_t* p_visit_ct = NULL;
1501 assert( mdata_vector_is_locked( &(parser->ast) ) );
1504#if MLISP_EXEC_TRACE_LVL > 0
1505 debug_printf( MLISP_EXEC_TRACE_LVL,
1506 "%u: resetting node " SIZE_T_FMT
" child idx to 0", exec->uid, n_idx );
1509 assert( NULL != p_child_idx );
1512#if MLISP_EXEC_TRACE_LVL > 0
1513 debug_printf( MLISP_EXEC_TRACE_LVL,
1514 "%u: resetting node " SIZE_T_FMT
" visit count to 0", exec->uid, n_idx );
1517 assert( NULL != p_visit_ct );
1520 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1524 retval = _mlisp_reset_child_pcs( parser, n->ast_idx_children[i], exec );
1525 maug_cleanup_if_not_ok();
1541#if MLISP_EXEC_TRACE_LVL > 0
1542 debug_printf( MLISP_EXEC_TRACE_LVL,
1543 "%u: resetting lambda " SIZE_T_FMT
"...", exec->uid, n_idx );
1549 assert( !mdata_table_is_locked( &(exec->
env[exec->
env_select]) ) );
1555 retval = _mlisp_reset_child_pcs( parser, n_idx, exec );
1568 size_t* p_lambda_child_idx = NULL;
1569 size_t* p_args_child_idx = NULL;
1571 size_t* p_n_last_lambda = NULL;
1572 ssize_t append_retval = 0;
1574#ifdef MLISP_DEBUG_TRACE
1575 exec->trace[exec->trace_depth++] = n_idx;
1576 assert( exec->trace_depth <= MLISP_DEBUG_TRACE );
1581 p_n_last_lambda = mdata_vector_get_last( &(exec->
lambda_trace),
size_t );
1583 if( NULL != p_n_last_lambda && n_idx == *p_n_last_lambda ) {
1587#if MLISP_EXEC_TRACE_LVL > 0
1588 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: TRACE TAIL TIME!", exec->uid );
1594 _mlisp_reset_lambda( parser, n_idx, exec );
1595 retval = mdata_vector_remove_last( &(exec->
lambda_trace) );
1596 maug_cleanup_if_not_ok();
1599#if MLISP_EXEC_TRACE_LVL > 0
1600 debug_printf( MLISP_EXEC_TRACE_LVL,
1601 "%u: xvxvxvxvxvxvx STEP LAMBDA " SIZE_T_FMT
" xvxvxvxvxvx",
1606 append_retval = mdata_vector_append(
1608 retval = mdata_retval( append_retval );
1609 maug_cleanup_if_not_ok();
1613 p_lambda_child_idx = mdata_vector_get(
1615 assert( NULL != p_lambda_child_idx );
1616#if MLISP_EXEC_TRACE_LVL > 0
1617 debug_printf( MLISP_EXEC_TRACE_LVL,
1618 "%u: lambda node " SIZE_T_FMT
" child idx: " SIZE_T_FMT,
1619 exec->uid, n_idx, *p_lambda_child_idx );
1622 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1628 if( 0 == *p_lambda_child_idx ) {
1633 p_args_child_idx = mdata_vector_get(
1635 n->ast_idx_children[*p_lambda_child_idx],
size_t );
1636 assert( NULL != p_args_child_idx );
1637#if MLISP_EXEC_TRACE_LVL > 0
1638 debug_printf( MLISP_EXEC_TRACE_LVL,
1639 "%u: child idx for args AST node " SIZE_T_FMT
": " SIZE_T_FMT,
1640 exec->uid, *p_lambda_child_idx, *p_args_child_idx );
1644 retval = _mlisp_step_lambda_args(
1645 parser, n->ast_idx_children[*p_lambda_child_idx], exec );
1651 if( MERROR_OK == retval ) {
1660 (*p_lambda_child_idx)++;
1661#if MLISP_EXEC_TRACE_LVL > 0
1662 debug_printf( MLISP_EXEC_TRACE_LVL,
1663 "%u: incremented node " SIZE_T_FMT
" child idx to: " SIZE_T_FMT,
1664 exec->uid, n_idx, *p_lambda_child_idx );
1673 }
else if( mlisp_ast_has_ready_children( *p_lambda_child_idx, n ) ) {
1681 NULL == exec->global_env ||
1682 !mdata_table_is_locked( exec->global_env ) );
1684 retval = _mlisp_step_iter(
1685 parser, n->ast_idx_children[*p_lambda_child_idx], exec );
1687 retval = _mlisp_preempt(
1688 retval,
"lambda", parser, n_idx, exec, (*p_lambda_child_idx) + 1 );
1695 NULL == exec->global_env ||
1696 !mdata_table_is_locked( exec->global_env ) );
1697 _mlisp_reset_lambda( parser, n_idx, exec );
1704#if MLISP_EXEC_TRACE_LVL > 0
1705 debug_printf( MLISP_EXEC_TRACE_LVL,
1706 "%u: xvxvxvxvxvxvx END STEP LAMBDA " SIZE_T_FMT
" xvxvxvxvxvx",
1726 i = mdata_vector_ct( &(exec->
stack) ) - 1;
1730 maug_cleanup_if_not_ok();
1732 if( MLISP_TYPE_BEGIN == o.type && n_idx == o.value.begin ) {
1756 char* strpool_token = NULL;
1762 NULL == exec->global_env ||
1763 mdata_table_is_locked( exec->global_env ) );
1765 mdata_strpool_lock( &(parser->strpool) );
1768 strpool_token = mdata_strpool_get( &(parser->strpool), token_idx );
1769 assert( NULL != strpool_token );
1771#if MLISP_EXEC_TRACE_LVL > 0
1772 debug_printf( MLISP_EXEC_TRACE_LVL,
1773 "%u: eval token: \"%s\" (strlen: " SIZE_T_FMT
"r/" SIZE_T_FMT
"d)",
1774 exec->uid, strpool_token, token_sz, maug_strlen( strpool_token ) );
1776 if( 0 == strncmp( strpool_token,
"begin", token_sz ) ) {
1778 e_out->type = MLISP_TYPE_BEGIN;
1780 }
else if( NULL != (p_e = mlisp_env_get( exec, strpool_token ) ) ) {
1782#if MLISP_EXEC_TRACE_LVL > 0
1783 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: found %s in env!",
1784 exec->uid, strpool_token );
1792 }
else if( maug_is_num( strpool_token, token_sz, 10, 1 ) ) {
1794#if MLISP_EXEC_TRACE_LVL > 0
1795 debug_printf( MLISP_EXEC_TRACE_LVL,
1796 "%u: did not find %s in env, but it is a number...",
1797 exec->uid, strpool_token );
1799 e_out->value.integer = maug_atos32( strpool_token, token_sz );
1800 e_out->type = MLISP_TYPE_INT;
1802 }
else if( maug_is_float( strpool_token, token_sz ) ) {
1803#if MLISP_EXEC_TRACE_LVL > 0
1804 debug_printf( MLISP_EXEC_TRACE_LVL,
1805 "%u: did not find %s in env, but it is a float...",
1806 exec->uid, strpool_token );
1809 e_out->value.floating = maug_atof( strpool_token, token_sz );
1810 e_out->type = MLISP_TYPE_FLOAT;
1813#if MLISP_EXEC_TRACE_LVL > 0
1814 error_printf(
"%u: could not make sense of token: %s",
1815 exec->uid, strpool_token );
1822 if( mdata_strpool_is_locked( &(parser->strpool) ) ) {
1823 mdata_strpool_unlock( &(parser->strpool) );
1826 assert( MERROR_OK == retval );
1838 size_t* p_visit_ct = NULL;
1840 uint8_t e_flags = 0;
1841 mlisp_lambda_t e_lambda = 0;
1842 int8_t env_iter = 0;
1844#ifdef MLISP_DEBUG_TRACE
1845 exec->trace[exec->trace_depth++] = n_idx;
1846 assert( exec->trace_depth <= MLISP_DEBUG_TRACE );
1849 n = mdata_vector_get( &(parser->ast), n_idx,
struct MLISP_AST_NODE );
1852 p_visit_ct = mdata_vector_get(
1854 assert( NULL != p_visit_ct );
1856#if MLISP_EXEC_TRACE_LVL > 0
1857 debug_printf( MLISP_EXEC_TRACE_LVL,
1858 "%u: visit count for AST node " SIZE_T_FMT
": " SIZE_T_FMT,
1859 exec->uid, n_idx, *p_visit_ct );
1864 MLISP_AST_FLAG_BEGIN == (MLISP_AST_FLAG_BEGIN & n->flags) &&
1868 retval = _mlisp_stack_push_mlisp_begin_t( exec, n_idx );
1869 maug_cleanup_if_not_ok();
1874 (retval = _mlisp_step_iter_children( parser, n_idx, exec ))
1880 if( MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) ) {
1896 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
1897#if MLISP_EXEC_TRACE_LVL > 0
1898 debug_printf( MLISP_EXEC_TRACE_LVL,
1899 "%u: locking local env %d...", exec->uid, env_iter );
1901 mdata_table_lock( &(exec->
env[env_iter]) );
1905 NULL == exec->global_env || !mdata_table_is_locked( exec->global_env ) );
1906 if( NULL != exec->global_env ) {
1907 mdata_table_lock( exec->global_env );
1911 retval = _mlisp_eval_token_strpool(
1912 parser, exec, n->token_idx, n->token_sz, &e );
1913 maug_cleanup_if_not_ok();
1918# define _MLISP_TYPE_TABLE_ENVE( idx, ctype, name, const_name, fmt ) \
1919 } else if( MLISP_TYPE_ ## const_name == e.type ) { \
1920 retval = _mlisp_stack_push_ ## ctype( exec, e.value.name ); \
1921 maug_cleanup_if_not_ok();
1923 if( MLISP_EXEC_FLAG_DEF_TERM == (MLISP_EXEC_FLAG_DEF_TERM & exec->
flags) ) {
1927#if MLISP_EXEC_TRACE_LVL > 0
1928 debug_printf( MLISP_EXEC_TRACE_LVL,
1929 "%u: special case! pushing literal to stack: " SSIZE_T_FMT,
1930 exec->uid, n->token_idx );
1932 retval = _mlisp_stack_push_mdata_strpool_idx_t( exec, n->token_idx );
1933 maug_cleanup_if_not_ok();
1934 }
else if( MLISP_TYPE_BEGIN == e.type ) {
1938#if MLISP_EXEC_TRACE_LVL > 0
1939 debug_printf( MLISP_EXEC_TRACE_LVL,
1940 "%u: rewinding stack for begin on node " SSIZE_T_FMT,
1943 retval = _mlisp_stack_cleanup( parser, n_idx, exec );
1944 maug_cleanup_if_not_ok();
1949 retval = _mlisp_stack_push_mlisp_begin_t( exec, n_idx );
1950 maug_cleanup_if_not_ok();
1952 }
else if( MLISP_TYPE_CB == e.type ) {
1961 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
1962 mdata_table_unlock( &(exec->
env[env_iter]) );
1964 if( NULL != exec->global_env ) {
1965 mdata_table_unlock( exec->global_env );
1972 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
1973 mdata_table_lock( &(exec->
env[env_iter]) );
1975 if( NULL != exec->global_env ) {
1976 mdata_table_lock( exec->global_env );
1979 }
else if( MLISP_TYPE_LAMBDA == e.type ) {
1985 e_lambda = e.value.lambda;
1986 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
1987 mdata_table_unlock( &(exec->
env[env_iter]) );
1989 if( NULL != exec->global_env ) {
1990 mdata_table_unlock( exec->global_env );
1993 retval = _mlisp_step_lambda( parser, e_lambda, exec );
1996 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
1997 mdata_table_lock( &(exec->
env[env_iter]) );
1999 if( NULL != exec->global_env ) {
2000 mdata_table_lock( exec->global_env );
2005 retval = _mlisp_stack_push_mdata_strpool_idx_t( exec, n->token_idx );
2006 maug_cleanup_if_not_ok();
2011 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
2012 mdata_table_unlock( &(exec->
env[env_iter]) );
2015 if( NULL != exec->global_env ) {
2016 mdata_table_unlock( exec->global_env );
2026 void* cb_data,
size_t cb_data_sz,
size_t idx
2030 ssize_t* p_builtins = (ssize_t*)cb_data;
2032 if( MLISP_ENV_FLAG_BUILTIN == (MLISP_ENV_FLAG_BUILTIN & e->flags) ) {
2043 ssize_t builtins = 0;
2046 if( 0 == mdata_table_ct( &(exec->
env[0]) ) ) {
2050 if( !mdata_table_is_locked( &(exec->
env[0]) ) ) {
2051 mdata_table_lock( &(exec->
env[0]) );
2055 retval = mdata_table_iter(
2056 &(exec->
env[0]), _mlisp_count_builtins_iter, &builtins, 0 );
2060 if( MERROR_OK != retval ) {
2061 builtins = merror_retval_to_sz( retval );
2065 mdata_table_unlock( &(exec->
env[0]) );
2079 error_printf(
"no valid AST present; could not exec!" );
2080 retval = MERROR_EXEC;
2085 MLISP_EXEC_FLAG_INITIALIZED != (exec->
flags & MLISP_EXEC_FLAG_INITIALIZED)
2087 retval = MERROR_EXEC;
2102#ifdef MLISP_DEBUG_TRACE
2104 char trace_str[MLISP_DEBUG_TRACE * 5];
2105 maug_ms_t ms_start = 0;
2106 maug_ms_t ms_end = 0;
2108 ms_start = retroflat_get_ms();
2111#if MLISP_EXEC_TRACE_LVL > 0
2112 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: heartbeat start", exec->uid );
2120 assert( !mdata_vector_is_locked( &(parser->ast) ) );
2123 mdata_vector_lock( &(parser->ast) );
2126 exec->
flags &= MLISP_EXEC_FLAG_TRANSIENT_MASK;
2127 assert( 0 == mdata_vector_ct( &(exec->
lambda_trace) ) );
2129#ifdef MLISP_DEBUG_TRACE
2130 exec->trace_depth = 0;
2134 retval = _mlisp_step_iter( parser, 0, exec );
2138 }
else if( MERROR_OK == retval ) {
2140#if MLISP_EXEC_TRACE_LVL > 0
2141 debug_printf( MLISP_EXEC_TRACE_LVL,
2142 "%u: execution terminated successfully", exec->uid );
2144 retval = MERROR_EXEC;
2145#if MLISP_EXEC_TRACE_LVL > 0
2147 debug_printf( MLISP_EXEC_TRACE_LVL,
2148 "%u: execution terminated with retval: %d", exec->uid, retval );
2152#ifdef MLISP_DEBUG_TRACE
2153 ms_end = retroflat_get_ms();
2155 maug_mzero( trace_str, MLISP_DEBUG_TRACE * 5 );
2156 for( i = 0 ; exec->trace_depth > i ; i++ ) {
2158 &(trace_str[maug_strlen( trace_str )]),
2159 (MLISP_DEBUG_TRACE * 5) - maug_strlen( trace_str ),
2160 SIZE_T_FMT
", ", exec->trace[i] );
2162#if MLISP_EXEC_TRACE_LVL > 0
2163 debug_printf( MLISP_EXEC_TRACE_LVL,
2164 "%u: " MLISP_TRACE_SIGIL
" HBEXEC (%u): %s",
2165 exec->uid, ms_end - ms_start, trace_str );
2171#if MLISP_EXEC_TRACE_LVL > 0
2172 debug_printf( MLISP_EXEC_TRACE_LVL,
2173 "%u: heartbeat end: %x", exec->uid, retval );
2176 assert( mdata_vector_is_locked( &(parser->ast) ) );
2177 mdata_vector_unlock( &(parser->ast) );
2192 uint8_t autolock[MLISP_EXEC_ENV_FRAME_CT_MAX];
2193 mlisp_lambda_t lambda_idx = 0;
2195 int8_t env_iter = 0;
2197 if( MERROR_OK != mlisp_check_state( parser, exec ) ) {
2198 error_printf(
"mlisp not ready!" );
2199 retval = MERROR_EXEC;
2203 retval = _mlisp_autolock( parser, exec, 0xff, autolock );
2204 maug_cleanup_if_not_ok();
2207 e = mlisp_env_get( exec, lambda );
2209 error_printf(
"lambda \"%s\" not found!", lambda );
2210 retval = MERROR_OVERFLOW;
2213 lambda_idx = e->value.lambda;
2219 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
2220 if( MLISP_AUTOLOCK_EXEC_ENV == (MLISP_AUTOLOCK_EXEC_ENV & autolock[0]) ) {
2221 mdata_table_unlock( &(exec->
env[env_iter]) );
2222 autolock[env_iter] &= ~MLISP_AUTOLOCK_EXEC_ENV;
2226 MLISP_AUTOLOCK_GLOBAL_ENV == (MLISP_AUTOLOCK_GLOBAL_ENV & autolock[0])
2228 mdata_table_unlock( exec->global_env );
2229 autolock[0] &= ~MLISP_AUTOLOCK_GLOBAL_ENV;
2232#if MLISP_EXEC_TRACE_LVL > 0
2233 debug_printf( MLISP_EXEC_TRACE_LVL,
"%u: lambda \"%s\" is AST node idx %ld",
2234 exec->uid, lambda, lambda_idx );
2237 n = mdata_vector_get( &(parser->ast), lambda_idx,
struct MLISP_AST_NODE );
2238 assert( MLISP_AST_FLAG_LAMBDA == (MLISP_AST_FLAG_LAMBDA & n->flags) );
2241 retval = _mlisp_step_lambda( parser, lambda_idx, exec );
2245 _mlisp_autounlock( parser, exec, autolock );
2257 retval = mlisp_env_set(
2258 exec,
"gdefine", 7, MLISP_TYPE_CB, _mlisp_env_cb_define,
2260 maug_cleanup_if_not_ok();
2262 retval = mlisp_env_set(
2263 exec,
"and", 3, MLISP_TYPE_CB, _mlisp_env_cb_ano,
2264 0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ANO_AND );
2265 maug_cleanup_if_not_ok();
2267 retval = mlisp_env_set(
2268 exec,
"or", 2, MLISP_TYPE_CB, _mlisp_env_cb_ano,
2269 0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ANO_OR );
2270 maug_cleanup_if_not_ok();
2272#ifndef MAUG_NO_RETRO
2274 retval = mlisp_env_set(
2275 exec,
"random", 6, MLISP_TYPE_CB, _mlisp_env_cb_random,
2276 0, MLISP_ENV_FLAG_BUILTIN );
2277 maug_cleanup_if_not_ok();
2280 retval = mlisp_env_set(
2281 exec,
"if", 2, MLISP_TYPE_CB, _mlisp_env_cb_if,
2282 0, MLISP_ENV_FLAG_BUILTIN );
2283 maug_cleanup_if_not_ok();
2285 retval = mlisp_env_set(
2286 exec,
"define", 6, MLISP_TYPE_CB, _mlisp_env_cb_define,
2287 0, MLISP_ENV_FLAG_BUILTIN );
2288 maug_cleanup_if_not_ok();
2290 retval = mlisp_env_set(
2291 exec,
"*", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
2293 maug_cleanup_if_not_ok();
2295 retval = mlisp_env_set(
2296 exec,
"+", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
2298 maug_cleanup_if_not_ok();
2300 retval = mlisp_env_set(
2301 exec,
"/", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
2302 0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ARI_DIV );
2303 maug_cleanup_if_not_ok();
2305 retval = mlisp_env_set(
2306 exec,
"%", 1, MLISP_TYPE_CB, _mlisp_env_cb_arithmetic,
2307 0, MLISP_ENV_FLAG_BUILTIN | MLISP_ENV_FLAG_ARI_MOD );
2308 maug_cleanup_if_not_ok();
2310 retval = mlisp_env_set(
2311 exec,
"<", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
2313 maug_cleanup_if_not_ok();
2315 retval = mlisp_env_set(
2316 exec,
">", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
2318 maug_cleanup_if_not_ok();
2320 retval = mlisp_env_set(
2321 exec,
"=", 1, MLISP_TYPE_CB, _mlisp_env_cb_cmp,
2323 maug_cleanup_if_not_ok();
2336 ssize_t append_retval = 0;
2338 int16_t null_val = 0;
2340 assert( 0 == exec->
flags );
2344 exec->
flags = flags;
2345 exec->uid = g_mlispe_last_uid++;
2348 append_retval = mdata_vector_append(
2350 if( 0 > append_retval ) {
2351 retval = mdata_retval( append_retval );
2353 maug_cleanup_if_not_ok();
2359 retval = mlisp_env_set(
2360 exec,
"null", 4, MLISP_TYPE_INT, &null_val, 0, 0 );
2363 append_retval = mdata_vector_append(
2365 if( 0 > append_retval ) {
2366 retval = mdata_retval( append_retval );
2368 maug_cleanup_if_not_ok();
2373 mdata_vector_ct( &(parser->ast) )
2377 if( 0 > append_retval ) {
2378 retval = mdata_retval( append_retval );
2380 maug_cleanup_if_not_ok();
2384 append_retval = mdata_vector_append(
2386 if( 0 > append_retval ) {
2387 retval = mdata_retval( append_retval );
2389 maug_cleanup_if_not_ok();
2394 mdata_vector_ct( &(parser->ast) )
2398 if( 0 > append_retval ) {
2399 retval = mdata_retval( append_retval );
2401 maug_cleanup_if_not_ok();
2404 exec->
flags |= MLISP_EXEC_FLAG_INITIALIZED;
2408 retval = mlisp_exec_add_env_builtins( parser, exec );
2412 if( MERROR_OK != retval ) {
2413 error_printf(
"mlisp exec initialization failed: %d", retval );
2426 int16_t null_val = 0;
2428 exec->global_env = global_env;
2430 if( 0 == mdata_table_ct( global_env ) ) {
2435 retval = mlisp_env_set(
2436 exec,
"null", 4, MLISP_TYPE_INT, &null_val, 1, 0 );
2445 int8_t env_iter = 0;
2447#if MLISP_EXEC_TRACE_LVL > 0
2448 debug_printf( MLISP_EXEC_TRACE_LVL,
2449 "%u: destroying exec (stack: " SIZE_T_FMT
", env: " SIZE_T_FMT
")...",
2451 mdata_vector_ct( &(exec->
stack) ),
2456 mdata_vector_free( &(exec->
stack) );
2457 for( env_iter = exec->
env_select ; 0 <= env_iter ; env_iter-- ) {
2458 mdata_table_free( &(exec->
env[env_iter]) );
2462#if MLISP_EXEC_TRACE_LVL > 0
2463 debug_printf( MLISP_EXEC_TRACE_LVL,
"exec destroyed!" );
2482# define MLISP_PSTATE_TABLE_CONST( name, idx ) \
2483 extern MAUG_CONST uint8_t SEG_MCONST name;
2485MLISP_PARSER_PSTATE_TABLE( MLISP_PSTATE_TABLE_CONST )
2487#ifdef MPARSER_TRACE_NAMES
2488extern MAUG_CONST
char* SEG_MCONST gc_mlisp_pstate_names[];
int 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