diff --git a/doc/lbmref.md b/doc/lbmref.md index 165cf14c..80818506 100644 --- a/doc/lbmref.md +++ b/doc/lbmref.md @@ -1013,64 +1013,6 @@ Functions can be moved to flash storage as well: (move-to-flash f) ``` -### make-env - -The `make-env` form allows you to create an environment as a value. -The form of an `make-env` expression is `(make-env exp)`. When -The result of running `(make-env exp)` is the resulting environment after -evaluating the expression `exp`. The resulting environment is an association list. - -`make-env` can be used to encapsulate a set of bindings under a name. - -Example: - -```clj -(define my-env (make-env { - (defun f (x) (+ x 1)) - (defun g (x y) (+ x y)) - })) -``` - -See `in-env` for how to evaluate expressions inside of a provided environment. - ---- - - -### in-env - -The `in-env` form allows the evaluation in an environment that has -been augmented by an environment (association list) provided. -The form of an `in-env` expression is `(in-env env-expr expr)`. Here the -expression `expr` is evaluated with the local environemnt augmented with -the result of `env-expr`. The resulting environment of a `make-env` application -is compatible with the `env-expr` of `in-env` but any association list is ok. - -Example: - -```clj -(define my-env '( (a . 10) (b . 20))) - -(in-env my-env (+ a b)) -``` - -The example above evaluates to 30. - -Example combining `in-env` and `make-env`: - -```clj -(define lib - (make-env { - (define a 10) - (define b 20) - (define c 30) - })) - - -(in-env lib (+ a b)) -``` - - - --- ## Lists and cons cells diff --git a/include/eval_cps.h b/include/eval_cps.h index de73393a..7cc723ba 100644 --- a/include/eval_cps.h +++ b/include/eval_cps.h @@ -58,6 +58,7 @@ typedef struct eval_context_s{ lbm_uint sleep_us; lbm_cid id; lbm_cid parent; + lbm_uint wait_mask; /* while reading */ lbm_int row0; lbm_int row1; @@ -75,7 +76,7 @@ typedef struct { lbm_event_type_t type; lbm_uint parameter; lbm_uint buf_ptr; - uint32_t buf_len; + lbm_uint buf_len; } lbm_event_t; /** Fundamental operation type */ @@ -142,6 +143,12 @@ bool lbm_event(lbm_flat_value_t *fv); * \return true on success. */ bool lbm_event_unboxed(lbm_value unboxed); + +/** Trigger a flag to wake up all tasks waiting on that flag. + * \param wait_for_flags Flags to trigger. + */ +void lbm_trigger_flags(uint32_t wait_for_flags); + /** Remove a context that has finished executing and free up its associated memory. * * \param cid Context id of context to free. diff --git a/include/heap.h b/include/heap.h index 251e0207..3d840876 100644 --- a/include/heap.h +++ b/include/heap.h @@ -334,7 +334,7 @@ lbm_value lbm_heap_allocate_cell(lbm_type type, lbm_value car, lbm_value cdr); * \param n The number of heap-cells to allocate. * \return A list of heap-cells of Memory error if unable to allocate. */ -lbm_value lbm_heap_allocate_list(unsigned int n); +lbm_value lbm_heap_allocate_list(lbm_uint n); /** Allocate a list of n heap-cells and initialize the values. * \pram ls The result list is passed through this ptr. * \param n The length of list to allocate. @@ -484,7 +484,7 @@ int lbm_set_car_and_cdr(lbm_value c, lbm_value car_val, lbm_value cdr_val); * \param c A list * \return The length of the list. Unless the value is a cyclic structure on the heap, this function will terminate. */ -unsigned int lbm_list_length(lbm_value c); +lbm_uint lbm_list_length(lbm_value c); /** Calculate the length of a proper list and evaluate a predicate for each element. * \warning This is a dangerous function that should be used carefully. Cyclic structures on the heap @@ -688,7 +688,7 @@ extern lbm_value lbm_enc_u32(uint32_t x); * \param x float value to encode. * \return result encoded value. */ -extern lbm_value lbm_enc_float(float x); +extern lbm_value lbm_enc_float(lbm_float x); /** Encode a 64 bit integer into an lbm_value. * \param x 64 bit integer to encode. diff --git a/include/lbm_defines.h b/include/lbm_defines.h index 7965b39b..92c13cf3 100644 --- a/include/lbm_defines.h +++ b/include/lbm_defines.h @@ -208,7 +208,8 @@ #define SYM_EXIT_ERROR 0x15C #define SYM_MAP 0x15D #define SYM_REVERSE 0x15E -#define APPLY_FUNS_END 0x15E +#define SYM_WAIT_FOR 0x15F +#define APPLY_FUNS_END 0x15F #define FUNDAMENTALS_START 0x20E #define SYM_ADD 0x20E @@ -385,6 +386,7 @@ #define ENC_SYM_EXIT_ERROR ENC_SYM(SYM_EXIT_ERROR) #define ENC_SYM_MAP ENC_SYM(SYM_MAP) #define ENC_SYM_REVERSE ENC_SYM(SYM_REVERSE) +#define ENC_SYM_WAIT_FOR ENC_SYM(SYM_WAIT_FOR) #define ENC_SYM_GET_ENV ENC_SYM(SYM_GET_ENV) #define ENC_SYM_SET_ENV ENC_SYM(SYM_SET_ENV) diff --git a/include/lbm_flat_value.h b/include/lbm_flat_value.h index d8fa3054..19733d78 100644 --- a/include/lbm_flat_value.h +++ b/include/lbm_flat_value.h @@ -24,8 +24,8 @@ typedef struct { uint8_t *buf; - size_t buf_size; - uint32_t buf_pos; + lbm_uint buf_size; + lbm_uint buf_pos; } lbm_flat_value_t; // Arity #define S_CONS 0x1 // 2 car, cdr diff --git a/include/lbm_version.h b/include/lbm_version.h index c9d2d606..489564f3 100644 --- a/include/lbm_version.h +++ b/include/lbm_version.h @@ -27,12 +27,17 @@ extern "C" { /** LBM major version */ #define LBM_MAJOR_VERSION 0 /** LBM minor version */ -#define LBM_MINOR_VERSION 13 +#define LBM_MINOR_VERSION 14 /** LBM patch revision */ #define LBM_PATCH_VERSION 0 /*! \page changelog Changelog +JUN 8 2023: Version 0.14.0 + - wait-for that blocks code unless a flag is set. + - Bug fix in undefine. + - Lots of cleaning and refactoring. + MAJ 5 2023: Version 0.13.0 - Changed behavior of closure application to zero args. Used to be equivalent to application to nil. diff --git a/repl/repl.c b/repl/repl.c index a4257ba1..906c24bb 100644 --- a/repl/repl.c +++ b/repl/repl.c @@ -260,7 +260,7 @@ bool dyn_load(const char *str, const char **code) { lbm_value ext_block(lbm_value *args, lbm_uint argn) { - printf("blocking CID: %d\n", lbm_get_current_cid()); + printf("blocking CID: %d\n", (int32_t)lbm_get_current_cid()); lbm_block_ctx_from_extension(); return lbm_enc_sym(SYM_TRUE); } @@ -342,33 +342,21 @@ lbm_value ext_unflatten(lbm_value *args, lbm_uint argn) { char output[128]; -static lbm_value ext_range(lbm_value *args, lbm_uint argn) { - if (argn != 2 || lbm_type_of(args[0]) != LBM_TYPE_I || lbm_type_of(args[1]) != LBM_TYPE_I) { - return lbm_enc_sym(SYM_EERROR); - } - - lbm_int start = lbm_dec_i(args[0]); - lbm_int end = lbm_dec_i(args[1]); - - if (start > end || (end - start) > 100) { - return lbm_enc_sym(SYM_EERROR); - } - - lbm_value res = lbm_enc_sym(SYM_NIL); - - for (lbm_int i = end;i >= start;i--) { - res = lbm_cons(lbm_enc_i(i), res); - } - - return res; -} - static bool test_destruct(lbm_uint value) { printf("destroying custom value\n"); free((lbm_uint*)value); return true; } +static lbm_value ext_trigger(lbm_value *args, lbm_uint argn) { + if (argn == 1 && lbm_is_number(args[0])) { + lbm_trigger_flags(lbm_dec_as_u32(args[0])); + return ENC_SYM_TRUE; + } else { + return ENC_SYM_EERROR; + } +} + static lbm_value ext_custom(lbm_value *args, lbm_uint argn) { lbm_uint *mem = (lbm_uint*)malloc(1000*sizeof(lbm_uint)); @@ -469,7 +457,7 @@ void lookup_local(eval_context_t *ctx, void *arg1, void *arg2) { if (lbm_env_lookup_b(&res, (lbm_value)arg1, ctx->curr_env)) { lbm_print_value(output, 1024, res); - printf("CTX %d: %s = %s\n", ctx->id, (char *)arg2, output); + printf("CTX %d: %s = %s\n", (int32_t)ctx->id, (char *)arg2, output); } else { printf("not found\n"); } @@ -596,6 +584,12 @@ int main(int argc, char **argv) { else printf("Error adding extension.\n"); + res = lbm_add_extension("trigger", ext_trigger); + if (res) + printf("Extension added.\n"); + else + printf("Error adding extension.\n"); + /* Start evaluator thread */ if (pthread_create(&lispbm_thd, NULL, eval_thd_wrapper, NULL)) { @@ -671,7 +665,7 @@ int main(int argc, char **argv) { sleep_callback(10); } - lbm_cid cid = lbm_load_and_eval_program_incremental(&string_tok); + (void)lbm_load_and_eval_program_incremental(&string_tok); lbm_continue_eval(); //printf("started ctx: %"PRI_UINT"\n", cid); @@ -854,7 +848,7 @@ int main(int argc, char **argv) { lbm_create_string_char_channel(&string_tok_state, &string_tok, str); - lbm_cid cid = lbm_load_and_eval_expression(&string_tok); + (void)lbm_load_and_eval_expression(&string_tok); lbm_continue_eval(); //printf("started ctx: %"PRI_UINT"\n", cid); diff --git a/src/env.c b/src/env.c index 85696e96..1897a141 100644 --- a/src/env.c +++ b/src/env.c @@ -22,7 +22,7 @@ #include "heap.h" #include "print.h" -lbm_value env_global; +static lbm_value env_global; int lbm_init_env(void) { env_global = ENC_SYM_NIL; diff --git a/src/eval_cps.c b/src/eval_cps.c index dd64860d..18fc4369 100644 --- a/src/eval_cps.c +++ b/src/eval_cps.c @@ -1,4 +1,4 @@ -/* + /* Copyright 2018, 2020, 2021, 2022, 2023 Joel Svensson svenssonjoel@yahoo.se This program is free software: you can redistribute it and/or modify @@ -134,8 +134,17 @@ const char* lbm_error_str_flash_full = "Flash memory is full"; /* continue executing statements below */ \ } +typedef struct { + eval_context_t *first; + eval_context_t *last; +} eval_context_queue_t; + + static int gc(void); void error_ctx(lbm_value); +static void enqueue_ctx(eval_context_queue_t *q, eval_context_t *ctx); + +// The currently executing context. eval_context_t *ctx_running = NULL; static volatile bool gc_requested = false; @@ -237,7 +246,7 @@ void lbm_set_event_handler_pid(lbm_cid pid) { lbm_event_handler_pid = pid; } -static bool event_internal(lbm_event_type_t event_type, lbm_uint parameter, lbm_uint buf_ptr, uint32_t buf_len) { +static bool event_internal(lbm_event_type_t event_type, lbm_uint parameter, lbm_uint buf_ptr, lbm_uint buf_len) { bool r = false; if (lbm_events) { mutex_lock(&lbm_events_mutex); @@ -307,17 +316,16 @@ static bool lbm_event_pop(lbm_event_t *event) { sleep duration possible is 2 * 100us = 200us. */ -static bool eval_running = false; -static volatile bool blocking_extension = false; -mutex_t blocking_extension_mutex; -bool blocking_extension_mutex_initialized = false; -static uint32_t is_atomic = 0; - -typedef struct { - eval_context_t *first; - eval_context_t *last; -} eval_context_queue_t; +static bool eval_running = false; +static volatile bool blocking_extension = false; +mutex_t blocking_extension_mutex; +bool blocking_extension_mutex_initialized = false; +static uint32_t is_atomic = 0; +static volatile uint32_t wait_for = 0; // wake-up mask +void lbm_trigger_flags(uint32_t wait_for_flags) { + wait_for |= wait_for_flags; +} /* Process queues */ static eval_context_queue_t blocked = {NULL, NULL}; @@ -354,27 +362,12 @@ eval_context_t *lbm_get_current_context(void) { /****************************************************/ /* Utilities used locally in this file */ -// cons and cons_with_gc could add head, tail to mark list by default. -// potential imrpovement in readability at some application points. - -static lbm_value cons(lbm_value head, lbm_value tail) { - lbm_value res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail); - if (lbm_is_symbol_merror(res)) { - gc(); - res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head,tail); - if (lbm_is_symbol_merror(res)) { - error_ctx(ENC_SYM_MERROR); - } - } - return res; -} - static lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember) { lbm_value res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail); if (lbm_is_symbol_merror(res)) { - lbm_gc_mark_phase(1, remember); + lbm_gc_mark_phase(3, head, tail,remember); gc(); - res = lbm_heap_allocate_cell(LBM_TYPE_CONS,head, tail); + res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail); if (lbm_is_symbol_merror(res)) { error_ctx(ENC_SYM_MERROR); } @@ -390,6 +383,16 @@ static lbm_uint *get_stack_ptr(eval_context_t *ctx, unsigned int n) { return &ctx->K.data[index]; } +// pop_stack_ptr is safe when no GC is performed and +// the values of the stack will be dropped. +static lbm_uint *pop_stack_ptr(eval_context_t *ctx, unsigned int n) { + if (n > ctx->K.sp) { + error_ctx(ENC_SYM_STACK_ERROR); + } + ctx->K.sp -= n; + return &ctx->K.data[ctx->K.sp]; +} + static lbm_uint *stack_reserve(eval_context_t *ctx, unsigned int n) { if (ctx->K.sp + n >= ctx->K.size) { error_ctx(ENC_SYM_STACK_ERROR); @@ -477,6 +480,78 @@ static void get_car_and_cdr(lbm_value a, lbm_value *a_car, lbm_value *a_cdr) { } } +/* car cdr caar cadr replacements that are evaluator safe. */ +static lbm_value get_car(lbm_value a) { + if (lbm_is_ptr(a)) { + lbm_cons_t *cell = lbm_ref_cell(a); + return cell->car; + } else if (lbm_is_symbol_nil(a)) { + return a; + } + error_ctx(ENC_SYM_TERROR); + return(ENC_SYM_TERROR); +} + +static lbm_value get_cdr(lbm_value a) { + if (lbm_is_ptr(a)) { + lbm_cons_t *cell = lbm_ref_cell(a); + return cell->cdr; + } else if (lbm_is_symbol_nil(a)) { + return a; + } + error_ctx(ENC_SYM_TERROR); + return(ENC_SYM_TERROR); +} + +static lbm_value get_caar(lbm_value a) { + if (lbm_is_ptr(a)) { + lbm_cons_t *cell = lbm_ref_cell(a); + lbm_value tmp = cell->car; + if (lbm_is_ptr(tmp)) { + return lbm_ref_cell(tmp)->car; + } else if (lbm_is_symbol_nil(tmp)) { + return tmp; + } + } else if (lbm_is_symbol_nil(a)) { + return a; + } + error_ctx(ENC_SYM_TERROR); + return(ENC_SYM_TERROR); +} + +static lbm_value get_cadr(lbm_value a) { + if (lbm_is_ptr(a)) { + lbm_cons_t *cell = lbm_ref_cell(a); + lbm_value tmp = cell->cdr; + if (lbm_is_ptr(tmp)) { + return lbm_ref_cell(tmp)->car; + } else if (lbm_is_symbol_nil(tmp)) { + return tmp; + } + } else if (lbm_is_symbol_nil(a)) { + return a; + } + error_ctx(ENC_SYM_TERROR); + return(ENC_SYM_TERROR); +} + +static lbm_value get_cddr(lbm_value a) { + if (lbm_is_ptr(a)) { + lbm_cons_t *cell = lbm_ref_cell(a); + lbm_value tmp = cell->cdr; + if (lbm_is_ptr(tmp)) { + return lbm_ref_cell(tmp)->cdr; + } else if (lbm_is_symbol_nil(tmp)) { + return tmp; + } + } else if (lbm_is_symbol_nil(a)) { + return a; + } + error_ctx(ENC_SYM_TERROR); + return(ENC_SYM_TERROR); +} + + static lbm_value allocate_closure(lbm_value params, lbm_value body, lbm_value env) { if (lbm_heap_num_free() < 4) { gc(); @@ -503,6 +578,43 @@ static lbm_value allocate_closure(lbm_value params, lbm_value body, lbm_value en return res; } +#define CLO_PARAMS 0 +#define CLO_BODY 1 +#define CLO_ENV 2 +// (closure params exp env) -> [params, exp, env]) +static void extract_closure(lbm_value closure, lbm_value *res) { + lbm_value curr = get_cdr(closure); + for (int i = 0; i < 3; i ++) { + get_car_and_cdr(curr,&res[i],&curr); + } +} + +static void call_fundamental(lbm_uint fundamental, lbm_value *args, lbm_uint arg_count, eval_context_t *ctx) { + lbm_value res; + res = fundamental_table[fundamental](args, arg_count, ctx); + if (lbm_is_error(res)) { + if (lbm_is_symbol_merror(res)) { + gc(); + res = fundamental_table[fundamental](args, arg_count, ctx); + } + if (lbm_is_error(res)) { + error_ctx(res); + } + } + lbm_stack_drop(&ctx->K, arg_count+1); + ctx->app_cont = true; + ctx->r = res; +} + +static void block_current_ctx(lbm_uint sleep_us, uint32_t wait_mask, bool do_cont) { + ctx_running->timestamp = timestamp_us_callback(); + ctx_running->sleep_us = sleep_us; + ctx_running->wait_mask = wait_mask; + ctx_running->app_cont = do_cont; + enqueue_ctx(&blocked, ctx_running); + ctx_running = NULL; +} + /****************************************************/ /* Error message creation */ @@ -1000,6 +1112,7 @@ static lbm_cid lbm_create_ctx_parent(lbm_value program, lbm_value env, lbm_uint ctx->id = cid; ctx->parent = parent; + ctx->wait_mask = 0; if (!lbm_push(&ctx->K, DONE)) { lbm_memory_free((lbm_uint*)ctx->mailbox); @@ -1039,7 +1152,7 @@ bool lbm_mailbox_change_size(eval_context_t *ctx, lbm_uint new_size) { } lbm_memory_free(ctx->mailbox); ctx->mailbox = mailbox; - ctx->mailbox_size = new_size; + ctx->mailbox_size = (uint32_t)new_size; return true; } @@ -1167,8 +1280,8 @@ static bool match(lbm_value p, lbm_value e, lbm_value *env, bool *gc) { lbm_value binding; if (lbm_is_match_binder(p)) { - lbm_value var = lbm_cadr(p); - lbm_value bindertype = lbm_car(p); + lbm_value var = get_cadr(p); + lbm_value bindertype = get_car(p); if (!lbm_is_symbol(var)) return false; @@ -1196,7 +1309,7 @@ static bool match(lbm_value p, lbm_value e, lbm_value *env, bool *gc) { /* Comma-qualification experiment. */ if (lbm_is_comma_qualified_symbol(p)) { - lbm_value sym = lbm_cadr(p); + lbm_value sym = get_cadr(p); lbm_value val = lbm_env_lookup(sym, *env); if (lbm_is_symbol(SYM_NOT_FOUND)) { return false; @@ -1214,7 +1327,8 @@ static bool match(lbm_value p, lbm_value e, lbm_value *env, bool *gc) { lbm_value headp, tailp; lbm_value heade, taile; get_car_and_cdr(p, &headp, &tailp); - get_car_and_cdr(e, &heade, &taile); + get_car_and_cdr(e, &heade, &taile); // Static analysis warns, but execution does not + // pass this point unless head and tail get initialized. if (!match(headp, heade, env, gc)) { return false; } @@ -1231,17 +1345,17 @@ static int find_match(lbm_value plist, lbm_value *earr, lbm_uint num, lbm_value for (int i = 0; i < (int)num; i ++ ) { lbm_value curr_e = earr[i]; while (lbm_is_cons(curr_p)) { - lbm_value me = lbm_car(curr_p); - if (match(lbm_car(me), curr_e, env, &gc)) { + lbm_value me = get_car(curr_p); + if (match(get_car(me), curr_e, env, &gc)) { if (gc) return FM_NEED_GC; - *e = lbm_cadr(me); + *e = get_cadr(me); - if (!lbm_is_symbol_nil(lbm_cadr(lbm_cdr(me)))) { + if (!lbm_is_symbol_nil(get_cadr(get_cdr(me)))) { return FM_PATTERN_ERROR; } return n; } - curr_p = lbm_cdr(curr_p); + curr_p = get_cdr(curr_p); } curr_p = plist; /* search all patterns against next exp */ n ++; @@ -1387,7 +1501,7 @@ static void eval_symbol(eval_context_t *ctx) { } static void eval_quote(eval_context_t *ctx) { - ctx->r = lbm_cadr(ctx->curr_exp); + ctx->r = get_cadr(ctx->curr_exp); ctx->app_cont = true; } @@ -1397,16 +1511,14 @@ static void eval_selfevaluating(eval_context_t *ctx) { } static void eval_progn(eval_context_t *ctx) { - lbm_value exps = lbm_cdr(ctx->curr_exp); - lbm_value env = ctx->curr_env; + lbm_value exps = get_cdr(ctx->curr_exp); if (lbm_is_cons(exps)) { lbm_uint *sptr = stack_reserve(ctx, 4); - sptr[0] = env; // env to restore between expressions in progn + sptr[0] = ctx->curr_env; // env to restore between expressions in progn sptr[1] = lbm_enc_u(0); // Has env been copied (needed for progn local bindings) sptr[3] = PROGN_REST; get_car_and_cdr(exps, &ctx->curr_exp, &sptr[2]); - ctx->curr_env = env; if (lbm_is_symbol(sptr[2])) /* The only symbol it can be is nil */ lbm_stack_drop(&ctx->K, 4); } else if (lbm_is_symbol_nil(exps)) { @@ -1438,13 +1550,13 @@ static void eval_callcc(eval_context_t *ctx) { error_ctx(ENC_SYM_MERROR); } } - lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(cont_array); + lbm_array_header_t *arr = (lbm_array_header_t*)get_car(cont_array); memcpy(arr->data, ctx->K.data, ctx->K.sp * sizeof(lbm_uint)); - lbm_value acont = cons_with_gc(ENC_SYM_CONT, cont_array, cont_array); + lbm_value acont = cons_with_gc(ENC_SYM_CONT, cont_array, ENC_SYM_NIL); /* Create an application */ - lbm_value fun_arg = lbm_cadr(ctx->curr_exp); + lbm_value fun_arg = get_cadr(ctx->curr_exp); lbm_value app = ENC_SYM_NIL; WITH_GC_RMBR(app, lbm_heap_allocate_list_init(2, fun_arg, @@ -1456,7 +1568,7 @@ static void eval_callcc(eval_context_t *ctx) { // (define sym exp) static void eval_define(eval_context_t *ctx) { - lbm_value args = lbm_cdr(ctx->curr_exp); + lbm_value args = get_cdr(ctx->curr_exp); lbm_value key, rest_args; get_car_and_cdr(args, &key, &rest_args); lbm_value val_exp, rest_val; @@ -1487,18 +1599,18 @@ static void eval_define(eval_context_t *ctx) { // (lambda param-list body-exp) -> (closure param-list body-exp env) static void eval_lambda(eval_context_t *ctx) { - lbm_value cdr = lbm_cdr(ctx->curr_exp); - ctx->r = allocate_closure(lbm_car(cdr), lbm_cadr(cdr), ctx->curr_env); + lbm_value cdr = get_cdr(ctx->curr_exp); + ctx->r = allocate_closure(get_car(cdr), get_cadr(cdr), ctx->curr_env); ctx->app_cont = true; } static void eval_if(eval_context_t *ctx) { - lbm_value cdr = lbm_cdr(ctx->curr_exp); + lbm_value cdr = get_cdr(ctx->curr_exp); lbm_value exp, cddr; get_car_and_cdr(cdr, &exp, &cddr); - lbm_value then_branch = lbm_car(cddr); - lbm_value else_branch = lbm_cadr(cddr); + lbm_value then_branch = get_car(cddr); + lbm_value else_branch = get_cadr(cddr); lbm_uint *sptr = stack_reserve(ctx, 4); sptr[0] = else_branch; @@ -1509,21 +1621,21 @@ static void eval_if(eval_context_t *ctx) { } static void eval_cond(eval_context_t *ctx) { - lbm_value cond1 = lbm_cadr(ctx->curr_exp); + lbm_value cond1 = get_cadr(ctx->curr_exp); if (lbm_is_symbol_nil(cond1)) { ctx->r = ENC_SYM_NIL; ctx->app_cont = true; } else { - uint32_t len = lbm_list_length(cond1); + lbm_uint len = lbm_list_length(cond1); if (len != 2) { lbm_set_error_reason("Incorrect syntax in cond"); error_ctx(ENC_SYM_EERROR); } - lbm_value condition = lbm_car(cond1); - lbm_value body = lbm_cadr(cond1); + lbm_value condition = get_car(cond1); + lbm_value body = get_cadr(cond1); lbm_value rest; - rest = cons(ENC_SYM_COND, lbm_cddr(ctx->curr_exp)); + rest = cons_with_gc(ENC_SYM_COND, get_cddr(ctx->curr_exp), ENC_SYM_NIL); lbm_uint *sptr = stack_reserve(ctx, 4); sptr[0] = rest; sptr[1] = body; @@ -1540,24 +1652,24 @@ static void eval_app_cont(eval_context_t *ctx) { // (var x (...)) - local binding inside of an progn static void eval_var(eval_context_t *ctx) { - lbm_value args = lbm_cdr(ctx->curr_exp); - lbm_value sym = lbm_car(args); - lbm_value v_exp = lbm_cadr(args); + lbm_value args = get_cdr(ctx->curr_exp); + lbm_value sym = get_car(args); + lbm_value v_exp = get_cadr(args); stack_push_2(&ctx->K, sym, PROGN_VAR); ctx->curr_exp = v_exp; } // (setq x (...)) - same as (set 'x (...)) or (setvar 'x (...)) static void eval_setq(eval_context_t *ctx) { - lbm_value args = lbm_cdr(ctx->curr_exp); - lbm_value sym = lbm_car(args); - lbm_value v_exp = lbm_cadr(args); + lbm_value args = get_cdr(ctx->curr_exp); + lbm_value sym = get_car(args); + lbm_value v_exp = get_cadr(args); stack_push_2(&ctx->K, sym, SETQ); ctx->curr_exp = v_exp; } static void eval_move_to_flash(eval_context_t *ctx) { - lbm_value args = lbm_cdr(ctx->curr_exp); + lbm_value args = get_cdr(ctx->curr_exp); stack_push_2(&ctx->K, args, MOVE_TO_FLASH); ctx->app_cont = true; } @@ -1580,9 +1692,9 @@ static int create_binding_location(lbm_value key, lbm_value *env) { } *env = new_env_tmp; } else if (lbm_is_cons(key)) { // deconstruct case - int r = create_binding_location(lbm_car(key), env); + int r = create_binding_location(get_car(key), env); if (r == BL_OK) { - r = create_binding_location(lbm_cdr(key), env); + r = create_binding_location(get_cdr(key), env); } return r; } @@ -1591,8 +1703,8 @@ static int create_binding_location(lbm_value key, lbm_value *env) { static void eval_let(eval_context_t *ctx) { lbm_value orig_env = ctx->curr_env; - lbm_value binds = lbm_cadr(ctx->curr_exp); // key value pairs. - lbm_value exp = lbm_cadr(lbm_cdr(ctx->curr_exp)); // exp to evaluate in the new env. + lbm_value binds = get_cadr(ctx->curr_exp); // key value pairs. + lbm_value exp = get_cadr(get_cdr(ctx->curr_exp)); // exp to evaluate in the new env. lbm_value curr = binds; lbm_value new_env = orig_env; @@ -1606,7 +1718,7 @@ static void eval_let(eval_context_t *ctx) { // Implements letrec by "preallocating" the key parts while (lbm_is_cons(curr)) { lbm_value new_env_tmp = new_env; - lbm_value key = lbm_caar(curr); + lbm_value key = get_caar(curr); int r = create_binding_location(key, &new_env_tmp); if (r < 0) { if (r == BL_NO_MEMORY) { @@ -1626,15 +1738,15 @@ static void eval_let(eval_context_t *ctx) { } } new_env = new_env_tmp; - curr = lbm_cdr(curr); + curr = get_cdr(curr); } - lbm_value key0 = lbm_caar(binds); - lbm_value val0_exp = lbm_cadr(lbm_car(binds)); + lbm_value key0 = get_caar(binds); + lbm_value val0_exp = get_cadr(get_car(binds)); lbm_uint *sptr = stack_reserve(ctx, 5); sptr[0] = exp; - sptr[1] = lbm_cdr(binds); + sptr[1] = get_cdr(binds); sptr[2] = new_env; sptr[3] = key0; sptr[4] = BIND_TO_KEY_REST; @@ -1644,24 +1756,24 @@ static void eval_let(eval_context_t *ctx) { } static void eval_and(eval_context_t *ctx) { - lbm_value rest = lbm_cdr(ctx->curr_exp); + lbm_value rest = get_cdr(ctx->curr_exp); if (lbm_is_symbol_nil(rest)) { ctx->app_cont = true; ctx->r = ENC_SYM_TRUE; } else { - stack_push_2(&ctx->K, lbm_cdr(rest), AND); - ctx->curr_exp = lbm_car(rest); + stack_push_2(&ctx->K, get_cdr(rest), AND); + ctx->curr_exp = get_car(rest); } } static void eval_or(eval_context_t *ctx) { - lbm_value rest = lbm_cdr(ctx->curr_exp); + lbm_value rest = get_cdr(ctx->curr_exp); if (lbm_is_symbol_nil(rest)) { ctx->app_cont = true; ctx->r = ENC_SYM_NIL; } else { - stack_push_2(&ctx->K, lbm_cdr(rest), OR); - ctx->curr_exp = lbm_car(rest); + stack_push_2(&ctx->K, get_cdr(rest), OR); + ctx->curr_exp = get_car(rest); } } @@ -1672,7 +1784,7 @@ static void eval_or(eval_context_t *ctx) { /* ... ) */ static void eval_match(eval_context_t *ctx) { - lbm_value rest = lbm_cdr(ctx->curr_exp); + lbm_value rest = get_cdr(ctx->curr_exp); if (lbm_type_of(rest) == LBM_TYPE_SYMBOL && rest == ENC_SYM_NIL) { /* Someone wrote the program (match) */ @@ -1693,10 +1805,7 @@ static void eval_receive(eval_context_t *ctx) { } if (ctx->num_mail == 0) { - ctx->timestamp = timestamp_us_callback(); - ctx->sleep_us = 0; - enqueue_ctx(&blocked,ctx); - ctx_running = NULL; + block_current_ctx(0,0,false); } else { lbm_value pats = ctx->curr_exp; lbm_value *msgs = ctx->mailbox; @@ -1710,11 +1819,11 @@ static void eval_receive(eval_context_t *ctx) { /* The common case */ lbm_value e; lbm_value new_env = ctx->curr_env; - int n = find_match(lbm_cdr(pats), msgs, num, &e, &new_env); + int n = find_match(get_cdr(pats), msgs, num, &e, &new_env); if (n == FM_NEED_GC) { gc(); new_env = ctx->curr_env; - n = find_match(lbm_cdr(pats), msgs, num, &e, &new_env); + n = find_match(get_cdr(pats), msgs, num, &e, &new_env); if (n == FM_NEED_GC) { error_ctx(ENC_SYM_MERROR); } @@ -1727,11 +1836,8 @@ static void eval_receive(eval_context_t *ctx) { ctx->curr_env = new_env; ctx->curr_exp = e; } else { /* No match go back to sleep */ - ctx->timestamp = timestamp_us_callback(); - ctx->sleep_us = 0; - enqueue_ctx(&blocked,ctx); - ctx_running = NULL; ctx->r = ENC_SYM_NO_MATCH; + block_current_ctx(0,0, false); } } } @@ -1785,20 +1891,17 @@ static void cont_progn_rest(eval_context_t *ctx) { rest = sptr[2]; env = sptr[0]; - if (lbm_is_symbol_nil(rest)) { - lbm_stack_drop(&ctx->K, 2); - ctx->app_cont = true; - return; - } - // allow for tail recursion - if (lbm_is_symbol_nil(lbm_cdr(rest))) { - ctx->curr_exp = lbm_car(rest); + lbm_value rest_car, rest_cdr; + get_car_and_cdr(rest, &rest_car, &rest_cdr); + if (lbm_is_symbol_nil(rest_cdr)) { + // allow for tail recursion + ctx->curr_exp = rest_car; ctx->curr_env = env; lbm_stack_drop(&ctx->K, 3); } else { - sptr[2] = lbm_cdr(rest); + sptr[2] = rest_cdr; stack_push(&ctx->K, PROGN_REST); - ctx->curr_exp = lbm_car(rest); + ctx->curr_exp = rest_car; ctx->curr_env = env; } } @@ -1931,30 +2034,22 @@ static void apply_spawn_base(lbm_value *args, lbm_uint nargs, eval_context_t *ct error_ctx(ENC_SYM_EERROR); } - lbm_value cdr_fun = lbm_cdr(args[closure_pos]); - lbm_value cddr_fun = lbm_cdr(cdr_fun); - lbm_value cdddr_fun = lbm_cdr(cddr_fun); - lbm_value params = lbm_car(cdr_fun); - lbm_value exp = lbm_car(cddr_fun); - lbm_value clo_env = lbm_car(cdddr_fun); - - lbm_value curr_param = params; + lbm_value cl[3]; + extract_closure(args[closure_pos], cl); + lbm_value curr_param = cl[CLO_PARAMS]; + lbm_value clo_env = cl[CLO_ENV]; lbm_uint i = closure_pos + 1; - while (lbm_is_cons(curr_param) && - i <= nargs) { - - lbm_value entry = cons_with_gc(lbm_car(curr_param), args[i], clo_env); - - lbm_value aug_env; - WITH_GC_RMBR(aug_env,lbm_cons(entry, clo_env),2, clo_env,entry); + while (lbm_is_cons(curr_param) && i <= nargs) { + lbm_value entry = cons_with_gc(get_car(curr_param), args[i], clo_env); + lbm_value aug_env = cons_with_gc(entry, clo_env,ENC_SYM_NIL); clo_env = aug_env; - curr_param = lbm_cdr(curr_param); + curr_param = get_cdr(curr_param); i ++; } lbm_stack_drop(&ctx->K, nargs+1); - lbm_value program = cons_with_gc(exp, ENC_SYM_NIL, clo_env); + lbm_value program = cons_with_gc(cl[CLO_BODY], ENC_SYM_NIL, clo_env); lbm_cid cid = lbm_create_ctx_parent(program, clo_env, @@ -1988,7 +2083,7 @@ static void apply_yield(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { } static void apply_wait(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { - if (lbm_type_of(args[0]) == LBM_TYPE_I) { + if (nargs == 1 && lbm_type_of(args[0]) == LBM_TYPE_I) { lbm_cid cid = (lbm_cid)lbm_dec_i(args[0]); lbm_stack_drop(&ctx->K, nargs+1); stack_push_2(&ctx->K, lbm_enc_i(cid), WAIT); @@ -2000,6 +2095,21 @@ static void apply_wait(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { } } +static void apply_wait_for(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { + if (nargs == 1 && lbm_is_number(args[0])) { + uint32_t w = lbm_dec_as_u32(args[0]); + lbm_stack_drop(&ctx->K, nargs+1); + if (w != 0) { + block_current_ctx(0, w, true); + } else { + ctx->r = ENC_SYM_NIL; + ctx->app_cont = true; + } + } else { + error_ctx(ENC_SYM_EERROR); + } +} + static void apply_eval(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { if ( nargs == 1) { ctx->curr_exp = args[0]; @@ -2023,7 +2133,7 @@ static void apply_eval_program(lbm_value *args, lbm_uint nargs, eval_context_t * if (ctx->K.sp > nargs+2) { // if there is a continuation app_cont = cons_with_gc(ENC_SYM_APP_CONT, ENC_SYM_NIL, prg_copy); - WITH_GC_RMBR(app_cont_prg, lbm_cons(app_cont, ENC_SYM_NIL), 2, app_cont, prg_copy); + app_cont_prg = cons_with_gc(app_cont, ENC_SYM_NIL, prg_copy); new_prg = lbm_list_append(app_cont_prg, ctx->program); new_prg = lbm_list_append(prg_copy, new_prg); } else { @@ -2033,8 +2143,8 @@ static void apply_eval_program(lbm_value *args, lbm_uint nargs, eval_context_t * error_ctx(ENC_SYM_EERROR); } stack_push(&ctx->K, DONE); - ctx->program = lbm_cdr(new_prg); - ctx->curr_exp = lbm_car(new_prg); + ctx->program = get_cdr(new_prg); + ctx->curr_exp = get_car(new_prg); } else { lbm_set_error_reason((char*)lbm_error_str_num_args); error_ctx(ENC_SYM_EERROR); @@ -2043,17 +2153,17 @@ static void apply_eval_program(lbm_value *args, lbm_uint nargs, eval_context_t * static void apply_send(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { if (nargs == 2) { - lbm_value status = ENC_SYM_TERROR; if (lbm_type_of(args[0]) == LBM_TYPE_I) { lbm_cid cid = (lbm_cid)lbm_dec_i(args[0]); lbm_value msg = args[1]; - - WITH_GC(status, lbm_find_receiver_and_send(cid, msg)); + lbm_value status = lbm_find_receiver_and_send(cid, msg); + /* return the status */ + lbm_stack_drop(&ctx->K, nargs+1); + ctx->r = status; + ctx->app_cont = true; + } else { + error_ctx(ENC_SYM_TERROR); } - /* return the status */ - lbm_stack_drop(&ctx->K, nargs+1); - ctx->r = status; - ctx->app_cont = true; } else { lbm_set_error_reason((char*)lbm_error_str_num_args); error_ctx(ENC_SYM_EERROR); @@ -2089,20 +2199,20 @@ static void apply_map(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { lbm_value *sptr = get_stack_ptr(ctx, 3); lbm_value f = args[0]; - lbm_value h = lbm_car(args[1]); - lbm_value t = lbm_cdr(args[1]); + lbm_value h = get_car(args[1]); + lbm_value t = get_cdr(args[1]); lbm_value appli_1; lbm_value appli; WITH_GC(appli_1, lbm_heap_allocate_list(2)); WITH_GC(appli, lbm_heap_allocate_list(2)); - lbm_value appli_0 = lbm_cdr(appli_1); + lbm_value appli_0 = get_cdr(appli_1); lbm_set_car_and_cdr(appli_0, h, ENC_SYM_NIL); lbm_set_car(appli_1, ENC_SYM_QUOTE); - lbm_set_car_and_cdr(lbm_cdr(appli), appli_1, ENC_SYM_NIL); + lbm_set_car_and_cdr(get_cdr(appli), appli_1, ENC_SYM_NIL); lbm_set_car(appli, f); stack_push_4(&ctx->K, ENC_SYM_NIL, appli, appli_0, MAP_FIRST); @@ -2116,7 +2226,7 @@ static void apply_map(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { if (lbm_str_to_symbol("x", &sym)) { lbm_value *sptr = get_stack_ptr(ctx, 2); // Store params and body on stack temporarily to keep them safe from gc. - sptr[0] = cons(lbm_enc_sym(sym), ENC_SYM_NIL); + sptr[0] = cons_with_gc(lbm_enc_sym(sym), ENC_SYM_NIL,ENC_SYM_NIL); WITH_GC(sptr[1], lbm_heap_allocate_list_init(3, ENC_SYM_MAP, args[0], @@ -2139,9 +2249,9 @@ static void apply_reverse(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) lbm_value new_list = ENC_SYM_NIL; while (lbm_is_cons(curr)) { - lbm_value tmp = cons_with_gc(lbm_car(curr), new_list, new_list); + lbm_value tmp = cons_with_gc(get_car(curr), new_list, ENC_SYM_NIL); new_list = tmp; - curr = lbm_cdr(curr); + curr = get_cdr(curr); } lbm_stack_drop(&ctx->K, 2); ctx->r = new_list; @@ -2173,6 +2283,7 @@ static const apply_fun fun_table[] = apply_error, apply_map, apply_reverse, + apply_wait_for, }; /***************************************************/ @@ -2193,14 +2304,7 @@ static void application(eval_context_t *ctx, lbm_value *fun_args, lbm_uint arg_c 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); - } - lbm_stack_drop(&ctx->K, arg_count+1); - ctx->app_cont = true; - ctx->r = res; + call_fundamental(fund_val, &fun_args[1], arg_count, ctx); } else { // It may be an extension extension_fptr f = lbm_get_extension(fun_val); @@ -2217,11 +2321,7 @@ static void application(eval_context_t *ctx, lbm_value *fun_args, lbm_uint arg_c if (blocking_extension) { blocking_extension = false; - ctx->timestamp = timestamp_us_callback(); - ctx->sleep_us = 0; - ctx->app_cont = true; - enqueue_ctx(&blocked,ctx); - ctx_running = NULL; + block_current_ctx(0,0,true); mutex_unlock(&blocking_extension_mutex); } else { ctx->app_cont = true; @@ -2245,7 +2345,7 @@ static void cont_closure_application_args(eval_context_t *ctx) { lbm_value ls; WITH_GC(ls, lbm_heap_allocate_list(2)); lbm_value entry = ls; - lbm_value aug_env = lbm_cdr(ls); + lbm_value aug_env = get_cdr(ls); lbm_cons_t *c1 = lbm_ref_cell(entry); c1->car = car_params; c1->cdr = ctx->r; @@ -2298,19 +2398,18 @@ static void cont_application_args(eval_context_t *ctx) { ctx->curr_env = env; sptr[0] = arg; - if (lbm_is_symbol_nil(rest)) { + if (lbm_is_cons(rest)) { + lbm_cons_t *cell = lbm_ref_cell(rest); + sptr[1] = env; + sptr[2] = cell->cdr; + stack_push_2(&ctx->K, count + (1 << LBM_VAL_SHIFT), APPLICATION_ARGS); + ctx->curr_exp = cell->car; + } else { // No more arguments lbm_stack_drop(&ctx->K, 2); lbm_uint nargs = lbm_dec_u(count); - lbm_value *args = get_stack_ptr(ctx, nargs + 1); + lbm_value *args = get_stack_ptr(ctx, (uint32_t)(nargs + 1)); application(ctx,args, nargs); - } else { - lbm_value car_rest, cdr_rest; - get_car_and_cdr(rest, &car_rest, &cdr_rest); - sptr[1] = env; - sptr[2] = cdr_rest; - stack_push_2(&ctx->K, count + (1 << LBM_VAL_SHIFT), APPLICATION_ARGS); - ctx->curr_exp = car_rest; } } @@ -2324,8 +2423,8 @@ static void cont_and(eval_context_t *ctx) { } else if (lbm_is_symbol_nil(rest)) { ctx->app_cont = true; } else { - stack_push_2(&ctx->K, lbm_cdr(rest), AND); - ctx->curr_exp = lbm_car(rest); + stack_push_2(&ctx->K, get_cdr(rest), AND); + ctx->curr_exp = get_car(rest); } } @@ -2339,8 +2438,8 @@ static void cont_or(eval_context_t *ctx) { ctx->app_cont = true; ctx->r = ENC_SYM_NIL; } else { - stack_push_2(&ctx->K, lbm_cdr(rest), OR); - ctx->curr_exp = lbm_car(rest); + stack_push_2(&ctx->K, get_cdr(rest), OR); + ctx->curr_exp = get_car(rest); } } @@ -2351,9 +2450,9 @@ static int fill_binding_location(lbm_value key, lbm_value value, lbm_value env) return FB_OK; } else if (lbm_is_cons(key) && lbm_is_cons(value)) { - int r = fill_binding_location(lbm_car(key), lbm_car(value), env); + int r = fill_binding_location(get_car(key), get_car(value), env); if (r == FB_OK) { - r = fill_binding_location(lbm_cdr(key), lbm_cdr(value), env); + r = fill_binding_location(get_cdr(key), get_cdr(value), env); } return r; } @@ -2374,10 +2473,10 @@ static void cont_bind_to_key_rest(eval_context_t *ctx) { } if (lbm_is_cons(rest)) { - lbm_value keyn = lbm_caar(rest); - lbm_value valn_exp = lbm_cadr(lbm_car(rest)); + lbm_value keyn = get_caar(rest); + lbm_value valn_exp = get_cadr(get_car(rest)); - sptr[1] = lbm_cdr(rest); + sptr[1] = get_cdr(rest); sptr[3] = keyn; stack_push(&ctx->K, BIND_TO_KEY_REST); ctx->curr_exp = valn_exp; @@ -2394,7 +2493,7 @@ static void cont_if(eval_context_t *ctx) { lbm_value arg = ctx->r; - lbm_value *sptr = get_stack_ptr(ctx, 3); + lbm_value *sptr = pop_stack_ptr(ctx, 3); ctx->curr_env = sptr[2]; if (lbm_is_symbol_nil(arg)) { @@ -2402,7 +2501,6 @@ static void cont_if(eval_context_t *ctx) { } else { ctx->curr_exp = sptr[1]; // then branch } - lbm_stack_drop(&ctx->K, 3); } static void cont_match_many(eval_context_t *ctx) { @@ -2429,7 +2527,7 @@ static void cont_match_many(eval_context_t *ctx) { lbm_uint *sptr = stack_reserve(ctx, 3); old_stack[2] = cdr_rest_msgs; sptr[0] = MATCH_MANY; - sptr[1] = lbm_cdr(pats); + sptr[1] = get_cdr(pats); sptr[2] = MATCH; ctx->r = car_rest_msgs; ctx->app_cont = true; @@ -2455,10 +2553,10 @@ static void cont_match(eval_context_t *ctx) { ctx->r = ENC_SYM_NO_MATCH; ctx->app_cont = true; } else if (lbm_is_cons(patterns)) { - lbm_value match_case = lbm_car(patterns); - lbm_value pattern = lbm_car(match_case); - lbm_value n1 = lbm_cadr(match_case); - lbm_value n2 = lbm_cadr(lbm_cdr(match_case)); + lbm_value match_case = get_car(patterns); + lbm_value pattern = get_car(match_case); + lbm_value n1 = get_cadr(match_case); + lbm_value n2 = get_cadr(get_cdr(match_case)); lbm_value body; bool check_guard = false; if (lbm_is_symbol_nil(n2)) { // TODO: Not a very robust check. @@ -2481,7 +2579,7 @@ static void cont_match(eval_context_t *ctx) { if (is_match) { if (check_guard) { lbm_value *sptr = stack_reserve(ctx,7); - sptr[0] = lbm_cdr(patterns); + sptr[0] = get_cdr(patterns); sptr[1] = ctx->curr_env; sptr[2] = MATCH; sptr[3] = new_env; @@ -2496,7 +2594,7 @@ static void cont_match(eval_context_t *ctx) { } } else { /* set up for checking of next pattern */ - stack_push_3(&ctx->K, lbm_cdr(patterns),ctx->curr_env, MATCH); + stack_push_3(&ctx->K, get_cdr(patterns),ctx->curr_env, MATCH); /* leave r unaltered */ ctx->app_cont = true; } @@ -2517,7 +2615,7 @@ static void cont_map_first(eval_context_t *ctx) { lbm_value ls = sptr[0]; lbm_value env = sptr[1]; - lbm_value elt = cons(ctx->r, ENC_SYM_NIL); + lbm_value elt = cons_with_gc(ctx->r, ENC_SYM_NIL,ENC_SYM_NIL); sptr[2] = elt; // head of result list sptr[3] = elt; // tail of result list if (lbm_is_cons(ls)) { @@ -2543,7 +2641,7 @@ static void cont_map_rest(eval_context_t *ctx) { lbm_value env = sptr[1]; lbm_value t = sptr[3]; - lbm_value elt = cons(ctx->r, ENC_SYM_NIL); + lbm_value elt = cons_with_gc(ctx->r, ENC_SYM_NIL, ENC_SYM_NIL); lbm_set_cdr(t, elt); sptr[3] = elt; // update tail of result list. if (lbm_is_cons(ls)) { @@ -2763,7 +2861,7 @@ static void cont_read_next_token(eval_context_t *ctx) { error_ctx(ENC_SYM_MERROR); } } - lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(res); + lbm_array_header_t *arr = (lbm_array_header_t*)get_car(res); char *data = (char*)arr->data; memset(data,0, string_len + 1); memcpy(data, tokpar_sym_str, string_len); @@ -2812,10 +2910,10 @@ static void cont_read_next_token(eval_context_t *ctx) { res = lbm_enc_u((lbm_uint)(int_result.negative ? -int_result.value : int_result.value)); break; case TOKTYPEI32: - WITH_GC(res, lbm_enc_i32((lbm_int)(int_result.negative ? -int_result.value : int_result.value))); + WITH_GC(res, lbm_enc_i32((int32_t)(int_result.negative ? -int_result.value : int_result.value))); break; case TOKTYPEU32: - WITH_GC(res,lbm_enc_u32((lbm_uint)(int_result.negative ? -int_result.value : int_result.value))); + WITH_GC(res,lbm_enc_u32((uint32_t)(int_result.negative ? -int_result.value : int_result.value))); break; case TOKTYPEI64: WITH_GC(res,lbm_enc_i64((int64_t)(int_result.negative ? -int_result.value : int_result.value))); @@ -2940,7 +3038,7 @@ static void cont_read_append_array(eval_context_t *ctx) { error_ctx(ENC_SYM_MERROR); } - lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(array); // TODO: Check + lbm_array_header_t *arr = (lbm_array_header_t*)get_car(array); // TODO: Check if (lbm_is_number(ctx->r)) { ((uint8_t*)arr->data)[ix] = (uint8_t)lbm_dec_as_u32(ctx->r); @@ -2998,7 +3096,7 @@ static void cont_read_append_continue(eval_context_t *ctx) { return; } } - lbm_value new_cell = cons(ctx->r, ENC_SYM_NIL); + lbm_value new_cell = cons_with_gc(ctx->r, ENC_SYM_NIL, ENC_SYM_NIL); if (lbm_is_symbol_merror(new_cell)) { lbm_channel_reader_close(str); return; @@ -3160,15 +3258,15 @@ static void cont_read_backquote_result(eval_context_t *ctx) { } static void cont_read_commaat_result(eval_context_t *ctx) { - lbm_value cell2 = cons(ctx->r,ENC_SYM_NIL); - lbm_value cell1 = cons_with_gc(ENC_SYM_COMMAAT, cell2, cell2); + lbm_value cell2 = cons_with_gc(ctx->r,ENC_SYM_NIL, ENC_SYM_NIL); + lbm_value cell1 = cons_with_gc(ENC_SYM_COMMAAT, cell2, ENC_SYM_NIL); ctx->r = cell1; ctx->app_cont = true; } static void cont_read_comma_result(eval_context_t *ctx) { - lbm_value cell2 = cons(ctx->r,ENC_SYM_NIL); - lbm_value cell1 = cons_with_gc(ENC_SYM_COMMA, cell2, cell2); + lbm_value cell2 = cons_with_gc(ctx->r,ENC_SYM_NIL,ENC_SYM_NIL); + lbm_value cell1 = cons_with_gc(ENC_SYM_COMMA, cell2, ENC_SYM_NIL); ctx->r = cell1; ctx->app_cont = true; } @@ -3186,23 +3284,19 @@ static void cont_application_start(eval_context_t *ctx) { } else if (lbm_is_cons(ctx->r)) { lbm_uint *sptr = get_stack_ptr(ctx, 2); lbm_value args = (lbm_value)sptr[1]; - switch (lbm_car(ctx->r)) { + switch (get_car(ctx->r)) { case ENC_SYM_CLOSURE: { - lbm_value cdr_fun = lbm_cdr(ctx->r); - lbm_value params, cddr_fun; - get_car_and_cdr(cdr_fun, ¶ms, &cddr_fun); - lbm_value exp, cdddr_fun = lbm_cdr(cddr_fun); - get_car_and_cdr(cddr_fun, &exp, &cdddr_fun); - lbm_value clo_env = lbm_car(cdddr_fun); + lbm_value cl[3]; + extract_closure(ctx->r, cl); lbm_value arg_env = (lbm_value)sptr[0]; lbm_value arg0, arg_rest; get_car_and_cdr(args, &arg0, &arg_rest); - sptr[1] = exp; + sptr[1] = cl[CLO_BODY]; if (lbm_is_symbol_nil(args)) { - if (lbm_is_symbol_nil(params)) { + if (lbm_is_symbol_nil(cl[CLO_PARAMS])) { // No param closure - ctx->curr_exp = exp; - ctx->curr_env = clo_env; // empty + ctx->curr_exp = cl[CLO_BODY]; + ctx->curr_env = cl[CLO_ENV]; ctx->app_cont = false; } else { ctx->app_cont = true; @@ -3210,8 +3304,8 @@ static void cont_application_start(eval_context_t *ctx) { lbm_stack_drop(&ctx->K, 2); } else { lbm_value *reserved = stack_reserve(ctx, 4); - reserved[0] = clo_env; - reserved[1] = params; + reserved[0] = cl[CLO_ENV]; + reserved[1] = cl[CLO_PARAMS]; reserved[2] = arg_rest; reserved[3] = CLOSURE_ARGS; ctx->curr_exp = arg0; @@ -3223,7 +3317,7 @@ static void cont_application_start(eval_context_t *ctx) { /* Continuation created using call-cc. * ((SYM_CONT . cont-array) arg0 ) */ - lbm_value c = lbm_cdr(ctx->r); /* should be the continuation array*/ + lbm_value c = get_cdr(ctx->r); /* should be the continuation array*/ if (!lbm_is_array_r(c)) { error_ctx(ENC_SYM_FATAL_ERROR); @@ -3236,7 +3330,7 @@ static void cont_application_start(eval_context_t *ctx) { arg = ENC_SYM_NIL; break; case 1: - arg = lbm_car(args); + arg = get_car(args); break; default: lbm_set_error_reason((char*)lbm_error_str_num_args); @@ -3244,7 +3338,7 @@ static void cont_application_start(eval_context_t *ctx) { } lbm_stack_clear(&ctx->K); - lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(c); + lbm_array_header_t *arr = (lbm_array_header_t*)get_car(c); ctx->K.sp = arr->size / sizeof(lbm_uint); memcpy(ctx->K.data, arr->data, arr->size); @@ -3262,7 +3356,7 @@ static void cont_application_start(eval_context_t *ctx) { */ lbm_value env = (lbm_value)sptr[0]; - lbm_value curr_param = lbm_cadr(ctx->r); + lbm_value curr_param = get_cadr(ctx->r); lbm_value curr_arg = args; lbm_value expand_env = env; while (lbm_is_cons(curr_param) && @@ -3273,9 +3367,7 @@ static void cont_application_start(eval_context_t *ctx) { get_car_and_cdr(curr_arg, &car_curr_arg, &cdr_curr_arg); lbm_value entry = cons_with_gc(car_curr_param, car_curr_arg, expand_env); - - lbm_value aug_env; - WITH_GC_RMBR(aug_env,lbm_cons(entry, expand_env), 2, expand_env, entry); + lbm_value aug_env = cons_with_gc(entry, expand_env,ENC_SYM_NIL); expand_env = aug_env; curr_param = cdr_curr_param; @@ -3286,7 +3378,7 @@ static void cont_application_start(eval_context_t *ctx) { * Second to evaluate the resulting program. */ sptr[1] = EVAL_R; - lbm_value exp = lbm_cadr(lbm_cdr(ctx->r)); + lbm_value exp = get_cadr(get_cdr(ctx->r)); ctx->curr_exp = exp; ctx->curr_env = expand_env; @@ -3399,9 +3491,9 @@ static void cont_move_val_to_flash_dispatch(eval_context_t *ctx) { if (lbm_is_cons(val)) { lbm_value flash_cell = ENC_SYM_NIL; handle_flash_status(request_flash_storage_cell(val, &flash_cell)); - stack_push_4(&ctx->K, flash_cell, flash_cell, lbm_cdr(val), MOVE_LIST_TO_FLASH); + stack_push_4(&ctx->K, flash_cell, flash_cell, get_cdr(val), MOVE_LIST_TO_FLASH); stack_push(&ctx->K, MOVE_VAL_TO_FLASH_DISPATCH); - ctx->r = lbm_car(val); + ctx->r = get_car(val); ctx->app_cont = true; return; } @@ -3491,10 +3583,10 @@ static void cont_move_list_to_flash(eval_context_t *ctx) { handle_flash_status(request_flash_storage_cell(val, &rest_cell)); handle_flash_status(write_const_cdr(lst, rest_cell)); sptr[1] = rest_cell; - sptr[2] = lbm_cdr(val); + sptr[2] = get_cdr(val); stack_push(&ctx->K, MOVE_LIST_TO_FLASH); stack_push(&ctx->K, MOVE_VAL_TO_FLASH_DISPATCH); - ctx->r = lbm_car(val); + ctx->r = get_car(val); } else { sptr[0] = fst; sptr[1] = lst; @@ -3632,8 +3724,8 @@ static void evaluation_step(void){ } } /* - * At this point head can be a closure, fundamental, extension or a macro. - * Anything else would be an error. + * At this point head can be anything. It should evaluate + * into a form that can be applied (closure, symbol, ...) though. */ lbm_value *reserved = stack_reserve(ctx, 3); reserved[0] = ctx->curr_env; @@ -3731,6 +3823,47 @@ static void process_events(void) { } } +static void process_waiting(void) { + + uint32_t wait_flags = wait_for; // Should ideally be atomic + wait_for = wait_flags ^ wait_for; // + + eval_context_queue_t *q = &blocked; + + mutex_lock(&qmutex); + eval_context_t *curr = q->first; + while (curr != NULL) { + eval_context_t *next = curr->next; // grab here + if (curr->wait_mask & wait_flags) { + eval_context_t *ctx = curr; + if (curr == q->last) { + if (curr->prev) { + q->last = curr->prev; + q->last->next = NULL; + } else { + q->first = NULL; + q->last = NULL; + } + } else if (curr->prev == NULL) { + q->first = curr->next; + if (q->first) { + q->first->prev = NULL; + } + } else { + curr->prev->next = curr->next; + if (curr->next) { + curr->next->prev = curr->prev; + } + } + ctx->wait_mask = 0; + ctx->r = ENC_SYM_TRUE; // woken up task receives true. + enqueue_ctx_nm(&queue, ctx); // changes meaing of curr->next. + } + curr = next; + } + mutex_unlock(&qmutex); +} + /* eval_cps_run can be paused I think it would be better use a mailbox for communication between other threads and the run_eval @@ -3781,6 +3914,9 @@ void lbm_run_eval(void){ if (gc_requested) { gc(); } + if (wait_for) { + process_waiting(); + } process_events(); next_to_run = dequeue_ctx(&sleeping, &us); } diff --git a/src/extensions/array_extensions.c b/src/extensions/array_extensions.c index 86464171..ae82514e 100644 --- a/src/extensions/array_extensions.c +++ b/src/extensions/array_extensions.c @@ -913,7 +913,7 @@ lbm_value array_extension_buffer_length(lbm_value *args, lbm_uint argn) { return res; } - +//TODO: Have to think about 32 vs 64 bit here static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn) { lbm_value res = ENC_SYM_EERROR; @@ -931,25 +931,25 @@ static lbm_value array_extensions_bufclear(lbm_value *args, lbm_uint argn) { clear_byte = (uint8_t)lbm_dec_as_u32(args[1]); } - unsigned int start = 0; + uint32_t start = 0; if (argn >= 3) { if (!lbm_is_number(args[2])) { return res; } - unsigned int start_new = lbm_dec_as_u32(args[2]); + uint32_t start_new = lbm_dec_as_u32(args[2]); if (start_new < array->size) { start = start_new; } else { return res; } } - - unsigned int len = array->size - start; + // Truncates size on 64 bit build + uint32_t len = (uint32_t)array->size - start; if (argn >= 4) { if (!lbm_is_number(args[3])) { return res; } - unsigned int len_new = lbm_dec_as_u32(args[3]); + uint32_t len_new = lbm_dec_as_u32(args[3]); if (len_new <= len) { len = len_new; } @@ -971,19 +971,19 @@ static lbm_value array_extensions_bufcpy(lbm_value *args, lbm_uint argn) { lbm_array_header_t *array1 = (lbm_array_header_t *)lbm_car(args[0]); - unsigned int start1 = lbm_dec_as_u32(args[1]); + uint32_t start1 = lbm_dec_as_u32(args[1]); lbm_array_header_t *array2 = (lbm_array_header_t *)lbm_car(args[2]); - unsigned int start2 = lbm_dec_as_u32(args[3]); - unsigned int len = lbm_dec_as_u32(args[4]); + uint32_t start2 = lbm_dec_as_u32(args[3]); + uint32_t len = lbm_dec_as_u32(args[4]); if (start1 < array1->size && start2 < array2->size) { if (len > (array1->size - start1)) { - len = (array1->size - start1); + len = ((uint32_t)array1->size - start1); } if (len > (array2->size - start2)) { - len = (array2->size - start2); + len = ((uint32_t)array2->size - start2); } memcpy((char*)array1->data + start1, (char*)array2->data + start2, len); diff --git a/src/extensions/matvec_extensions.c b/src/extensions/matvec_extensions.c index b2fa4216..cdd7e787 100644 --- a/src/extensions/matvec_extensions.c +++ b/src/extensions/matvec_extensions.c @@ -25,7 +25,7 @@ static const char *vector_float_desc = "Vector-Float"; static const char *matrix_float_desc = "Matrix-Float"; typedef struct { - unsigned int size; + lbm_uint size; float data[1]; } vector_float_t; @@ -184,7 +184,7 @@ static lbm_value ext_axpy(lbm_value *args, lbm_uint argn ) { if (X->size == Y->size) { - unsigned int res_size = X->size; + lbm_uint res_size = X->size; res = vector_float_allocate(res_size); if (!lbm_is_symbol_merror(res)) { @@ -214,7 +214,7 @@ static lbm_value ext_dot(lbm_value *args, lbm_uint argn) { vector_float_t *Y = (vector_float_t*)lbm_get_custom_value(y); if (X->size == Y->size) { - unsigned int res_size = X->size; + lbm_uint res_size = X->size; float f_res = 0; for (unsigned i = 0; i < res_size; i ++) { @@ -306,7 +306,7 @@ static lbm_value ext_matrix_to_list(lbm_value *args, lbm_uint argn) { lbm_value res = ENC_SYM_TERROR; if (argn == 1 && is_matrix_float(args[0])) { matrix_float_t *lmat = (matrix_float_t*)lbm_get_custom_value(args[0]); - unsigned int size = lmat->rows * lmat->cols; + lbm_uint size = lmat->rows * lmat->cols; res = lbm_heap_allocate_list(size); if (lbm_is_cons(res)) { diff --git a/src/extensions/string_extensions.c b/src/extensions/string_extensions.c index f28db5f9..5676292a 100644 --- a/src/extensions/string_extensions.c +++ b/src/extensions/string_extensions.c @@ -134,7 +134,7 @@ static lbm_value ext_str_to_i(lbm_value *args, lbm_uint argn) { base = (int)lbm_dec_as_u32(args[1]); } - return lbm_enc_i32(strtol(str, NULL, base)); + return lbm_enc_i32((int32_t)strtol(str, NULL, base)); } static lbm_value ext_str_to_f(lbm_value *args, lbm_uint argn) { @@ -160,15 +160,15 @@ static lbm_value ext_str_part(lbm_value *args, lbm_uint argn) { return ENC_SYM_EERROR; } - size_t len = strlen(str); + uint32_t len = (uint32_t)strlen(str); - unsigned int start = lbm_dec_as_u32(args[1]); + uint32_t start = lbm_dec_as_u32(args[1]); if (start >= len) { return ENC_SYM_EERROR; } - unsigned int n = len - start; + uint32_t n = len - start; if (argn == 3) { if (!lbm_is_number(args[2])) { return ENC_SYM_EERROR; @@ -257,6 +257,7 @@ static lbm_value ext_str_split(lbm_value *args, lbm_uint argn) { } } +// Todo: Clean this up for 64bit static lbm_value ext_str_replace(lbm_value *args, lbm_uint argn) { if (argn != 2 && argn != 3) { return ENC_SYM_EERROR; @@ -413,7 +414,7 @@ static lbm_value ext_str_cmp(lbm_value *args, lbm_uint argn) { // TODO: This is very similar to ext-print. Maybe they can share code. static lbm_value to_str(char *delimiter, lbm_value *args, lbm_uint argn) { const int str_len = 300; - char *str = lbm_malloc(str_len); + char *str = lbm_malloc((lbm_uint)str_len); if (!str) { return ENC_SYM_MERROR; } diff --git a/src/fundamental.c b/src/fundamental.c index ad100917..f7822169 100644 --- a/src/fundamental.c +++ b/src/fundamental.c @@ -665,24 +665,30 @@ static lbm_value fundamental_append(lbm_value *args, lbm_uint nargs, eval_contex return(res); } -// TODO: See if trouble 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 new_env = env; lbm_value result = ENC_SYM_EERROR; if (nargs == 1 && lbm_is_symbol(args[0])) { result = lbm_env_drop_binding(env, args[0]); + if (result == ENC_SYM_NOT_FOUND) { + return env; + } *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); + result = lbm_env_drop_binding(new_env, key); + if (result != ENC_SYM_NOT_FOUND) { + new_env = result; + } curr = lbm_cdr(curr); } - *lbm_get_env_ptr() = result; + *lbm_get_env_ptr() = new_env; } - return result; + return new_env; } static lbm_value fundamental_buf_create(lbm_value *args, lbm_uint nargs, eval_context_t *ctx) { diff --git a/src/heap.c b/src/heap.c index b3c561e4..b92a2804 100644 --- a/src/heap.c +++ b/src/heap.c @@ -1,6 +1,6 @@ /* - Copyright 2018, 2020, 2022 Joel Svensson svenssonjoel@yahoo.se - 2022 Benjamin Vedder + Copyright 2018, 2020, 2022, 2023 Joel Svensson svenssonjoel@yahoo.se + 2022 Benjamin Vedder This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -79,7 +79,7 @@ lbm_value lbm_enc_u32(uint32_t x) { #endif } -lbm_value lbm_enc_float(float x) { +lbm_value lbm_enc_float(lbm_float x) { #ifndef LBM64 lbm_uint t; memcpy(&t, &x, sizeof(lbm_float)); @@ -427,7 +427,7 @@ static int generate_freelist(size_t num_cells) { for (i = 1; i < num_cells; i ++) { t = lbm_ref_cell(lbm_enc_cons_ptr(i-1)); t->car = ENC_SYM_RECOVERED; // all cars in free list are "RECOVERED" - t->cdr = lbm_enc_cons_ptr(i); + t->cdr = lbm_enc_cons_ptr(i); } // Replace the incorrect pointer at the last cell. @@ -506,12 +506,13 @@ lbm_value lbm_heap_allocate_cell(lbm_type ptr_type, lbm_value car, lbm_value cdr res = lbm_heap_state.freelist; if (lbm_type_of(res) == LBM_TYPE_CONS) { - lbm_heap_state.freelist = lbm_cdr(lbm_heap_state.freelist); + lbm_cons_t *rc = lbm_ref_cell(res); + lbm_heap_state.freelist = rc->cdr; lbm_heap_state.num_alloc++; - lbm_ref_cell(res)->car = car; - lbm_ref_cell(res)->cdr = cdr; + rc->car = car; + rc->cdr = cdr; res = lbm_set_ptr_type(res, ptr_type); return res; @@ -526,53 +527,49 @@ lbm_value lbm_heap_allocate_cell(lbm_type ptr_type, lbm_value car, lbm_value cdr } } -lbm_value lbm_heap_allocate_list(unsigned int n) { +lbm_value lbm_heap_allocate_list(lbm_uint n) { if (n == 0) return ENC_SYM_NIL; if (lbm_heap_num_free() < n) return ENC_SYM_MERROR; - lbm_value res = lbm_heap_state.freelist; - if (lbm_type_of(res) == LBM_TYPE_CONS) { + lbm_value curr = lbm_heap_state.freelist; + lbm_value res = curr; + if (lbm_type_of(curr) == LBM_TYPE_CONS) { - lbm_value curr = res; - unsigned int count = 1; - while (lbm_type_of(curr) == LBM_TYPE_CONS && count < n) { - lbm_ref_cell(curr)->car = ENC_SYM_NIL; - curr = lbm_cdr(curr); + lbm_cons_t *c_cell = NULL; + lbm_uint count = 0; + do { + c_cell = lbm_ref_cell(curr); + c_cell->car = ENC_SYM_NIL; + curr = c_cell->cdr; count ++; - } - lbm_set_car(curr, ENC_SYM_NIL); - lbm_heap_state.freelist = lbm_cdr(curr); - lbm_set_cdr(curr, ENC_SYM_NIL); + } while (count < n); + lbm_heap_state.freelist = curr; + c_cell->cdr = ENC_SYM_NIL; lbm_heap_state.num_alloc+=count; return res; - } else { - return ENC_SYM_FATAL_ERROR; } + return ENC_SYM_FATAL_ERROR; } lbm_value lbm_heap_allocate_list_init_va(unsigned int n, va_list valist) { - if (n == 0) { - return ENC_SYM_NIL; - } - if (lbm_heap_num_free() < n) { - return ENC_SYM_MERROR; - } + if (n == 0) return ENC_SYM_NIL; + if (lbm_heap_num_free() < n) return ENC_SYM_MERROR; - lbm_value res = lbm_heap_state.freelist; - if (lbm_type_of(res) == LBM_TYPE_CONS) { + lbm_value curr = lbm_heap_state.freelist; + lbm_value res = curr; + if (lbm_type_of(curr) == LBM_TYPE_CONS) { - lbm_value curr = res; - unsigned int count = 1; - while (lbm_type_of(curr) == LBM_TYPE_CONS && count < n) { - lbm_ref_cell(curr)->car = va_arg(valist, lbm_value); - curr = lbm_cdr(curr); + lbm_cons_t *c_cell = NULL; + unsigned int count = 0; + do { + c_cell = lbm_ref_cell(curr); + c_cell->car = va_arg(valist, lbm_value); + curr = c_cell->cdr; count ++; - } - lbm_set_car(curr, va_arg(valist, lbm_value)); - lbm_heap_state.freelist = lbm_cdr(curr); - lbm_set_cdr(curr, ENC_SYM_NIL); + } while (count < n); + lbm_heap_state.freelist = curr; + c_cell->cdr = ENC_SYM_NIL; lbm_heap_state.num_alloc+=count; - va_end(valist); return res; } return ENC_SYM_FATAL_ERROR; @@ -640,8 +637,8 @@ int lbm_gc_mark_phase(int num, ... ) { //lbm_value env) { if (t_ptr >= LBM_NON_CONS_POINTER_TYPE_FIRST && t_ptr <= LBM_NON_CONS_POINTER_TYPE_LAST) continue; - res &= lbm_push(s, lbm_ref_cell(curr)->cdr); - res &= lbm_push(s, lbm_ref_cell(curr)->car); + res &= lbm_push(s, cell->cdr); + res &= lbm_push(s, cell->car); if (!res) break; } @@ -877,8 +874,8 @@ int lbm_set_car_and_cdr(lbm_value c, lbm_value car_val, lbm_value cdr_val) { } /* calculate length of a proper list */ -unsigned int lbm_list_length(lbm_value c) { - unsigned int len = 0; +lbm_uint lbm_list_length(lbm_value c) { + lbm_uint len = 0; while (lbm_is_cons(c)){ len ++; diff --git a/src/lbm_channel.c b/src/lbm_channel.c index 383adfba..232a6ea6 100644 --- a/src/lbm_channel.c +++ b/src/lbm_channel.c @@ -368,7 +368,7 @@ void lbm_create_string_char_channel(lbm_string_channel_state_t *st, char *str) { st->str = str; - st->length = strlen(str); + st->length = (unsigned int)strlen(str); st->read_pos = 0; st->write_pos = 0; st->more = false; diff --git a/src/lbm_flat_value.c b/src/lbm_flat_value.c index e3c21cc8..3087a1e3 100644 --- a/src/lbm_flat_value.c +++ b/src/lbm_flat_value.c @@ -274,9 +274,15 @@ static int lbm_unflatten_value_internal(lbm_flat_value_t *v, lbm_value *res) { } case S_FLOAT_VALUE: { lbm_uint tmp; - if (extract_word(v, &tmp)) { - float f; - memcpy(&f, &tmp, sizeof(float)); + bool b; +#ifndef LBM64 + b = extract_word(v, &tmp); +#else + b = extract_dword(v, &tmp); +#endif + if (b) { + lbm_float f; + memcpy(&f, &tmp, sizeof(lbm_float)); lbm_value im = lbm_enc_float(f); if (lbm_is_symbol_merror(im)) { return UNFLATTEN_GC_RETRY; @@ -287,7 +293,7 @@ static int lbm_unflatten_value_internal(lbm_flat_value_t *v, lbm_value *res) { return UNFLATTEN_MALFORMED; } case S_I32_VALUE: { - lbm_uint tmp; + uint32_t tmp; if (extract_word(v, &tmp)) { lbm_value im = lbm_enc_i32((int32_t)tmp); if (lbm_is_symbol_merror(im)) { @@ -299,7 +305,7 @@ static int lbm_unflatten_value_internal(lbm_flat_value_t *v, lbm_value *res) { return UNFLATTEN_MALFORMED; } case S_U32_VALUE: { - lbm_uint tmp; + uint32_t tmp; if (extract_word(v, &tmp)) { lbm_value im = lbm_enc_u32(tmp); if (lbm_is_symbol_merror(im)) { diff --git a/src/lbm_memory.c b/src/lbm_memory.c index 27060da9..fac26414 100644 --- a/src/lbm_memory.c +++ b/src/lbm_memory.c @@ -81,7 +81,7 @@ int lbm_memory_init(lbm_uint *data, lbm_uint data_size, memory_base_address = (lbm_uint)data; memory_size = data_size; memory_num_free = data_size; - memory_reserve_level = (lbm_uint)(0.1 * data_size); + memory_reserve_level = (lbm_uint)(0.1 * (lbm_float)data_size); res = 1; } mutex_unlock(&lbm_mem_mutex); diff --git a/src/print.c b/src/print.c index 06ec1632..2ea1b1c4 100644 --- a/src/print.c +++ b/src/print.c @@ -135,15 +135,15 @@ int print_emit_symbol(lbm_char_channel_t *chan, lbm_value sym) { return print_emit_string(chan, str_ptr); } -int print_emit_i(lbm_char_channel_t *chan, int32_t v) { +int print_emit_i(lbm_char_channel_t *chan, lbm_int v) { char buf[EMIT_BUFFER_SIZE]; - snprintf(buf, EMIT_BUFFER_SIZE, "%"PRIi32, v); + snprintf(buf, EMIT_BUFFER_SIZE, "%"PRI_INT, v); return print_emit_string(chan, buf); } -int print_emit_u(lbm_char_channel_t *chan, uint32_t v, bool ps) { +int print_emit_u(lbm_char_channel_t *chan, lbm_uint v, bool ps) { char buf[EMIT_BUFFER_SIZE]; - snprintf(buf, EMIT_BUFFER_SIZE, "%"PRIu32"%s", v, ps ? "u" : ""); + snprintf(buf, EMIT_BUFFER_SIZE, "%"PRI_UINT"%s", v, ps ? "u" : ""); return print_emit_string(chan, buf); } diff --git a/src/symrepr.c b/src/symrepr.c index 6618df3c..9a19cf08 100644 --- a/src/symrepr.c +++ b/src/symrepr.c @@ -66,6 +66,7 @@ special_sym const special_symbols[] = { {"exit-error" , SYM_EXIT_ERROR}, {"map" , SYM_MAP}, {"reverse" , SYM_REVERSE}, + {"wait-for" , SYM_WAIT_FOR}, {"gc" , SYM_PERFORM_GC}, // pattern matching diff --git a/tests/test_lisp_code_cps.c b/tests/test_lisp_code_cps.c index 2dae79b2..47c87a82 100644 --- a/tests/test_lisp_code_cps.c +++ b/tests/test_lisp_code_cps.c @@ -113,9 +113,9 @@ void context_done_callback(eval_context_t *ctx) { if (test_cid == ctx->id) experiment_done = true; - int res = lbm_print_value(output, 128, t); + (void)lbm_print_value(output, 128, t); - printf("Thread %d finished: %s\n", ctx->id, output); + printf("Thread %d finished: %s\n", (int32_t)ctx->id, output); } bool dyn_load(const char *str, const char **code) { @@ -347,7 +347,7 @@ LBM_EXTENSION(ext_check, args, argn) { printf("Test: Failed!\n"); printf("Result: %s\n", output); } - return res; + return ENC_SYM_TRUE; } char *const_prg = "(define a 10) (+ a 1)"; @@ -357,13 +357,18 @@ LBM_EXTENSION(ext_const_prg, args, argn) { (void) argn; lbm_value v = ENC_SYM_NIL; - char *str = const_prg; - if (!lbm_share_const_array(&v, const_prg, strlen(const_prg)+1)) return ENC_SYM_NIL; return v; } +LBM_EXTENSION(ext_trigger, args, argn) { + if (argn == 1 && lbm_is_number(args[0])) { + lbm_trigger_flags(lbm_dec_as_u32(args[0])); + return ENC_SYM_TRUE; + } + return ENC_SYM_NIL; +} int main(int argc, char **argv) { @@ -681,6 +686,14 @@ int main(int argc, char **argv) { return 0; } + res = lbm_add_extension("trigger", ext_trigger); + if (res) + printf("Extension added.\n"); + else { + printf("Error adding extension.\n"); + return 0; + } + lbm_set_dynamic_load_callback(dyn_load); lbm_set_timestamp_us_callback(timestamp_callback); lbm_set_usleep_callback(sleep_callback); diff --git a/tests/test_undefine_1.lisp b/tests/test_undefine_1.lisp new file mode 100644 index 00000000..5c3fb6da --- /dev/null +++ b/tests/test_undefine_1.lisp @@ -0,0 +1,6 @@ +(setvar 'apa 1) +(define bepa 2) + +(undefine 'apa) + +(check (= bepa 2)) diff --git a/tests/test_undefine_2.lisp b/tests/test_undefine_2.lisp new file mode 100644 index 00000000..0c107f73 --- /dev/null +++ b/tests/test_undefine_2.lisp @@ -0,0 +1,7 @@ + +(define apa 1) +(setvar 'bepa 2) + +(undefine 'apa) + +(check (= bepa 2)) diff --git a/tests/test_undefine_3.lisp b/tests/test_undefine_3.lisp new file mode 100644 index 00000000..78407788 --- /dev/null +++ b/tests/test_undefine_3.lisp @@ -0,0 +1,19 @@ + +(define a 10) + +(defun f (n) + (if (= n 0) 0 + (progn + (define b 100) + (undefine 'b) + (f (- n 1))))) + +(f 10000) + +(define b 75) + +(check (and (= a 10) + (= b 75))) + + + diff --git a/tests/test_undefine_4.lisp b/tests/test_undefine_4.lisp new file mode 100644 index 00000000..dcf4e7a7 --- /dev/null +++ b/tests/test_undefine_4.lisp @@ -0,0 +1,15 @@ +(setvar 'a 10) + +(defun f (n) + (if (= n 0) 0 + (progn + (setvar 'b 100) + (undefine 'b) + (f (- n 1))))) + +(f 10000) + +(define b 75) + +(check (and (= a 10) + (= b 75))) diff --git a/tests/test_undefine_5.lisp b/tests/test_undefine_5.lisp new file mode 100644 index 00000000..d73f466a --- /dev/null +++ b/tests/test_undefine_5.lisp @@ -0,0 +1,18 @@ +(define a 10) + +(defun f (n) + (if (= n 0) 0 + (progn + (define b 100) + (undefine 'b) + (f (- n 1))))) + +(f 10000) +(define c 5) +(f 10000) + +(define b 75) + +(check (and (= a 10) + (= b 75) + (= c 5))) diff --git a/tests/test_undefine_6.lisp b/tests/test_undefine_6.lisp new file mode 100644 index 00000000..ffc94aa8 --- /dev/null +++ b/tests/test_undefine_6.lisp @@ -0,0 +1,19 @@ +(define a 10) + +(defun f (n) + (if (= n 0) 0 + (progn + (set 'a 10) + (define b 100) + (undefine 'b) + (f (- n 1))))) + +(f 10000) +(undefine 'a) +(define c 5) +(f 10000) + +(define b 75) + +(check (and (= b 75) + (= c 5))) diff --git a/tests/test_undefine_7.lisp b/tests/test_undefine_7.lisp new file mode 100644 index 00000000..0cab31a3 --- /dev/null +++ b/tests/test_undefine_7.lisp @@ -0,0 +1,5 @@ +(define a 10) + +(undefine 'kurt) + +(check (= a 10)) diff --git a/tests/test_undefine_8.lisp b/tests/test_undefine_8.lisp new file mode 100644 index 00000000..8c3d0963 --- /dev/null +++ b/tests/test_undefine_8.lisp @@ -0,0 +1,7 @@ + +(define a 10) +(define b 20) + +(undefine (list 'a)) + +(check (= b 20)) diff --git a/tests/test_undefine_9.lisp b/tests/test_undefine_9.lisp new file mode 100644 index 00000000..addc70a4 --- /dev/null +++ b/tests/test_undefine_9.lisp @@ -0,0 +1,7 @@ + +(define a 10) +(define b 20) + +(undefine (list 'a 'kurt 'russel)) + +(check (= b 20)) diff --git a/tests/test_wait_for_1.lisp b/tests/test_wait_for_1.lisp new file mode 100644 index 00000000..6d64cdd7 --- /dev/null +++ b/tests/test_wait_for_1.lisp @@ -0,0 +1,12 @@ + + +(defun f () { + (wait-for (shl 1 9)) + (check 't) + }) + + +(spawn f) + + +(trigger (shl 1 9)) diff --git a/tests/test_wait_for_2.lisp b/tests/test_wait_for_2.lisp new file mode 100644 index 00000000..e80e12de --- /dev/null +++ b/tests/test_wait_for_2.lisp @@ -0,0 +1,16 @@ + + +(defun g () { + (wait-for (shl 1 3)) + (check 't) + }) + +(defun f () { + (wait-for (shl 1 9)) + (trigger (shl 1 3)) + }) + +(spawn f) +(spawn g) + +(trigger (shl 1 9)) diff --git a/tests/test_wait_for_3.lisp b/tests/test_wait_for_3.lisp new file mode 100644 index 00000000..a91098d7 --- /dev/null +++ b/tests/test_wait_for_3.lisp @@ -0,0 +1,19 @@ + +(def a 0) + +(defun g () { + (wait-for (shl 1 9)) + (def a (+ a 1)) + }) + +(defun f () { + (wait-for (shl 1 9)) + (def a (+ a 1)) + }) + +(spawn f) +(spawn g) +(yield 10000) +(trigger (shl 1 9)) +(yield 10000) +(check (= a 2))