diff --git a/lispBM/lispBM/include/fundamental.h b/lispBM/lispBM/include/fundamental.h index 2106aea3..7c45a654 100644 --- a/lispBM/lispBM/include/fundamental.h +++ b/lispBM/lispBM/include/fundamental.h @@ -28,68 +28,7 @@ #ifdef __cplusplus extern "C" { #endif - - void fundamental_add(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_sub(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_mul(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_div(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_mod(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_numeq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_num_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_lt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_gt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_leq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_geq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_gc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_self(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_set_mailbox_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_cons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_append(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_undefine(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_array_read(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_array_write(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_array_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_array_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_array_clear(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_symbol_to_string(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_string_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_symbol_to_uint(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_uint_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_set_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_set_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_set_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_acons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_set_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_cossa(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_i(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_i32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_u(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_u32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_float(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_i64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_u64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_double(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_to_byte(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_shl(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_shr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_bitwise_and(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_bitwise_or(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_bitwise_xor(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_bitwise_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_list_length(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx); - void fundamental_reg_event_handler(lbm_value *args, lbm_uint argn, eval_context_t *ctx); - + extern const fundamental_fun fundamental_table[]; bool struct_eq(lbm_value a, lbm_value b); #ifdef __cplusplus } diff --git a/lispBM/lispBM/include/lbm_defines.h b/lispBM/lispBM/include/lbm_defines.h index ecdbdedb..242a2978 100644 --- a/lispBM/lispBM/include/lbm_defines.h +++ b/lispBM/lispBM/include/lbm_defines.h @@ -200,6 +200,9 @@ #define SYM_EXIT_ERROR 0x20B #define SYM_MAP 0x20C #define SYM_REVERSE 0x20D +#define APPLY_FUNS_END 0x20D + +#define FUNDAMENTALS_START 0x20E #define SYM_ADD 0x20E #define SYM_SUB 0x20F #define SYM_MUL 0x210 @@ -260,8 +263,8 @@ #define SYM_LIST_LENGTH 0x247 #define SYM_RANGE 0x248 #define SYM_REG_EVENT_HANDLER 0x249 +#define FUNDAMENTALS_END 0x249 -#define APPLY_FUNS_END 0x249 #define SPECIAL_SYMBOLS_START 0 diff --git a/lispBM/lispBM/src/eval_cps.c b/lispBM/lispBM/src/eval_cps.c index 59116cea..20b88a56 100644 --- a/lispBM/lispBM/src/eval_cps.c +++ b/lispBM/lispBM/src/eval_cps.c @@ -2017,66 +2017,6 @@ static const apply_fun fun_table[] = apply_error, apply_map, apply_reverse, - fundamental_add, - fundamental_sub, - fundamental_mul, - fundamental_div, - fundamental_mod, - fundamental_eq, - fundamental_not_eq, - fundamental_numeq, - fundamental_num_not_eq, - fundamental_lt, - fundamental_gt, - fundamental_leq, - fundamental_geq, - fundamental_not, - fundamental_gc, - fundamental_self, - fundamental_set_mailbox_size, - fundamental_cons, - fundamental_car, - fundamental_cdr, - fundamental_list, - fundamental_append, - fundamental_undefine, - fundamental_array_read, - fundamental_array_write, - fundamental_array_create, - fundamental_array_size, - fundamental_array_clear, - fundamental_symbol_to_string, - fundamental_string_to_symbol, - fundamental_symbol_to_uint, - fundamental_uint_to_symbol, - fundamental_set_car, - fundamental_set_cdr, - fundamental_set_ix, - fundamental_assoc, - fundamental_acons, - fundamental_set_assoc, - fundamental_cossa, - fundamental_ix, - fundamental_to_i, - fundamental_to_i32, - fundamental_to_u, - fundamental_to_u32, - fundamental_to_float, - fundamental_to_i64, - fundamental_to_u64, - fundamental_to_double, - fundamental_to_byte, - fundamental_shl, - fundamental_shr, - fundamental_bitwise_and, - fundamental_bitwise_or, - fundamental_bitwise_xor, - fundamental_bitwise_not, - fundamental_custom_destruct, - fundamental_type_of, - fundamental_list_length, - fundamental_range, - fundamental_reg_event_handler }; /***************************************************/ @@ -2114,13 +2054,25 @@ static void application(eval_context_t *ctx, lbm_value *fun_args, lbm_uint arg_c ctx->app_cont = true; } else if (lbm_type_of(fun) == LBM_TYPE_SYMBOL) { /* eval_cps specific operations */ - lbm_uint sym_val = lbm_dec_sym(fun) - APPLY_FUNS_START; + lbm_uint fun_val = lbm_dec_sym(fun); + lbm_uint apply_val = fun_val - APPLY_FUNS_START; + lbm_uint fund_val = fun_val - FUNDAMENTALS_START; - if (sym_val <= (APPLY_FUNS_END - APPLY_FUNS_START)) { - fun_table[sym_val](&fun_args[1], arg_count, ctx); + if (apply_val <= (APPLY_FUNS_END - APPLY_FUNS_START)) { + fun_table[apply_val](&fun_args[1], arg_count, ctx); + } else if (fund_val <= (FUNDAMENTALS_END - FUNDAMENTALS_START)) { + lbm_value res; + WITH_GC(res, fundamental_table[fund_val](&fun_args[1], arg_count, ctx)); + if (lbm_is_error(res)) { + error_ctx(res); + return; + } + lbm_stack_drop(&ctx->K, arg_count+1); + ctx->app_cont = true; + ctx->r = res; } else { // It may be an extension - extension_fptr f = lbm_get_extension(lbm_dec_sym(fun)); + extension_fptr f = lbm_get_extension(fun_val); if (f == NULL) { error_ctx(ENC_SYM_EERROR); return; diff --git a/lispBM/lispBM/src/fundamental.c b/lispBM/lispBM/src/fundamental.c index a3a3f12c..1a2f9e39 100644 --- a/lispBM/lispBM/src/fundamental.c +++ b/lispBM/lispBM/src/fundamental.c @@ -15,7 +15,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - #include #include "symrepr.h" #include "stack.h" @@ -26,57 +25,138 @@ #include "env.h" #include "lbm_utils.h" #include "lbm_custom_type.h" -#include "lbm_constants.h" #include #include -extern eval_context_t *ctx_running; -extern void error_ctx(lbm_value); -extern int lbm_perform_gc(void); +static lbm_uint add2(lbm_uint a, lbm_uint b) { -#define RETURN(X) \ - {ctx->r = (X); \ - ctx->app_cont = true; \ - lbm_stack_drop(&ctx->K, nargs + 1); \ - return;} + lbm_uint retval = ENC_SYM_TERROR; -#define ERROR(X) \ - {error_ctx(X); \ - return;} - -#define WITH_GC(y, x) \ - { \ - lbm_value gc_tmp = (x); \ - if (lbm_is_symbol_merror(gc_tmp)) { \ - lbm_perform_gc(); \ - gc_tmp = (x); \ - if (lbm_is_symbol_merror(gc_tmp)) { \ - ctx_running->done = true; \ - error_ctx(ENC_SYM_MERROR); \ - return; \ - } \ - } \ - (y) = gc_tmp; \ - /* continue executing statements below */ \ + if (!(lbm_is_number(a) && lbm_is_number(b))) { + return retval; } -#define WITH_GC_RMBR(y, x, n, ...) \ - { \ - lbm_value gc_tmp = (x); \ - if (lbm_is_symbol_merror(gc_tmp)) { \ - lbm_gc_mark_phase((n), __VA_ARGS__); \ - lbm_perform_gc(); \ - gc_tmp = (x); \ - if (lbm_is_symbol_merror(gc_tmp)) { \ - ctx_running->done = true; \ - error_ctx(ENC_SYM_MERROR); \ - return; \ - } \ - } \ - (y) = gc_tmp; \ - /* continue executing statements below */ \ + lbm_uint t = (lbm_type_of(a) < lbm_type_of(b)) ? lbm_type_of(b) : lbm_type_of(a); + switch (t) { + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i32(a) + lbm_dec_as_i32(b)); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u32(a) + lbm_dec_as_u32(b)); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_as_u32(a) + lbm_dec_as_u32(b)); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_as_i32(a) + lbm_dec_as_i32(b)); break; + case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_as_float(a) + lbm_dec_as_float(b)); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_as_u64(a) + lbm_dec_as_u64(b)); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_as_i64(a) + lbm_dec_as_i64(b)); break; + case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_as_double(a) + lbm_dec_as_double(b)); break; } + return retval; +} + +static lbm_uint mul2(lbm_uint a, lbm_uint b) { + + lbm_uint retval = ENC_SYM_TERROR; + + if (!(lbm_is_number(a) && lbm_is_number(b))) { + return retval; + } + + lbm_uint t = (lbm_type_of(a) < lbm_type_of(b)) ? lbm_type_of(b) : lbm_type_of(a); + switch (t) { + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i32(a) * lbm_dec_as_i32(b)); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u32(a) * lbm_dec_as_u32(b)); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_as_u32(a) * lbm_dec_as_u32(b)); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_as_i32(a) * lbm_dec_as_i32(b)); break; + case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_as_float(a) * lbm_dec_as_float(b)); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_as_u64(a) * lbm_dec_as_u64(b)); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_as_i64(a) * lbm_dec_as_i64(b)); break; + case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_as_double(a) * lbm_dec_as_double(b)); break; + } + return retval; +} + +static lbm_uint div2(lbm_uint a, lbm_uint b) { + + lbm_uint retval = ENC_SYM_TERROR; + + if (!(lbm_is_number(a) && lbm_is_number(b))) { + return retval; + } + + lbm_uint t = (lbm_type_of(a) < lbm_type_of(b)) ? lbm_type_of(b) : lbm_type_of(a); + switch (t) { + case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i32(a) / lbm_dec_as_i32(b)); break; + case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u32(a) / lbm_dec_as_u32(b)); break; + case LBM_TYPE_U32: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u32(lbm_dec_as_u32(a) / lbm_dec_as_u32(b)); break; + case LBM_TYPE_I32: if (lbm_dec_as_i32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i32(lbm_dec_as_i32(a) / lbm_dec_as_i32(b)); break; + case LBM_TYPE_FLOAT: if (lbm_dec_as_float(b) == 0.0f || lbm_dec_as_float(b) == -0.0f) {return ENC_SYM_DIVZERO;} retval = lbm_enc_float(lbm_dec_as_float(a) / lbm_dec_as_float(b)); break; + case LBM_TYPE_U64: if (lbm_dec_as_u64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u64(lbm_dec_as_u32(a) / lbm_dec_as_u64(b)); break; + case LBM_TYPE_I64: if (lbm_dec_as_i64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i64(lbm_dec_as_i32(a) / lbm_dec_as_i64(b)); break; + case LBM_TYPE_DOUBLE: if (lbm_dec_as_double(b) == (double)0.0 || lbm_dec_as_double(b) == (double)-0.0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_double(lbm_dec_as_double(a) / lbm_dec_as_double(b)); break; + } + return retval; +} + +static lbm_uint mod2(lbm_uint a, lbm_uint b) { + + lbm_uint retval = ENC_SYM_TERROR; + + if (!(lbm_is_number(a) && lbm_is_number(b))) { + return retval; + } + + lbm_uint t = (lbm_type_of(a) < lbm_type_of(b)) ? lbm_type_of(b) : lbm_type_of(a); + switch (t) { + case LBM_TYPE_I: if (lbm_dec_i(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i(lbm_dec_as_i32(a) % lbm_dec_as_i32(b)); break; + case LBM_TYPE_U: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u(lbm_dec_as_u32(a) % lbm_dec_as_u32(b)); break; + case LBM_TYPE_U32: if (lbm_dec_as_u32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u32(lbm_dec_as_u32(a) % lbm_dec_as_u32(b)); break; + case LBM_TYPE_I32: if (lbm_dec_as_i32(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i32(lbm_dec_as_i32(a) % lbm_dec_as_i32(b)); break; + case LBM_TYPE_FLOAT: if (lbm_dec_as_float(b) == 0.0f || lbm_dec_as_float(b) == -0.0f) {return ENC_SYM_DIVZERO;} retval = lbm_enc_float(fmodf(lbm_dec_as_float(a), lbm_dec_as_float(b))); break; + case LBM_TYPE_U64: if (lbm_dec_as_u64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_u64(lbm_dec_as_u64(a) % lbm_dec_as_u64(b)); break; + case LBM_TYPE_I64: if (lbm_dec_as_i64(b) == 0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_i64(lbm_dec_as_i64(a) % lbm_dec_as_i64(b)); break; + case LBM_TYPE_DOUBLE: if (lbm_dec_as_double(b) == (double)0.0 || lbm_dec_as_double(b) == (double)-0.0) {return ENC_SYM_DIVZERO;} retval = lbm_enc_double(fmod(lbm_dec_as_double(a), lbm_dec_as_double(b))); break; + } + return retval; +} + +static lbm_uint negate(lbm_uint a) { + + lbm_uint retval = ENC_SYM_TERROR; + + if (lbm_type_of(a) > LBM_TYPE_CHAR) { + switch (lbm_type_of(a)) { + case LBM_TYPE_I: retval = lbm_enc_i(- lbm_dec_i(a)); break; + case LBM_TYPE_U: retval = lbm_enc_u(- lbm_dec_u(a)); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(- lbm_dec_u32(a)); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(- lbm_dec_i32(a)); break; + case LBM_TYPE_FLOAT: retval = lbm_enc_float(- lbm_dec_float(a)); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(- lbm_dec_u64(a)); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(- lbm_dec_i64(a)); break; + case LBM_TYPE_DOUBLE: retval = lbm_enc_double(- lbm_dec_double(a)); break; + } + } + return retval; +} + +static lbm_uint sub2(lbm_uint a, lbm_uint b) { + + lbm_uint retval = ENC_SYM_TERROR; + + if (!(lbm_is_number(a) && lbm_is_number(b))) { + return retval; + } + + lbm_uint t = (lbm_type_of(a) < lbm_type_of(b)) ? lbm_type_of(b) : lbm_type_of(a); + switch (t) { + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_as_u32(a) - lbm_dec_as_u32(b)); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_as_i32(a) - lbm_dec_as_i32(b)); break; + case LBM_TYPE_FLOAT: retval = lbm_enc_float(lbm_dec_as_float(a) - lbm_dec_as_float(b)); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_as_u64(a) - lbm_dec_as_u64(b)); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_as_i64(a) - lbm_dec_as_i64(b)); break; + case LBM_TYPE_DOUBLE: retval = lbm_enc_double(lbm_dec_as_double(a) - lbm_dec_as_double(b)); break; + } + return retval; +} static bool array_equality(lbm_value a, lbm_value b) { if (lbm_type_of(a) == LBM_TYPE_ARRAY && @@ -166,846 +246,9 @@ static int compare(lbm_uint a, lbm_uint b) { return retval; } -static int elt_size(lbm_type t) { - switch(t) { - case LBM_TYPE_BYTE: - return 1; - case LBM_TYPE_U32: /* fall through */ - case LBM_TYPE_I32: - case LBM_TYPE_FLOAT: - return 4; - case LBM_TYPE_U64: /* fall through */ - case LBM_TYPE_I64: - case LBM_TYPE_DOUBLE: - return 8; - default: - return -1; - } -} - -static lbm_value index_list(lbm_value l, int32_t n) { - lbm_value curr = l; - - if (n < 0) { - int32_t len = (int32_t)lbm_list_length(l); - n = len + n; - if (n < 0) return ENC_SYM_NIL; - } - - while ( lbm_type_of(curr) == LBM_TYPE_CONS && - n > 0) { - curr = lbm_cdr(curr); - n --; - } - if (lbm_type_of(curr) == LBM_TYPE_CONS) { - return lbm_car(curr); - } else { - return ENC_SYM_NIL; - } -} - -static lbm_value assoc_lookup(lbm_value key, lbm_value assoc) { - lbm_value curr = assoc; - while (lbm_type_of(curr) == LBM_TYPE_CONS) { - lbm_value c = lbm_ref_cell(curr)->car; - if (struct_eq(lbm_ref_cell(c)->car, key)) { - return lbm_ref_cell(c)->cdr; - } - curr = lbm_ref_cell(curr)->cdr; - } - return ENC_SYM_NO_MATCH; -} - -static lbm_value cossa_lookup(lbm_value key, lbm_value assoc) { - lbm_value curr = assoc; - while (lbm_type_of(curr) == LBM_TYPE_CONS) { - lbm_value c = lbm_ref_cell(curr)->car; - if (struct_eq(lbm_ref_cell(c)->cdr, key)) { - return lbm_ref_cell(c)->car; - } - curr = lbm_ref_cell(curr)->cdr; - } - return ENC_SYM_NO_MATCH; -} - - - -/***************************************************/ -/* Fundamental operations */ - -typedef struct { - lbm_type type; - bool is_error; - union { - int32_t ival; - uint32_t uval; - float fval; - uint64_t u64val; - int64_t i64val; - double dval; - lbm_uint err_val; - } value; -} number_t; - -typedef void (*operation)(number_t *, lbm_value); - -static bool value_to_number(number_t *n, lbm_value v) { - switch(lbm_type_of(v)) { - case LBM_TYPE_I: n->type = LBM_TYPE_I; n->value.ival = lbm_dec_i(v); break; - case LBM_TYPE_U: n->type = LBM_TYPE_U; n->value.uval = lbm_dec_u(v); break; - case LBM_TYPE_U32: n->type = LBM_TYPE_U32; n->value.uval = lbm_dec_u32(v); break; - case LBM_TYPE_I32: n->type = LBM_TYPE_I32; n->value.ival = lbm_dec_i32(v); break; - case LBM_TYPE_FLOAT: n->type = LBM_TYPE_FLOAT; n->value.fval = lbm_dec_float(v); break; - case LBM_TYPE_U64: n->type = LBM_TYPE_U64; n->value.u64val = lbm_dec_u64(v); break; - case LBM_TYPE_I64: n->type = LBM_TYPE_I64; n->value.i64val = lbm_dec_i64(v); break; - case LBM_TYPE_DOUBLE: n->type = LBM_TYPE_DOUBLE; n->value.dval = lbm_dec_double(v); break; - default: - n->is_error = true; - n->value.err_val = ENC_SYM_TERROR; - return false; - } - n->is_error = false; - return true; -} - -static void number_to_i(number_t *n) { - switch(n->type) { - case LBM_TYPE_I: break; // the same - case LBM_TYPE_U: break; // same binary representation - case LBM_TYPE_U32: break; - case LBM_TYPE_I32: break; - case LBM_TYPE_FLOAT: n->value.ival = (int32_t)n->value.fval; break; - case LBM_TYPE_U64: n->value.ival = (int32_t)n->value.u64val; break; - case LBM_TYPE_I64: n->value.ival = (int32_t)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.ival = (int32_t)n->value.dval; break; - } - n->type = LBM_TYPE_I; -} - -static void number_to_u(number_t *n) { - switch(n->type) { - case LBM_TYPE_I: break; // the same - case LBM_TYPE_U: break; // same binary representation - case LBM_TYPE_U32: break; - case LBM_TYPE_I32: break; - case LBM_TYPE_FLOAT: n->value.uval = (uint32_t)n->value.fval; break; - case LBM_TYPE_U64: n->value.uval = (uint32_t)n->value.u64val; break; - case LBM_TYPE_I64: n->value.uval = (uint32_t)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.uval = (uint32_t)n->value.dval; break; - } - n->type = LBM_TYPE_U; -} - -static void number_to_f(number_t *n) { - switch(n->type) { - case LBM_TYPE_I32: /* fall through */ - case LBM_TYPE_I: n->value.fval = (float)n->value.ival; break; - case LBM_TYPE_U: /* fall through */ - case LBM_TYPE_U32: n->value.fval = (float)n->value.uval; break; - case LBM_TYPE_FLOAT: break; - case LBM_TYPE_U64: n->value.fval = (float)n->value.u64val; break; - case LBM_TYPE_I64: n->value.fval = (float)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.fval = (float)n->value.dval; break; - } - n->type = LBM_TYPE_FLOAT; -} - -static void number_to_i64(number_t *n) { - switch(n->type) { - case LBM_TYPE_I32: /* fall through */ - case LBM_TYPE_I: n->value.i64val = (int64_t)n->value.ival; break; - case LBM_TYPE_U: /* fall through */ - case LBM_TYPE_U32: n->value.i64val = (int64_t)n->value.uval; break; - case LBM_TYPE_FLOAT: n->value.i64val = (int64_t)n->value.fval; break; - case LBM_TYPE_U64: n->value.i64val = (int64_t)n->value.u64val; break; - case LBM_TYPE_I64: n->value.i64val = (int64_t)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.i64val = (int64_t)n->value.dval; break; - } - n->type = LBM_TYPE_I64; -} - -static void number_to_u64(number_t *n) { - switch(n->type) { - case LBM_TYPE_I32: /* fall through */ - case LBM_TYPE_I: n->value.u64val = (uint64_t)n->value.ival; break; - case LBM_TYPE_U: /* fall through */ - case LBM_TYPE_U32: n->value.u64val = (uint64_t)n->value.uval; break; - case LBM_TYPE_FLOAT: n->value.u64val = (uint64_t)n->value.fval; break; - case LBM_TYPE_U64: n->value.u64val = (uint64_t)n->value.u64val; break; - case LBM_TYPE_I64: n->value.u64val = (uint64_t)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.u64val = (uint64_t)n->value.dval; break; - } - n->type = LBM_TYPE_I64; -} - -static void number_to_d(number_t *n) { - switch(n->type) { - case LBM_TYPE_I32: /* fall through */ - case LBM_TYPE_I: n->value.dval = (double)n->value.ival; break; - case LBM_TYPE_U: /* fall through */ - case LBM_TYPE_U32: n->value.dval = (double)n->value.uval; break; - case LBM_TYPE_FLOAT: n->value.dval = (double)n->value.fval; break; - case LBM_TYPE_U64: n->value.dval = (double)n->value.u64val; break; - case LBM_TYPE_I64: n->value.dval = (double)n->value.i64val; break; - case LBM_TYPE_DOUBLE: n->value.dval = (double)n->value.dval; break; - } - n->type = LBM_TYPE_DOUBLE; -} - - -static void add_op(number_t *n, lbm_value v) { - lbm_type tval = lbm_type_of(v); - lbm_uint t = n->type < tval ? tval : n->type; - switch (t) { - case LBM_TYPE_I: number_to_i(n); n->value.ival += lbm_dec_as_i32(v); n->type = LBM_TYPE_I; break; - case LBM_TYPE_U: number_to_u(n); n->value.uval += lbm_dec_as_u32(v); n->type = LBM_TYPE_U; break; - case LBM_TYPE_U32: number_to_u(n); n->value.uval += lbm_dec_as_u32(v); n->type = LBM_TYPE_U32; break; - case LBM_TYPE_I32: number_to_i(n); n->value.ival += lbm_dec_as_i32(v); n->type = LBM_TYPE_I32; break; - case LBM_TYPE_FLOAT: number_to_f(n); n->value.fval += lbm_dec_as_float(v); n->type = LBM_TYPE_FLOAT; break; - case LBM_TYPE_U64: number_to_u64(n); n->value.u64val += lbm_dec_as_u64(v); n->type = LBM_TYPE_U64; break; - case LBM_TYPE_I64: number_to_i64(n); n->value.i64val += lbm_dec_as_i64(v); n->type = LBM_TYPE_I64; break; - case LBM_TYPE_DOUBLE: number_to_d(n); n->value.dval += lbm_dec_as_double(v); n->type = LBM_TYPE_DOUBLE; break; - } -} - -static void sub_op(number_t *n, lbm_value v) { - lbm_type tval = lbm_type_of(v); - lbm_uint t = n->type < tval ? tval : n->type; - switch (t) { - case LBM_TYPE_I: number_to_i(n); n->value.ival -= lbm_dec_as_i32(v); n->type = LBM_TYPE_I; break; - case LBM_TYPE_U: number_to_u(n); n->value.uval -= lbm_dec_as_u32(v); n->type = LBM_TYPE_U; break; - case LBM_TYPE_U32: number_to_u(n); n->value.uval -= lbm_dec_as_u32(v); n->type = LBM_TYPE_U32; break; - case LBM_TYPE_I32: number_to_i(n); n->value.ival -= lbm_dec_as_i32(v); n->type = LBM_TYPE_I32; break; - case LBM_TYPE_FLOAT: number_to_f(n); n->value.fval -= lbm_dec_as_float(v); n->type = LBM_TYPE_FLOAT; break; - case LBM_TYPE_U64: number_to_u64(n); n->value.u64val -= lbm_dec_as_u64(v); n->type = LBM_TYPE_U64; break; - case LBM_TYPE_I64: number_to_i64(n); n->value.i64val -= lbm_dec_as_i64(v); n->type = LBM_TYPE_I64; break; - case LBM_TYPE_DOUBLE: number_to_d(n); n->value.dval -= lbm_dec_as_double(v); n->type = LBM_TYPE_DOUBLE; break; - } -} - -static void mul_op(number_t *n, lbm_value v) { - lbm_type tval = lbm_type_of(v); - lbm_uint t = n->type < tval ? tval : n->type; - switch (t) { - case LBM_TYPE_I: number_to_i(n); n->value.ival *= lbm_dec_as_i32(v); n->type = LBM_TYPE_I; break; - case LBM_TYPE_U: number_to_u(n); n->value.uval *= lbm_dec_as_u32(v); n->type = LBM_TYPE_U; break; - case LBM_TYPE_U32: number_to_u(n); n->value.uval *= lbm_dec_as_u32(v); n->type = LBM_TYPE_U32; break; - case LBM_TYPE_I32: number_to_i(n); n->value.ival *= lbm_dec_as_i32(v); n->type = LBM_TYPE_I32; break; - case LBM_TYPE_FLOAT: number_to_f(n); n->value.fval *= lbm_dec_as_float(v); n->type = LBM_TYPE_FLOAT; break; - case LBM_TYPE_U64: number_to_u64(n); n->value.u64val *= lbm_dec_as_u64(v); n->type = LBM_TYPE_U64; break; - case LBM_TYPE_I64: number_to_i64(n); n->value.i64val *= lbm_dec_as_i64(v); n->type = LBM_TYPE_I64; break; - case LBM_TYPE_DOUBLE: number_to_d(n); n->value.dval *= lbm_dec_as_double(v); n->type = LBM_TYPE_DOUBLE; break; - } -} - -static void div_op(number_t *n, lbm_value v) { - lbm_type tval = lbm_type_of(v); - lbm_uint t = n->type < tval ? tval : n->type; - if (n->is_error) return; - switch (t) { - case LBM_TYPE_I: { - int32_t i = lbm_dec_as_i32(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i(n); - n->value.ival /= i; - n->type = LBM_TYPE_I; - break; - } - case LBM_TYPE_U: { - uint32_t u = lbm_dec_as_u32(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u(n); - n->value.uval /= u; - n->type = LBM_TYPE_U; - break; - } - case LBM_TYPE_U32: { - uint32_t u = lbm_dec_as_u32(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u(n); - n->value.uval /= u; - n->type = LBM_TYPE_U32; - break; - } - case LBM_TYPE_I32: { - int32_t i = lbm_dec_as_i32(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i(n); - n->value.ival /= i; - n->type = LBM_TYPE_I32; - break; - } - case LBM_TYPE_FLOAT: { - float f = lbm_dec_as_float(v); - if (f == 0.0f || f == -0.0f) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_f(n); - n->value.fval /= f; - n->type = LBM_TYPE_FLOAT; - break; - } - case LBM_TYPE_U64: { - uint64_t u = lbm_dec_as_u64(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u64(n); - n->value.u64val /= u; - n->type = LBM_TYPE_U64; - break; - } - case LBM_TYPE_I64: { - int64_t i = lbm_dec_as_i64(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i64(n); - n->value.i64val /= i; - n->type = LBM_TYPE_I64; - break; - } - case LBM_TYPE_DOUBLE: { - double d = lbm_dec_as_double(v); - if (d == (double)0.0 || d == (double)-0.0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_d(n); - n->value.dval /= d; - n->type = LBM_TYPE_DOUBLE; - break; - } - } -} - -static void mod_op(number_t *n, lbm_value v) { - lbm_type tval = lbm_type_of(v); - lbm_uint t = n->type < tval ? tval : n->type; - if (n->is_error) return; - switch (t) { - case LBM_TYPE_I: { - int32_t i = lbm_dec_as_i32(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i(n); - n->value.ival %= i; - n->type = LBM_TYPE_I; - break; - } - case LBM_TYPE_U: { - uint32_t u = lbm_dec_as_u32(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u(n); - n->value.uval %= u; - n->type = LBM_TYPE_U; - break; - } - case LBM_TYPE_U32: { - uint32_t u = lbm_dec_as_u32(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u(n); - n->value.uval %= u; - n->type = LBM_TYPE_U32; - break; - } - case LBM_TYPE_I32: { - int32_t i = lbm_dec_as_i32(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i(n); - n->value.ival %= i; - n->type = LBM_TYPE_I32; - break; - } - case LBM_TYPE_FLOAT: { - float f = lbm_dec_as_float(v); - if (f == 0.0f || f == -0.0f) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_f(n); - n->value.fval = fmodf(n->value.fval, f); - n->type = LBM_TYPE_FLOAT; - break; - } - case LBM_TYPE_U64: { - uint64_t u = lbm_dec_as_u64(v); - if (u == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_u64(n); - n->value.u64val %= u; - n->type = LBM_TYPE_U64; - break; - } - case LBM_TYPE_I64: { - int64_t i = lbm_dec_as_i64(v); - if (i == 0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_i64(n); - n->value.i64val %= i; - n->type = LBM_TYPE_I64; - break; - } - case LBM_TYPE_DOUBLE: { - double d = lbm_dec_as_double(v); - if (d == (double)0.0 || d == (double)-0.0) { - n->is_error = true; - n->value.err_val = ENC_SYM_DIVZERO; - return; - } - number_to_d(n); - n->value.dval = fmod(n->value.dval,d); - n->type = LBM_TYPE_DOUBLE; - break; - } - } -} - - -static lbm_value encode_number(number_t *n) { - lbm_value res; - switch(n->type) { - case LBM_TYPE_CHAR: res = lbm_enc_char((char)n->value.ival); break; - case LBM_TYPE_I: res = lbm_enc_i(n->value.ival); break; - case LBM_TYPE_U: res = lbm_enc_u(n->value.uval); break; - case LBM_TYPE_U32: res = lbm_enc_u32(n->value.uval); break; - case LBM_TYPE_I32: res = lbm_enc_i32(n->value.ival); break; - case LBM_TYPE_FLOAT: res = lbm_enc_float(n->value.fval); break; - case LBM_TYPE_U64: res = lbm_enc_u64(n->value.u64val); break; - case LBM_TYPE_I64: res = lbm_enc_i64(n->value.i64val); break; - case LBM_TYPE_DOUBLE: res = lbm_enc_double(n->value.dval); break; - default: res = ENC_SYM_TERROR; - } - return res; -} - -static bool numerical_reduce(operation op, number_t *id_res, lbm_value *args, lbm_uint nargs) { - for (lbm_uint i = 0; i < nargs; i ++) { - lbm_value val = args[i]; - if(!lbm_is_number(val)) return false; - op(id_res, val); - } - return true; -} - -void fundamental_add(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - - number_t n; - n.type = LBM_TYPE_U; - n.value.uval = 0; - if (numerical_reduce(add_op, &n, args, nargs)) { - lbm_value r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - lbm_perform_gc(); - r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - ERROR(ENC_SYM_MERROR); - } - } - RETURN(r); - } else { - ERROR(ENC_SYM_TERROR); - } -} - -void fundamental_sub(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - number_t n; - bool ok = false; - if (nargs == 1) { - n.value.uval = 0; - n.type = LBM_TYPE_U; - if (numerical_reduce(sub_op, &n, args, nargs)) { - ok = true; - } - } else { - if (value_to_number(&n, args[0])) { - if (numerical_reduce(sub_op, &n, args+1, nargs -1)) { - ok = true; - } - } - } - if (ok) { - lbm_value r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - lbm_perform_gc(); - r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - ERROR(ENC_SYM_MERROR); - } - } - RETURN(r); - } - ERROR(ENC_SYM_TERROR); -} - -void fundamental_mul(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - - number_t n; - n.type = LBM_TYPE_U; - n.value.uval = 1; - if (numerical_reduce(mul_op, &n, args, nargs)) { - lbm_value r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - lbm_perform_gc(); - r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - ERROR(ENC_SYM_MERROR); - } - } - RETURN(r); - } else { - ERROR(ENC_SYM_TERROR); - } -} - -void fundamental_div(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if(nargs >= 1) { - number_t n; - value_to_number(&n, args[0]); - if (numerical_reduce(div_op, &n, args+1, nargs -1)) { - lbm_value r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - lbm_perform_gc(); - r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - ERROR(ENC_SYM_MERROR); - } - } - RETURN(r); - } else if (n.is_error) { - ERROR(n.value.err_val); - } - } - ERROR(ENC_SYM_TERROR); -} - -void fundamental_mod(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if(nargs >= 1) { - number_t n; - value_to_number(&n, args[0]); - if (numerical_reduce(mod_op, &n, args+1, nargs -1)) { - lbm_value r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - lbm_perform_gc(); - r = encode_number(&n); - if (lbm_is_symbol_merror(r)) { - ERROR(ENC_SYM_MERROR); - } - } - RETURN(r); - } else if (n.is_error) { - ERROR(n.value.err_val); - } - } - ERROR(ENC_SYM_TERROR); -} - -void fundamental_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - r = r && struct_eq(a, b); - if (!r) break; - } - if (r) { - RETURN(ENC_SYM_TRUE); - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - fundamental_eq(args, nargs, ctx); - if (ctx->r == ENC_SYM_NIL) { - ctx->r = ENC_SYM_TRUE; - } else { - ctx->r = ENC_SYM_NIL; - } -} - - -void fundamental_numeq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - (void) ctx; - if (nargs <= 1) RETURN(ENC_SYM_TRUE); - - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - - if (!lbm_is_number(a)) { - ERROR(ENC_SYM_TERROR); - } - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - if (!lbm_is_number(b)) { - ERROR(ENC_SYM_TERROR); - break; - } - r = r && (compare(a, b) == 0); - if (!r) break; - } - if (r) { - RETURN(ENC_SYM_TRUE); - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_num_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - fundamental_numeq(args, nargs, ctx); - if (ctx->r == ENC_SYM_NIL) { - ctx->r = ENC_SYM_TRUE; - return; - } else if (ctx->r == ENC_SYM_TERROR) { - return; - } - ctx->r = ENC_SYM_NIL; - return; -} - - -void fundamental_lt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - - if (!lbm_is_number(a) || nargs < 2) { - ERROR(ENC_SYM_TERROR); - } - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - if (!lbm_is_number(b)) ERROR(ENC_SYM_TERROR); - r = r && (compare(a, b) == -1); - } - if (r) { - RETURN(ENC_SYM_TRUE) - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_gt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - if (!lbm_is_number(a)) ERROR(ENC_SYM_TERROR); - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - if (!lbm_is_number(b)) ERROR(ENC_SYM_TERROR); - r = r && (compare(a, b) == 1); - } - if (r) { - RETURN(ENC_SYM_TRUE); - } else { - RETURN(ENC_SYM_NIL); - } -} - -void fundamental_leq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - if (!lbm_is_number(a)) ERROR(ENC_SYM_TERROR); - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - if (!lbm_is_number(b)) ERROR(ENC_SYM_TERROR); - r = r && (compare(a, b) <= 0); - } - if (r) { - RETURN(ENC_SYM_TRUE); - } else { - RETURN(ENC_SYM_NIL); - } -} - -void fundamental_geq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_uint a = args[0]; - lbm_uint b; - bool r = true; - if (!lbm_is_number(a)) ERROR(ENC_SYM_TERROR); - for (lbm_uint i = 1; i < nargs; i ++) { - b = args[i]; - if (!lbm_is_number(b)) ERROR(ENC_SYM_TERROR); - r = r && (compare(a, b) >= 0); - } - if (r) { - RETURN(ENC_SYM_TRUE); - } else { - RETURN(ENC_SYM_NIL); - } -} - -void fundamental_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 0) { - RETURN(ENC_SYM_NIL); - } - lbm_uint a = args[0]; - if (lbm_type_of(a) == LBM_TYPE_SYMBOL && - lbm_dec_sym(a) == SYM_NIL) { - RETURN(ENC_SYM_TRUE); - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_gc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - (void) args; +static void array_read(lbm_value *args, lbm_uint nargs, lbm_uint *result) { (void) nargs; - lbm_perform_gc(); - RETURN(ENC_SYM_TRUE); -} - -void fundamental_self(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - (void) args; - (void) nargs; - RETURN(lbm_enc_i(ctx->id)); -} - -void fundamental_set_mailbox_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - - if (nargs == 1 && lbm_is_number(args[0])) { - uint32_t s = lbm_dec_as_u32(args[0]); - if (lbm_mailbox_change_size(ctx, s)) { - RETURN(ENC_SYM_TRUE); - } - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_cons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 2) ERROR(ENC_SYM_EERROR); - lbm_uint a = args[0]; - lbm_uint b = args[1]; - lbm_value c = lbm_cons(a,b); - if (lbm_is_symbol_merror(c)) { - lbm_perform_gc(); - c = lbm_cons(a,b); - } - if (lbm_is_symbol_merror(c)) ERROR(ENC_SYM_MERROR); - RETURN(c); -} - -void fundamental_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 1) { - if (lbm_type_of(args[0]) == LBM_TYPE_CONS) { - lbm_cons_t *cell = lbm_ref_cell(args[0]); - RETURN(cell->car); - } - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 1) { - if (lbm_type_of(args[0]) == LBM_TYPE_CONS) { - lbm_cons_t *cell = lbm_ref_cell(args[0]); - RETURN(cell->cdr); - } - } - RETURN(ENC_SYM_NIL); -} - -void fundamental_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_value result = lbm_heap_allocate_list(nargs); - if (lbm_is_symbol_merror(result)) { - lbm_perform_gc(); - result = lbm_heap_allocate_list(nargs); - } - if (lbm_is_symbol_merror(result)) ERROR(result); - if (lbm_is_cons(result)) { - lbm_value curr = result; - for (lbm_uint i = 0; i < nargs; i ++) { - lbm_set_car(curr, args[i]); - curr = lbm_cdr(curr); - } - } - RETURN(result); -} - -void fundamental_append(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 2) ERROR(ENC_SYM_TERROR); - lbm_value res = args[nargs-1]; - for (int i = (int)nargs -2; i >= 0; i --) { - lbm_value curr = args[i]; - int n = 0; - while (lbm_type_of(curr) == LBM_TYPE_CONS) { - n++; - curr = lbm_cdr(curr); - } - curr = args[i]; - for (int j = n-1; j >= 0; j --) { - WITH_GC_RMBR(res, lbm_cons(index_list(curr,j), res),1,res); - } - } - RETURN(res); -} - -void fundamental_undefine(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_value env = lbm_get_env(); - lbm_value result = ENC_SYM_EERROR; - if (nargs == 1 && lbm_is_symbol(args[0])) { - result = lbm_env_drop_binding(env, args[0]); - *lbm_get_env_ptr() = result; - RETURN(result); - } else if (nargs == 1 && lbm_is_cons(args[0])) { - lbm_value curr = args[0]; - while (lbm_type_of(curr) == LBM_TYPE_CONS) { - lbm_value key = lbm_car(curr); - result = lbm_env_drop_binding(env, key); - curr = lbm_cdr(curr); - } - *lbm_get_env_ptr() = result; - RETURN(result); - } - ERROR(result); -} - -void fundamental_array_read(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 2) ERROR(ENC_SYM_TERROR); + if (nargs < 2) return; // Args are: array, index lbm_value arr = args[0]; lbm_value index = args[1]; @@ -1042,104 +285,87 @@ void fundamental_array_read(lbm_value *args, lbm_uint nargs, eval_context_t *ctx for (lbm_int i = (lbm_int)ix_end; i >= (lbm_int)ix; i--) { if ((lbm_uint)i >= array->size){ - RETURN(ENC_SYM_NIL); + *result = ENC_SYM_NIL; + return; } - number_t r_val; + switch(array->elt_type) { case LBM_TYPE_CHAR: - r_val.type = LBM_TYPE_CHAR; - r_val.value.ival = ((char*)data)[i]; + curr = lbm_enc_char(((char*)data)[i]); break; case LBM_TYPE_U: - r_val.type = LBM_TYPE_U; - r_val.value.uval = (uint32_t)data[i]; + curr = lbm_enc_u((uint32_t)data[i]); break; case LBM_TYPE_I: - r_val.type = LBM_TYPE_I; - r_val.value.ival = (int32_t)data[i]; + curr = lbm_enc_i((int32_t)data[i]); break; case LBM_TYPE_U32: - r_val.type = LBM_TYPE_U32; - r_val.value.uval = (uint32_t)data[i]; + curr = lbm_enc_u32((uint32_t)data[i]); break; case LBM_TYPE_I32: - r_val.type = LBM_TYPE_U32; - r_val.value.ival = (int32_t)data[i]; + curr = lbm_enc_i32((int32_t)data[i]); break; case LBM_TYPE_FLOAT: { float v; memcpy(&v, &data[i], sizeof(float)); - r_val.type = LBM_TYPE_FLOAT; - r_val.value.fval = v; + curr = lbm_enc_float(v); } break; #ifndef LBM64 case LBM_TYPE_U64: { uint64_t v = 0; v |= (uint64_t)data[i*2]; v |= ((uint64_t)data[i*2+1]) << 32; - r_val.type = LBM_TYPE_U64; - r_val.value.u64val = v; + curr = lbm_enc_u64(v); } break; case LBM_TYPE_I64: { uint64_t v = 0; v |= (uint64_t)data[i*2]; v |= ((uint64_t)data[i*2+1]) << 32; - r_val.type = LBM_TYPE_I64; - r_val.value.i64val = (int64_t)v; + curr = lbm_enc_i64((int64_t)v); } break; case LBM_TYPE_DOUBLE: { double v; memcpy(&v, &data[i*2], sizeof(double)); - r_val.type = LBM_TYPE_DOUBLE; - r_val.value.dval = v; + curr = lbm_enc_double(v); } break; #else case LBM_TYPE_U64: - r_val.type = LBM_TYPE_U64; - r_val.value.u64val = data[i]; + curr = lbm_enc_u64(data[i]); break; case LBM_TYPE_I64: - r_val.type = LBM_TYPE_I64; - r_val.value.i64val = (int64_t)data[i]; + curr = lbm_enc_i64((int64_t)data[i]); break; case LBM_TYPE_DOUBLE: { double v; memcpy(&v, &data[i], sizeof(double)); - r_val.type = LBM_TYPE_DOUBLE; - r_val.value.dval = v; + curr = lbm_enc_double(v); } break; #endif default: - ERROR(ENC_SYM_EERROR); - } - curr = encode_number(&r_val); - if (lbm_is_symbol_merror(curr)) { - lbm_gc_mark_phase(1, acc); - lbm_perform_gc(); - curr = encode_number(&r_val); - if (lbm_is_symbol_merror(curr)) { - ERROR(ENC_SYM_MERROR); - } + curr = ENC_SYM_EERROR; + break; } if (read_many) { - WITH_GC_RMBR(acc, lbm_cons(curr, acc),1, acc); + acc = lbm_cons(curr, acc); } } /* for i */ } if (read_many) { - RETURN(acc); + *result = acc; + } else { + *result = curr; } - RETURN(curr); - } -void fundamental_array_write(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 3) ERROR(ENC_SYM_TERROR); +static void array_write(lbm_value *args, lbm_uint nargs, lbm_uint *result) { + (void) nargs; lbm_value arr = args[0]; lbm_value index = args[1]; lbm_value val = args[2]; lbm_uint ix; + *result = ENC_SYM_EERROR; + if (lbm_is_number(index)) { ix = lbm_dec_as_u32(index); } else { @@ -1148,8 +374,15 @@ void fundamental_array_write(lbm_value *args, lbm_uint nargs, eval_context_t *ct if (lbm_type_of(arr) == LBM_TYPE_ARRAY) { lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(arr); - if (array == NULL) ERROR(ENC_SYM_FATAL_ERROR); - if (ix >= array->size) RETURN(ENC_SYM_NIL); + if (array == NULL) { + *result = ENC_SYM_FATAL_ERROR; + return; + } + + if (ix >= array->size) { + *result = ENC_SYM_NIL; + return; + } switch(array->elt_type) { case LBM_TYPE_CHAR: { @@ -1224,550 +457,994 @@ void fundamental_array_write(lbm_value *args, lbm_uint nargs, eval_context_t *ct // Maybe result should be something else than arr here. break; } - RETURN(arr); + *result = arr; + return; } } -void fundamental_array_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - uint32_t n; - lbm_uint t_sym; - +/* (array-create type size) */ +static void array_create(lbm_value *args, lbm_uint nargs, lbm_value *result) { + *result = ENC_SYM_EERROR; if (nargs == 1 && lbm_is_number(args[0])) { - n = lbm_dec_as_u32(args[0]); - t_sym = SYM_TYPE_CHAR; - } else if (nargs == 2 && - lbm_type_of(args[0]) == LBM_TYPE_SYMBOL && - lbm_is_number(args[1])) { - n = lbm_dec_as_u32(args[1]); - t_sym = lbm_dec_sym(args[0]); - } else { - ERROR(ENC_SYM_TERROR); - } - - lbm_value result; - if (n > 0) { - bool retry = false;; - do { - switch(t_sym) { + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[0]), LBM_TYPE_BYTE); + } else if (nargs == 2) { + if (lbm_type_of(args[0]) == LBM_TYPE_SYMBOL && + lbm_is_number(args[1])) { + switch(lbm_dec_sym(args[0])) { case SYM_TYPE_CHAR: /* fall through */ case SYM_TYPE_BYTE: - lbm_heap_allocate_array(&result, n, LBM_TYPE_BYTE); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_BYTE); break; case SYM_TYPE_I32: - lbm_heap_allocate_array(&result, n, LBM_TYPE_I32); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_I32); break; case SYM_TYPE_U32: - lbm_heap_allocate_array(&result, n, LBM_TYPE_U32); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_U32); break; case SYM_TYPE_FLOAT: - lbm_heap_allocate_array(&result, n, LBM_TYPE_FLOAT); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_FLOAT); break; case SYM_TYPE_I64: - lbm_heap_allocate_array(&result, n, LBM_TYPE_I64); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_I64); break; case SYM_TYPE_U64: - lbm_heap_allocate_array(&result, n, LBM_TYPE_U64); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_U64); break; case SYM_TYPE_DOUBLE: - lbm_heap_allocate_array(&result, n, LBM_TYPE_DOUBLE); + lbm_heap_allocate_array(result, lbm_dec_as_u32(args[1]), LBM_TYPE_DOUBLE); break; default: break; } - if (!retry && lbm_is_symbol_merror(result)) { - lbm_perform_gc(); - retry = true; - } - else retry = false; - } while (retry); - } else { - lbm_set_error_reason((char*)lbm_error_str_incorrect_arg); - ERROR(ENC_SYM_EERROR); - } - RETURN(result); -} - -void fundamental_array_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs != 1) ERROR(ENC_SYM_TERROR); - - if (lbm_type_of(args[0]) == LBM_TYPE_ARRAY) { - lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(args[0]); - if (array == NULL) { - ERROR(ENC_SYM_FATAL_ERROR); } - RETURN(lbm_enc_u(array->size)); } - ERROR(ENC_SYM_TERROR); } -void fundamental_array_clear(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs != 1) ERROR(ENC_SYM_TERROR); +static int elt_size(lbm_type t) { + switch(t) { + case LBM_TYPE_BYTE: + return 1; + case LBM_TYPE_U32: /* fall through */ + case LBM_TYPE_I32: + case LBM_TYPE_FLOAT: + return 4; + case LBM_TYPE_U64: /* fall through */ + case LBM_TYPE_I64: + case LBM_TYPE_DOUBLE: + return 8; + default: + return -1; + } +} + +static lbm_value index_list(lbm_value l, int32_t n) { + lbm_value curr = l; + + if (n < 0) { + int32_t len = (int32_t)lbm_list_length(l); + n = len + n; + if (n < 0) return ENC_SYM_NIL; + } + + while ( lbm_type_of(curr) == LBM_TYPE_CONS && + n > 0) { + curr = lbm_cdr(curr); + n --; + } + if (lbm_type_of(curr) == LBM_TYPE_CONS) { + return lbm_car(curr); + } else { + return ENC_SYM_NIL; + } +} + +static lbm_value assoc_lookup(lbm_value key, lbm_value assoc) { + lbm_value curr = assoc; + while (lbm_type_of(curr) == LBM_TYPE_CONS) { + lbm_value c = lbm_ref_cell(curr)->car; + if (struct_eq(lbm_ref_cell(c)->car, key)) { + return lbm_ref_cell(c)->cdr; + } + curr = lbm_ref_cell(curr)->cdr; + } + return ENC_SYM_NO_MATCH; +} + +static lbm_value cossa_lookup(lbm_value key, lbm_value assoc) { + lbm_value curr = assoc; + while (lbm_type_of(curr) == LBM_TYPE_CONS) { + lbm_value c = lbm_ref_cell(curr)->car; + if (struct_eq(lbm_ref_cell(c)->cdr, key)) { + return lbm_ref_cell(c)->car; + } + curr = lbm_ref_cell(curr)->cdr; + } + return ENC_SYM_NO_MATCH; +} + + + +/***************************************************/ +/* Fundamental operations */ + +static lbm_value fundamental_add(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint sum = lbm_enc_u(0); + for (lbm_uint i = 0; i < nargs; i ++) { + sum = add2(sum, args[i]); + if (lbm_type_of(sum) == LBM_TYPE_SYMBOL) { + break; + } + } + return sum; +} + +static lbm_value fundamental_sub(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint res = nargs == 0 ? lbm_enc_u(0) : args[0]; + if (nargs == 1) { + res = negate(res); + } else { + for (lbm_uint i = 1; i < nargs; i ++) { + res = sub2(res, args[i]); + if (lbm_type_of(res) == LBM_TYPE_SYMBOL) + break; + } + } + return res; +} + +static lbm_value fundamental_mul(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint prod = lbm_enc_u(1); + for (lbm_uint i = 0; i < nargs; i ++) { + prod = mul2(prod, args[i]); + if (lbm_type_of(prod) == LBM_TYPE_SYMBOL) { + break; + } + } + return prod; +} + +static lbm_value fundamental_div(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint res = args[0]; + + if (nargs >= 1) { + for (lbm_uint i = 1; i < nargs; i ++) { + res = div2(res, args[i]); + if (lbm_type_of(res) == LBM_TYPE_SYMBOL) { + break; + } + } + } else { + res = ENC_SYM_EERROR; + } + return res; +} + +static lbm_value fundamental_mod(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint res = args[0]; + for (lbm_uint i = 1; i < nargs; i ++) { + res = mod2(res, args[i]); + if (lbm_type_of(res) == LBM_TYPE_SYMBOL) { + break; + } + } + return res; +} + +static lbm_value fundamental_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + r = r && struct_eq(a, b); + if (!r) break; + } + if (r) { + return ENC_SYM_TRUE; + } + return ENC_SYM_NIL; +} + +static lbm_value fundamental_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + lbm_value r = fundamental_eq(args, nargs, ctx); + if (r == ENC_SYM_NIL) { + return ENC_SYM_TRUE; + } else if (r == ENC_SYM_TERROR) { + return ENC_SYM_TERROR; + } + return ENC_SYM_NIL; +} + + +static lbm_value fundamental_numeq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + bool ok = true; + + if (!lbm_is_number(a)) { + return ENC_SYM_TERROR; + } + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + if (!lbm_is_number(b)) { + ok = false; + break; + } + r = r && (compare(a, b) == 0); + if (!r) break; + } + if (ok) { + if (r) { + return ENC_SYM_TRUE; + } else { + return ENC_SYM_NIL; + } + } + return ENC_SYM_TERROR; +} + +static lbm_value fundamental_num_not_eq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + lbm_value r = fundamental_numeq(args, nargs, ctx); + if (r == ENC_SYM_NIL) { + return ENC_SYM_TRUE; + } else if (r == ENC_SYM_TERROR) { + return ENC_SYM_TERROR; + } + return ENC_SYM_NIL; +} + + +static lbm_value fundamental_lt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + bool ok = true; + + if (!lbm_is_number(a)) { + return ENC_SYM_TERROR; + } + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + if (!lbm_is_number(b)) { + ok = false; + break; + } + r = r && (compare(a, b) == -1); + } + if (ok) { + if (r) { + return ENC_SYM_TRUE; + } else { + return ENC_SYM_NIL; + } + } + return ENC_SYM_TERROR; +} + +static lbm_value fundamental_gt(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + bool ok = true; + + if (!lbm_is_number(a)) { + return ENC_SYM_TERROR; + } + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + if (!lbm_is_number(b)) { + ok = false; + break; + } + r = r && (compare(a, b) == 1); + } + if (ok) { + if (r) { + return ENC_SYM_TRUE; + } else { + return ENC_SYM_NIL; + } + } + return ENC_SYM_TERROR; +} + +static lbm_value fundamental_leq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + bool ok = true; + + if (!lbm_is_number(a)) { + return ENC_SYM_TERROR; + } + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + if (!lbm_is_number(b)) { + ok = false; + break; + } + r = r && (compare(a, b) <= 0); + } + if (ok) { + if (r) { + return ENC_SYM_TRUE; + } else { + return ENC_SYM_NIL; + } + } + return ENC_SYM_TERROR; +} + +static lbm_value fundamental_geq(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + lbm_uint a = args[0]; + lbm_uint b; + bool r = true; + bool ok = true; + + if (!lbm_is_number(a)) { + return ENC_SYM_TERROR; + } + for (lbm_uint i = 1; i < nargs; i ++) { + b = args[i]; + if (!lbm_is_number(b)) { + ok = false; + break; + } + r = r && (compare(a, b) >= 0); + } + if (ok) { + if (r) { + return ENC_SYM_TRUE; + } else { + return ENC_SYM_NIL; + } + } + return ENC_SYM_TERROR; +} + +static lbm_value fundamental_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + + if (nargs == 0) { + return ENC_SYM_NIL; + } + lbm_uint a = args[0]; + if (lbm_type_of(a) == LBM_TYPE_SYMBOL && + lbm_dec_sym(a) == SYM_NIL) { + return ENC_SYM_TRUE; + } + return ENC_SYM_NIL; +} + +static lbm_value fundamental_gc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) args; + (void) nargs; + (void) ctx; + lbm_perform_gc(); + return ENC_SYM_TRUE; +} + +static lbm_value fundamental_self(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) args; + (void) nargs; + (void) ctx; + return lbm_enc_i(ctx->id); +} + +static lbm_value fundamental_set_mailbox_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + + if (nargs == 1 && lbm_is_number(args[0])) { + uint32_t s = lbm_dec_as_u32(args[0]); + if (lbm_mailbox_change_size(ctx, s)) { + return ENC_SYM_TRUE; + } + } + return ENC_SYM_NIL; +} + +static lbm_value fundamental_cons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs < 2) return ENC_SYM_EERROR; + lbm_uint a = args[0]; + lbm_uint b = args[1]; + return lbm_cons(a,b); +} + +static lbm_value fundamental_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs == 1) { + if (lbm_type_of(args[0]) == LBM_TYPE_CONS) { + lbm_cons_t *cell = lbm_ref_cell(args[0]); + return cell->car; + } + } + return ENC_SYM_NIL; +} + +static lbm_value fundamental_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs == 1) { + if (lbm_type_of(args[0]) == LBM_TYPE_CONS) { + lbm_cons_t *cell = lbm_ref_cell(args[0]); + return cell->cdr; + } + } + return ENC_SYM_NIL; +} + +static lbm_value fundamental_list(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_NIL; + for (lbm_uint i = 1; i <= nargs; i ++) { + result = lbm_cons(args[nargs-i], result); + if (lbm_type_of(result) == LBM_TYPE_SYMBOL) + break; + } + return result; +} + +static lbm_value fundamental_append(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs < 2) return(ENC_SYM_TERROR); + lbm_value res = args[nargs-1]; + for (int i = (int)nargs -2; i >= 0; i --) { + lbm_value curr = args[i]; + int n = 0; + while (lbm_type_of(curr) == LBM_TYPE_CONS) { + n++; + curr = lbm_cdr(curr); + } + curr = args[i]; + for (int j = n-1; j >= 0; j --) { + res = lbm_cons(index_list(curr,j),res); + } + } + return(res); +} + +static lbm_value fundamental_undefine(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value env = lbm_get_env(); + lbm_value result = ENC_SYM_EERROR; + if (nargs == 1 && lbm_is_symbol(args[0])) { + result = lbm_env_drop_binding(env, args[0]); + *lbm_get_env_ptr() = result; + } else if (nargs == 1 && lbm_is_cons(args[0])) { + lbm_value curr = args[0]; + while (lbm_type_of(curr) == LBM_TYPE_CONS) { + lbm_value key = lbm_car(curr); + result = lbm_env_drop_binding(env, key); + curr = lbm_cdr(curr); + } + *lbm_get_env_ptr() = result; + } + return result; +} + +static lbm_value fundamental_array_read(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + array_read(args, nargs, &result); + return result; +} + +static lbm_value fundamental_array_write(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + array_write(args, nargs, &result); + return result; +} + +static lbm_value fundamental_array_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + array_create(args, nargs, &result); + return result; +} + +static lbm_value fundamental_array_size(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + if (nargs != 1) return result; if (lbm_type_of(args[0]) == LBM_TYPE_ARRAY) { lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(args[0]); if (array == NULL) { - ERROR(ENC_SYM_FATAL_ERROR); + result = ENC_SYM_FATAL_ERROR; + return result; + } + result = lbm_enc_u(array->size); + } + return result; +} + +static lbm_value fundamental_array_clear(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + if (nargs != 1) return ENC_SYM_EERROR; + + if (lbm_type_of(args[0]) == LBM_TYPE_ARRAY) { + lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(args[0]); + if (array == NULL) { + return ENC_SYM_FATAL_ERROR; } int es = elt_size(array->elt_type); - if (es < 0) ERROR(ENC_SYM_TERROR); + + if (es < 0) return result; + memset(array->data, 0, array->size ); + result = args[0]; } - RETURN(args[0]); + return result; } -void fundamental_symbol_to_string(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_symbol_to_string(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; if (nargs < 1 || lbm_type_of(args[0]) != LBM_TYPE_SYMBOL) - ERROR(ENC_SYM_TERROR); + return ENC_SYM_NIL; lbm_value sym = args[0]; const char *sym_str = lbm_get_name_by_symbol(lbm_dec_sym(sym)); - if (sym_str == NULL) ERROR(ENC_SYM_FATAL_ERROR); + if (sym_str == NULL) return ENC_SYM_NIL; size_t len = strlen(sym_str); lbm_value v; - if (!lbm_heap_allocate_array(&v, len+1, LBM_TYPE_CHAR)) { - lbm_perform_gc(); - lbm_heap_allocate_array(&v, len+1, LBM_TYPE_CHAR); + if (lbm_heap_allocate_array(&v, len+1, LBM_TYPE_CHAR)) { + lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(v); + if (!arr) return ENC_SYM_MERROR; + memset(arr->data,0,len+1); + memcpy(arr->data,sym_str,len); + } else { + return ENC_SYM_MERROR; } - if (lbm_is_symbol_merror(v)) ERROR(v); - lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(v); - if (!arr) ERROR(ENC_SYM_FATAL_ERROR); - memset(arr->data,0,len+1); - memcpy(arr->data,sym_str,len); - RETURN(v); + return v; } -void fundamental_string_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_string_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs < 1 || lbm_type_of(args[0] != LBM_TYPE_ARRAY)) - ERROR(ENC_SYM_TERROR); + return result; lbm_array_header_t *arr = (lbm_array_header_t *)lbm_car(args[0]); - if (!arr) ERROR(ENC_SYM_FATAL_ERROR); - if (arr->elt_type != LBM_TYPE_CHAR) ERROR(ENC_SYM_TERROR); + if (!arr) return ENC_SYM_FATAL_ERROR; + if (arr->elt_type != LBM_TYPE_CHAR) + return result; char *str = (char *)arr->data; lbm_uint sym; if (lbm_get_symbol_by_name(str, &sym)) { - RETURN(lbm_enc_sym(sym)); + result = lbm_enc_sym(sym); } else if (lbm_add_symbol(str, &sym)) { - RETURN(lbm_enc_sym(sym)); + result = lbm_enc_sym(sym); } - ERROR(ENC_SYM_FATAL_ERROR); + return result; } -void fundamental_symbol_to_uint(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 1) ERROR(ENC_SYM_TERROR); +static lbm_value fundamental_symbol_to_uint(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs < 1) return ENC_SYM_EERROR; lbm_value s = args[0]; if (lbm_type_of(s) == LBM_TYPE_SYMBOL) - RETURN(lbm_enc_u(lbm_dec_sym(s))); - ERROR(ENC_SYM_TERROR); + return lbm_enc_u(lbm_dec_sym(s)); + else + return ENC_SYM_TERROR; } -void fundamental_uint_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs < 1) ERROR(ENC_SYM_TERROR); +static lbm_value fundamental_uint_to_symbol(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs < 1) return ENC_SYM_EERROR; lbm_value s = args[0]; if (lbm_type_of(s) == LBM_TYPE_U) - RETURN(lbm_enc_sym(lbm_dec_u(s))); - ERROR(ENC_SYM_TERROR); + return lbm_enc_sym(lbm_dec_u(s)); + else + return ENC_SYM_TERROR; } -void fundamental_set_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_set_car(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; if (nargs == 2) { if (lbm_set_car(args[0],args[1])) { - RETURN(args[0]); + return ENC_SYM_TRUE; } else { - RETURN(ENC_SYM_NIL); + return ENC_SYM_NIL; } } - ERROR(ENC_SYM_TERROR); + return ENC_SYM_EERROR; } -void fundamental_set_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_set_cdr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; if (nargs == 2) { if (lbm_set_cdr(args[0],args[1])) { - RETURN(args[0]); + return ENC_SYM_TRUE; } else { - RETURN(ENC_SYM_NIL); + return ENC_SYM_NIL; } } - ERROR(ENC_SYM_TERROR); + return ENC_SYM_EERROR; } -void fundamental_set_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs != 3 || - !lbm_is_cons(args[0]) || - !lbm_is_number(args[1])) - ERROR(ENC_SYM_TERROR); - - lbm_value curr = args[0]; - lbm_uint i = 0; - lbm_uint ix = lbm_dec_as_u32(args[1]); - lbm_value result = ENC_SYM_NIL; - while (lbm_is_ptr(curr)) { - if (i == ix) { - lbm_set_car(curr, args[2]); - result = args[0]; - break; - } else if (i > ix) { - break; +static lbm_value fundamental_set_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + if (nargs == 3) { + if (lbm_is_cons(args[0]) && + lbm_is_number(args[1])) { + lbm_value curr = args[0]; + lbm_uint i = 0; + lbm_uint ix = lbm_dec_as_u32(args[1]); + result = ENC_SYM_NIL; + while (lbm_is_ptr(curr)) { + if (i == ix) { + lbm_set_car(curr, args[2]); + result = args[0]; + break; + } else if (i > ix) { + break; + } + curr = lbm_cdr(curr); + i++; + } } - curr = lbm_cdr(curr); - i++; } - RETURN(result); + return result; } -void fundamental_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 2) { if (lbm_is_cons(args[0])) { lbm_value r = assoc_lookup(args[1], args[0]); if (lbm_is_symbol(r) && lbm_dec_sym(r) == SYM_NO_MATCH) { - RETURN(ENC_SYM_NIL); + result = ENC_SYM_NIL; } else { - RETURN(r); + result = r; } } else if (lbm_is_symbol(args[0]) && lbm_dec_sym(args[0]) == SYM_NIL) { - RETURN(args[0]); /* nil */ + result = args[0]; /* nil */ } /* else error */ } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_acons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - lbm_value keyval; - lbm_value new_alist; - bool retry = false; - do { - if (nargs == 3) { - keyval = lbm_cons(args[0], args[1]); - new_alist = lbm_cons(keyval,args[2]); - } else if (nargs == 2) { - new_alist = lbm_cons(args[0], args[1]); - RETURN(new_alist); - } else { - ERROR(ENC_SYM_TERROR); - } - if (!retry && lbm_is_symbol_merror(new_alist)) { - lbm_perform_gc(); - retry = true; - } else retry = false; - } while(retry); - RETURN(new_alist); -} - -void fundamental_set_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_acons(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 3) { - RETURN(lbm_env_set(args[0], args[1], args[2])); + lbm_value keyval = lbm_cons(args[0], args[1]); + lbm_value new_alist = lbm_cons(keyval, args[2]); + + if (lbm_is_symbol(keyval) || + lbm_is_symbol(new_alist) ) + result = ENC_SYM_MERROR; + else + result = new_alist; + } else if (nargs == 2) { + result = lbm_cons(args[0], args[1]); + } + return result; +} + +static lbm_value fundamental_set_assoc(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; + if (nargs == 3) { + result = lbm_env_set(args[0], args[1], args[2]); } else if (nargs == 2 && lbm_is_cons(args[1])) { lbm_value x = lbm_car(args[1]); lbm_value xs = lbm_cdr(args[1]); - RETURN(lbm_env_set(args[0], x, xs)); + result = lbm_env_set(args[0], x, xs); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_cossa(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_cossa(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 2) { if (lbm_is_cons(args[0])) { lbm_value r = cossa_lookup(args[1], args[0]); if (lbm_is_symbol(r) && lbm_dec_sym(r) == SYM_NO_MATCH) { - RETURN(ENC_SYM_NIL); + result = ENC_SYM_NIL; } else { - RETURN(r); + result = r; } } else if (lbm_is_symbol(args[0]) && lbm_dec_sym(args[0]) == SYM_NIL) { - RETURN(ENC_SYM_NIL); + result = args[0]; /* nil */ } /* else error */ } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_ix(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 2 && lbm_is_number(args[1])) { - RETURN(index_list(args[0], lbm_dec_as_i32(args[1]))); + result = index_list(args[0], lbm_dec_as_i32(args[1])); } - ERROR(ENC_SYM_TERROR) + return result; } -void fundamental_to_i(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_i(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - RETURN(lbm_enc_i((lbm_int)lbm_dec_as_i64(args[0]))); + result = lbm_enc_i((lbm_int)lbm_dec_as_i64(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_i32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_i32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_i32(lbm_dec_as_i32(args[0]))); - RETURN(result); + result = lbm_enc_i32(lbm_dec_as_i32(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_u(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_u(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - RETURN(lbm_enc_u((lbm_uint)lbm_dec_as_u64(args[0]))); + result = lbm_enc_u((lbm_uint)lbm_dec_as_u64(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_u32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_u32(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_u32(lbm_dec_as_u32(args[0]))); - RETURN(result); + result = lbm_enc_u32(lbm_dec_as_u32(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_float(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_float(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_float(lbm_dec_as_float(args[0]))); - RETURN(result); + result = lbm_enc_float(lbm_dec_as_float(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_i64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_i64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_i64(lbm_dec_as_i64(args[0]))); - RETURN(result); + result = lbm_enc_i64(lbm_dec_as_i64(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_u64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_u64(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_u64(lbm_dec_as_u64(args[0]))); - RETURN(result); + result = lbm_enc_u64(lbm_dec_as_u64(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_double(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_double(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - lbm_value result; - WITH_GC(result, lbm_enc_double(lbm_dec_as_double(args[0]))); - RETURN(result); + result = lbm_enc_double(lbm_dec_as_double(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_to_byte(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_to_byte(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1) { - RETURN(lbm_enc_char(lbm_dec_as_char(args[0]))); + result = lbm_enc_char(lbm_dec_as_char(args[0])); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_shl(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 2 && - lbm_is_number(args[0]) && lbm_is_number(args[1])) { - - number_t n; +static lbm_value fundamental_shl(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 2) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]) && lbm_is_number(args[1]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (lbm_dec_i(args[0]) << lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (lbm_dec_u(args[0]) << lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U32; n.value.uval = (lbm_dec_u32(args[0]) << lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I32; n.value.ival = (lbm_dec_i32(args[0]) << lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (lbm_dec_i64(args[0]) << lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (lbm_dec_u64(args[0]) << lbm_dec_as_u32(args[1])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) << lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) << lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) << lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) << lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) << lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) << lbm_dec_as_u32(args[1])); break; } - - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_shr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 2 && - lbm_is_number(args[0]) && lbm_is_number(args[1])) { - number_t n; +static lbm_value fundamental_shr(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 2) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]) && lbm_is_number(args[1]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (lbm_dec_i(args[0]) >> lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (lbm_dec_u(args[0]) >> lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U32; n.value.uval = (lbm_dec_u32(args[0]) >> lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I32; n.value.ival = (lbm_dec_i32(args[0]) >> lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (lbm_dec_i64(args[0]) >> lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (lbm_dec_u64(args[0]) >> lbm_dec_as_u32(args[1])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) >> lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) >> lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) >> lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) >> lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) >> lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) >> lbm_dec_as_u32(args[1])); break; } - - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_bitwise_and(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 2 && - lbm_is_number(args[0]) && lbm_is_number(args[1])) { - - number_t n; +static lbm_value fundamental_bitwise_and(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 2) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]) && lbm_is_number(args[1]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (lbm_dec_i(args[0]) & lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (lbm_dec_u(args[0]) & lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U32; n.value.uval = (lbm_dec_u32(args[0]) & lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I32; n.value.ival = (lbm_dec_i32(args[0]) & lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (lbm_dec_i64(args[0]) & lbm_dec_as_i64(args[1])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (lbm_dec_u64(args[0]) & lbm_dec_as_u64(args[1])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) & lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) & lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) & lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) & lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) & lbm_dec_as_i64(args[1])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) & lbm_dec_as_u64(args[1])); break; } - - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_bitwise_or(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 2 && - lbm_is_number(args[0]) && lbm_is_number(args[1])) { - - number_t n; +static lbm_value fundamental_bitwise_or(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 2) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]) && lbm_is_number(args[1]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (lbm_dec_i(args[0]) | lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (lbm_dec_u(args[0]) | lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U32; n.value.uval = (lbm_dec_u32(args[0]) | lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I32; n.value.ival = (lbm_dec_i32(args[0]) | lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (lbm_dec_i64(args[0]) | lbm_dec_as_i64(args[1])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (lbm_dec_u64(args[0]) | lbm_dec_as_u64(args[1])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) | lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) | lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) | lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) | lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) | lbm_dec_as_i64(args[1])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) | lbm_dec_as_u64(args[1])); break; } - - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_bitwise_xor(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 2 && - lbm_is_number(args[0]) && lbm_is_number(args[1])) { - - number_t n; +static lbm_value fundamental_bitwise_xor(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 2) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]) && lbm_is_number(args[1]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (lbm_dec_i(args[0]) ^ lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (lbm_dec_u(args[0]) ^ lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U32; n.value.uval = (lbm_dec_u32(args[0]) ^ lbm_dec_as_u32(args[1])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I32; n.value.ival = (lbm_dec_i32(args[0]) ^ lbm_dec_as_i32(args[1])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (lbm_dec_i64(args[0]) ^ lbm_dec_as_i64(args[1])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (lbm_dec_u64(args[0]) ^ lbm_dec_as_u64(args[1])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(lbm_dec_i(args[0]) ^ lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_U: retval = lbm_enc_u(lbm_dec_u(args[0]) ^ lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(lbm_dec_u32(args[0]) ^ lbm_dec_as_u32(args[1])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(lbm_dec_i32(args[0]) ^ lbm_dec_as_i32(args[1])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(lbm_dec_i64(args[0]) ^ lbm_dec_as_i64(args[1])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(lbm_dec_u64(args[0]) ^ lbm_dec_as_u64(args[1])); break; } - - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_bitwise_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 1 && - lbm_is_number(args[0])) { - - number_t n; +static lbm_value fundamental_bitwise_not(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value retval = ENC_SYM_EERROR; + if (nargs == 1) { + retval = ENC_SYM_TERROR; + if (!(lbm_is_number(args[0]))) { + return retval; + } switch (lbm_type_of(args[0])) { - case LBM_TYPE_I: n.type = LBM_TYPE_I; n.value.ival = (~lbm_dec_i(args[0])); break; - case LBM_TYPE_U: n.type = LBM_TYPE_U; n.value.uval = (~lbm_dec_u(args[0])); break; - case LBM_TYPE_U32: n.type = LBM_TYPE_U; n.value.uval = (~lbm_dec_u32(args[0])); break; - case LBM_TYPE_I32: n.type = LBM_TYPE_I; n.value.ival = (~lbm_dec_i32(args[0])); break; - case LBM_TYPE_I64: n.type = LBM_TYPE_I64; n.value.i64val = (~lbm_dec_i64(args[0])); break; - case LBM_TYPE_U64: n.type = LBM_TYPE_U64; n.value.u64val = (~lbm_dec_u64(args[0])); break; - default: ERROR(ENC_SYM_TERROR); + case LBM_TYPE_I: retval = lbm_enc_i(~lbm_dec_i(args[0])); break; + case LBM_TYPE_U: retval = lbm_enc_u(~lbm_dec_u(args[0])); break; + case LBM_TYPE_U32: retval = lbm_enc_u32(~lbm_dec_u32(args[0])); break; + case LBM_TYPE_I32: retval = lbm_enc_i32(~lbm_dec_i32(args[0])); break; + case LBM_TYPE_I64: retval = lbm_enc_i64(~lbm_dec_i64(args[0])); break; + case LBM_TYPE_U64: retval = lbm_enc_u64(~lbm_dec_u64(args[0])); break; } - lbm_value res = encode_number(&n); - if (lbm_is_symbol_merror(res)) { - lbm_perform_gc(); - res = encode_number(&n); - if (lbm_is_symbol_merror(res)) ERROR(ENC_SYM_MERROR); - } - RETURN(res); } - ERROR(ENC_SYM_TERROR); + return retval; } -void fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_custom_destruct(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1 && (lbm_type_of(args[0]) == LBM_TYPE_CUSTOM)) { lbm_uint *mem_ptr = (lbm_uint*)lbm_dec_custom(args[0]); - if(!mem_ptr) ERROR(ENC_SYM_FATAL_ERROR); + if(!mem_ptr) return ENC_SYM_FATAL_ERROR; lbm_custom_type_destroy(mem_ptr); lbm_value tmp = lbm_set_ptr_type(args[0], LBM_TYPE_CONS); lbm_set_car(tmp, ENC_SYM_NIL); lbm_set_cdr(tmp, ENC_SYM_NIL); /* The original value will still be of type custom_ptr */ - RETURN(ENC_SYM_TRUE); + result = ENC_SYM_TRUE; } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (nargs == 1) { - lbm_value val = args[0]; - lbm_value res; - switch(lbm_type_of(val)) { - case LBM_TYPE_CONS: res = ENC_SYM_TYPE_LIST; break; - case LBM_TYPE_ARRAY: res = ENC_SYM_TYPE_ARRAY; break; - case LBM_TYPE_I32: res = ENC_SYM_TYPE_I32; break; - case LBM_TYPE_U32: res = ENC_SYM_TYPE_U32; break; - case LBM_TYPE_FLOAT: res = ENC_SYM_TYPE_FLOAT; break; - case LBM_TYPE_I64: res = ENC_SYM_TYPE_I64; break; - case LBM_TYPE_U64: res = ENC_SYM_TYPE_U64; break; - case LBM_TYPE_DOUBLE: res = ENC_SYM_TYPE_DOUBLE; break; - case LBM_TYPE_I: res = ENC_SYM_TYPE_I; break; - case LBM_TYPE_U: res = ENC_SYM_TYPE_U; break; - case LBM_TYPE_CHAR: res = ENC_SYM_TYPE_CHAR; break; - case LBM_TYPE_SYMBOL: res = ENC_SYM_TYPE_SYMBOL; break; - default: res = ENC_SYM_NIL; break; - } - RETURN(res); +static lbm_value fundamental_type_of(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + if (nargs != 1) return ENC_SYM_NIL; + lbm_value val = args[0]; + switch(lbm_type_of(val)) { + case LBM_TYPE_CONS: return ENC_SYM_TYPE_LIST; + case LBM_TYPE_ARRAY: return ENC_SYM_TYPE_ARRAY; + case LBM_TYPE_I32: return ENC_SYM_TYPE_I32; + case LBM_TYPE_U32: return ENC_SYM_TYPE_U32; + case LBM_TYPE_FLOAT: return ENC_SYM_TYPE_FLOAT; + case LBM_TYPE_I64: return ENC_SYM_TYPE_I64; + case LBM_TYPE_U64: return ENC_SYM_TYPE_U64; + case LBM_TYPE_DOUBLE: return ENC_SYM_TYPE_DOUBLE; + case LBM_TYPE_I: return ENC_SYM_TYPE_I; + case LBM_TYPE_U: return ENC_SYM_TYPE_U; + case LBM_TYPE_CHAR: return ENC_SYM_TYPE_CHAR; + case LBM_TYPE_SYMBOL: return ENC_SYM_TYPE_SYMBOL; } - ERROR(ENC_SYM_TERROR); + return ENC_SYM_TERROR; } -void fundamental_list_length(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_list_length(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; if (nargs == 1 && lbm_is_list(args[0])) { int32_t len = (int32_t)lbm_list_length(args[0]); - RETURN(lbm_enc_i(len)); + result = lbm_enc_i(len); } - ERROR(ENC_SYM_TERROR); + return result; } -void fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; + lbm_value result = ENC_SYM_EERROR; int32_t start; int32_t end; @@ -1782,49 +1459,99 @@ void fundamental_range(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { start = lbm_dec_as_i32(args[0]); end = lbm_dec_as_i32(args[1]); } else { - ERROR(ENC_SYM_TERROR); + return result; } - int num; - if (end == start) { - RETURN(ENC_SYM_NIL); - } else if (end < start) { + if (end == start) return ENC_SYM_NIL; + else if (end < start) { + int32_t tmp = end; + end = start; + start = tmp; rev = true; - num = start - end; - } else { - num = end - start; } - lbm_value r_list = lbm_heap_allocate_list((unsigned int)num); - if (lbm_is_symbol_merror(r_list)) { - lbm_perform_gc(); - r_list = lbm_heap_allocate_list((unsigned int)num); + int num = end - start; + + if ((unsigned int)num > lbm_heap_num_free()) { + return ENC_SYM_MERROR; } - if (lbm_is_symbol_merror(r_list)) { - ERROR(ENC_SYM_MERROR); + + lbm_value r_list = ENC_SYM_NIL; + for (int i = end - 1; i >= start; i --) { + r_list = lbm_cons(lbm_enc_i(i), r_list); } - if (lbm_is_cons(r_list)) { - lbm_value curr = r_list; - if (rev) { - for (int i = start-1; i >= end; i --) { - lbm_set_car(curr, lbm_enc_i(i)); - curr = lbm_cdr(curr); - } - } else { - for (int i = start; i < end; i ++) { - lbm_set_car(curr, lbm_enc_i(i)); - curr = lbm_cdr(curr); - } - } - } - RETURN(r_list) + return rev ? lbm_list_destructive_reverse(r_list) : r_list; } -void fundamental_reg_event_handler(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { +static lbm_value fundamental_reg_event_handler(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + (void) ctx; if (nargs != 1 || !lbm_is_number(args[0])) { - ERROR(ENC_SYM_TERROR); + return ENC_SYM_TERROR; } lbm_set_event_handler_pid((lbm_cid)lbm_dec_i(args[0])); - RETURN(ENC_SYM_TRUE); + return(ENC_SYM_TRUE); } + +const fundamental_fun fundamental_table[] = + {fundamental_add, + fundamental_sub, + fundamental_mul, + fundamental_div, + fundamental_mod, + fundamental_eq, + fundamental_not_eq, + fundamental_numeq, + fundamental_num_not_eq, + fundamental_lt, + fundamental_gt, + fundamental_leq, + fundamental_geq, + fundamental_not, + fundamental_gc, + fundamental_self, + fundamental_set_mailbox_size, + fundamental_cons, + fundamental_car, + fundamental_cdr, + fundamental_list, + fundamental_append, + fundamental_undefine, + fundamental_array_read, + fundamental_array_write, + fundamental_array_create, + fundamental_array_size, + fundamental_array_clear, + fundamental_symbol_to_string, + fundamental_string_to_symbol, + fundamental_symbol_to_uint, + fundamental_uint_to_symbol, + fundamental_set_car, + fundamental_set_cdr, + fundamental_set_ix, + fundamental_assoc, + fundamental_acons, + fundamental_set_assoc, + fundamental_cossa, + fundamental_ix, + fundamental_to_i, + fundamental_to_i32, + fundamental_to_u, + fundamental_to_u32, + fundamental_to_float, + fundamental_to_i64, + fundamental_to_u64, + fundamental_to_double, + fundamental_to_byte, + fundamental_shl, + fundamental_shr, + fundamental_bitwise_and, + fundamental_bitwise_or, + fundamental_bitwise_xor, + fundamental_bitwise_not, + fundamental_custom_destruct, + fundamental_type_of, + fundamental_list_length, + fundamental_range, + fundamental_reg_event_handler + };