From dccfe151354c45e77946b6b41a09d97b521c14e4 Mon Sep 17 00:00:00 2001 From: Benjamin Vedder Date: Thu, 6 Oct 2022 13:58:38 +0200 Subject: [PATCH] Squashed 'lispBM/lispBM/' changes from 7756d581..b3d8a6b2 b3d8a6b2 removed functions that nolonger have a purpose 306722dc remove the possibility to step through program and reorganize the most critical loop structure aa6eb5ca remove encode, decode from refman 899d8579 update README and plot script 132e9364 updated readme with more detailed intro git-subtree-dir: lispBM/lispBM git-subtree-split: b3d8a6b21af4683af8837ad1a5106cf0d2d7eac9 --- README.md | 11 ++++- benchmarks/plot_bench.py | 4 +- doc/lbmref.md | 47 ------------------ include/eval_cps.h | 10 ---- repl/repl.c | 6 --- src/eval_cps.c | 97 +++++++++++++++++--------------------- tests/test_lisp_code_cps.c | 49 ++++++++++--------- 7 files changed, 81 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index 99d783aa..a2e45cae 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,14 @@ # lispBM (LBM) -A concurrent lisp-like language with message-passing and -pattern-matching implemented in C for 32 bit and 64 bit platforms. +LispBM is a lisp or scheme like programming language for +microcontrollers. LispBM also borrows a couple of ideas from Erlang +when it comes to concurrency, message passing, pattern matching and +process monitoring. The LispBM runtime system can be compiled for +either 32 or 64 bit platforms and runs on a wide range of hardware +such as for example STM32, NRF52, ESP32 or X86. When running the +LispBM runtime system on a microcontroller it can be built on top of +ChibiOS, FreeRTOS or ZephyrOS and it can also be built to run on top +of a regular linux. ![LispBM mascot](https://github.com/svenssonjoel/lispBM/blob/master/mascot/lispbm_llama_small.png) diff --git a/benchmarks/plot_bench.py b/benchmarks/plot_bench.py index ac6d24a9..8a3fa8d9 100644 --- a/benchmarks/plot_bench.py +++ b/benchmarks/plot_bench.py @@ -36,7 +36,9 @@ for bench in benches: lgd = plt.legend(loc='center left', bbox_to_anchor=(1, 0.5)) ax = plt.gca() for tick in ax.get_xticklabels(): - tick.set_rotation(45) + tick.set_rotation(90) +ax.tick_params(axis='both', which='major', labelsize=6) +ax.tick_params(axis='both', which='minor', labelsize=4) plt.ylabel("Sec") plt.grid() plt.savefig('benchresults.png', dpi=600, bbox_extra_artists=(lgd,), bbox_inches='tight') diff --git a/doc/lbmref.md b/doc/lbmref.md index 7c98f49c..b7a8a502 100644 --- a/doc/lbmref.md +++ b/doc/lbmref.md @@ -347,53 +347,6 @@ the argument. ## Low level operations -### encode-i32 - -The `encode-i32` function converts a list of four (byte sized) values -into an i32 value. - -Example that evaluates to the i32 value 1024. -```clj -(encode-i32 (list 0 0 4 0)) -``` - - ---- - -### encode-u32 - -The `encode-u32` function converts a list of four (byte sized) values -into an u32 value. - -Example that evaluates to the u32 value 1024. -```clj -(encode-u32 (list 0 0 4 0)) -``` - ---- - -### encode-float - -The `encode-float` function converts a list four (byte sized) values -into a float value. - -Example that evaluates to 3.14. -```clj -(encode-float (list 64 72 245 195)) -``` - - ---- - -### decode - -The `decode` function decodes a value into a list of four (byte sized) values. - -Example that decodes float 3.14 into the list (64 72 245 195). -```clj -(decode 3.14) -``` - --- ## nil and t diff --git a/include/eval_cps.h b/include/eval_cps.h index e61dfd70..9d6f4126 100644 --- a/include/eval_cps.h +++ b/include/eval_cps.h @@ -141,16 +141,6 @@ void lbm_pause_eval(void); * \param num_free Perform GC if there are less than this many elements free on the heap. */ void lbm_pause_eval_with_gc(uint32_t num_free); -/** Perform a single step of evaluation. - * The evaluator should be in EVAL_CPS_STATE_PAUSED before running this function. - * After taking one step of evaluation, the evaluator will return to being in the - * EVAL_CPS_STATE_PUASED state. - */ -void lbm_step_eval(void); -/** Perform multiple steps of evaluation. - * \param n Number of eval steps to perform. - */ -void lbm_step_n_eval(uint32_t n); /** Resume from being in EVAL_CPS_STATE_PAUSED. * */ diff --git a/repl/repl.c b/repl/repl.c index f84942fd..416653b9 100644 --- a/repl/repl.c +++ b/repl/repl.c @@ -833,12 +833,6 @@ int main(int argc, char **argv) { } else if (strncmp(str, ":continue", 9) == 0) { lbm_continue_eval(); free(str); - } else if (strncmp(str, ":step", 5) == 0) { - - int num = atoi(str + 5); - - lbm_step_n_eval((uint32_t)num); - free(str); } else if (strncmp(str, ":inspect", 8) == 0) { int i = 8; diff --git a/src/eval_cps.c b/src/eval_cps.c index cd5c1a53..dbc72b8e 100644 --- a/src/eval_cps.c +++ b/src/eval_cps.c @@ -137,9 +137,10 @@ void lbm_set_eval_step_quota(uint32_t quota) { eval_steps_refill = quota; } -static uint32_t eval_cps_run_state = EVAL_CPS_STATE_INIT; -static volatile uint32_t eval_cps_next_state = EVAL_CPS_STATE_INIT; +static uint32_t eval_cps_run_state = EVAL_CPS_STATE_RUNNING; +static volatile uint32_t eval_cps_next_state = EVAL_CPS_STATE_RUNNING; static volatile uint32_t eval_cps_next_state_arg = 0; +static volatile bool eval_cps_state_changed = false; /* On ChibiOs the CH_CFG_ST_FREQUENCY setting in chconf.h sets the @@ -2884,29 +2885,23 @@ static void evaluation_step(void){ void lbm_pause_eval(void ) { eval_cps_next_state_arg = 0; eval_cps_next_state = EVAL_CPS_STATE_PAUSED; + if (eval_cps_next_state != eval_cps_run_state) eval_cps_state_changed = true; } void lbm_pause_eval_with_gc(uint32_t num_free) { eval_cps_next_state_arg = num_free; eval_cps_next_state = EVAL_CPS_STATE_PAUSED; -} - -void lbm_step_eval(void) { - eval_cps_next_state_arg = 1; - eval_cps_next_state = EVAL_CPS_STATE_STEP; -} - -void lbm_step_n_eval(uint32_t n) { - eval_cps_next_state_arg = n; - eval_cps_next_state = EVAL_CPS_STATE_STEP; + if (eval_cps_next_state != eval_cps_run_state) eval_cps_state_changed = true; } void lbm_continue_eval(void) { eval_cps_next_state = EVAL_CPS_STATE_RUNNING; + if (eval_cps_next_state != eval_cps_run_state) eval_cps_state_changed = true; } void lbm_kill_eval(void) { eval_cps_next_state = EVAL_CPS_STATE_KILL; + if (eval_cps_next_state != eval_cps_run_state) eval_cps_state_changed = true; } uint32_t lbm_get_eval_state(void) { @@ -2920,19 +2915,8 @@ uint32_t lbm_get_eval_state(void) { void lbm_run_eval(void){ while (eval_running) { - + eval_cps_state_changed = false; switch (eval_cps_next_state) { - case EVAL_CPS_STATE_INIT: - eval_cps_run_state = EVAL_CPS_STATE_RUNNING; - break; - case EVAL_CPS_STATE_STEP: - if (eval_cps_next_state_arg > 1) { - eval_cps_next_state = EVAL_CPS_STATE_STEP; - eval_cps_next_state_arg --; - } else { - eval_cps_next_state = EVAL_CPS_STATE_PAUSED; - } - break; case EVAL_CPS_STATE_PAUSED: if (eval_cps_run_state != EVAL_CPS_STATE_PAUSED) { if (lbm_heap_num_free() < eval_cps_next_state_arg) { @@ -2946,46 +2930,49 @@ void lbm_run_eval(void){ case EVAL_CPS_STATE_KILL: eval_running = false; continue; - default: + default: // running state eval_cps_run_state = eval_cps_next_state; break; } - eval_context_t *next_to_run = NULL; - if (eval_steps_quota <= 0 || !ctx_running) { - uint32_t us = EVAL_CPS_MIN_SLEEP; - - if (is_atomic) { - if (ctx_running) { - next_to_run = ctx_running; - ctx_running = NULL; - } else { - is_atomic = false; - // This is not right! - // but there is no context available to - // report an error in. - } + while (true) { + eval_context_t *next_to_run = NULL; + if (eval_steps_quota && ctx_running) { + eval_steps_quota--; + evaluation_step(); } else { - next_to_run = dequeue_ctx(&sleeping, &us); - } + if (eval_cps_state_changed) break; + uint32_t us = EVAL_CPS_MIN_SLEEP; - if (!next_to_run) { - next_to_run = enqueue_dequeue_ctx(&queue, ctx_running); - } else if (ctx_running) { - enqueue_ctx(&queue, ctx_running); - } + if (is_atomic) { + if (ctx_running) { + next_to_run = ctx_running; + ctx_running = NULL; + } else { + is_atomic = false; + // This is not right! + // but there is no context available to + // report an error in. + } + } else { + next_to_run = dequeue_ctx(&sleeping, &us); + } - eval_steps_quota = eval_steps_refill; - ctx_running = next_to_run; + if (!next_to_run) { + next_to_run = enqueue_dequeue_ctx(&queue, ctx_running); + } else if (ctx_running) { + enqueue_ctx(&queue, ctx_running); + } - if (!ctx_running) { - usleep_callback(us); - continue; + eval_steps_quota = eval_steps_refill; + ctx_running = next_to_run; + + if (!ctx_running) { + usleep_callback(us); + continue; + } } } - - eval_steps_quota--; - evaluation_step(); } } @@ -3010,7 +2997,7 @@ int lbm_eval_init() { done.last = NULL; ctx_running = NULL; - eval_cps_run_state = EVAL_CPS_STATE_INIT; + eval_cps_run_state = EVAL_CPS_STATE_RUNNING; mutex_init(&qmutex); diff --git a/tests/test_lisp_code_cps.c b/tests/test_lisp_code_cps.c index 1dd60db6..75ca857f 100644 --- a/tests/test_lisp_code_cps.c +++ b/tests/test_lisp_code_cps.c @@ -1,5 +1,5 @@ /* - Copyright 2018,2020 Joel Svensson svenssonjoel@yahoo.se + Copyright 2018,2020 Joel Svensson svenssonjoel@yahoo.se 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 @@ -109,8 +109,8 @@ bool dyn_load(const char *str, const char **code) { } else if (strlen(str) == 7 && strncmp(str, "reverse", 7) == 0) { *code = "(define reverse (lambda (xs)" "(let ((revacc (lambda (acc xs)" - "(if (eq nil xs) acc" - "(revacc (cons (car xs) acc) (cdr xs))))))" + "(if (eq nil xs) acc" + "(revacc (cons (car xs) acc) (cdr xs))))))" "(revacc nil xs))))"; res = true; } else if (strlen(str) == 4 && strncmp(str, "iota", 4) == 0) { @@ -122,45 +122,45 @@ bool dyn_load(const char *str, const char **code) { res = true; } else if (strlen(str) == 6 && strncmp(str, "length", 6) == 0) { *code = "(define length (lambda (xs)" - "(let ((len (lambda (l xs)" - "(if (eq xs nil) l" - "(len (+ l 1) (cdr xs))))))" + "(let ((len (lambda (l xs)" + "(if (eq xs nil) l" + "(len (+ l 1) (cdr xs))))))" "(len 0 xs))))"; res = true; } else if (strlen(str) == 4 && strncmp(str, "take", 4) == 0) { *code = "(define take (lambda (n xs)" - "(let ((take-tail (lambda (acc n xs)" - "(if (= n 0) acc" - "(take-tail (cons (car xs) acc) (- n 1) (cdr xs))))))" + "(let ((take-tail (lambda (acc n xs)" + "(if (= n 0) acc" + "(take-tail (cons (car xs) acc) (- n 1) (cdr xs))))))" "(reverse (take-tail nil n xs)))))"; res = true; } else if (strlen(str) == 4 && strncmp(str, "drop", 4) == 0) { *code = "(define drop (lambda (n xs)" - "(if (= n 0) xs" - "(if (eq xs nil) nil" + "(if (= n 0) xs" + "(if (eq xs nil) nil" "(drop (- n 1) (cdr xs))))))"; res = true; } else if (strlen(str) == 3 && strncmp(str, "zip", 3) == 0) { *code = "(define zip (lambda (xs ys)" - "(if (eq xs nil) nil" - "(if (eq ys nil) nil" + "(if (eq xs nil) nil" + "(if (eq ys nil) nil" "(cons (cons (car xs) (car ys)) (zip (cdr xs) (cdr ys)))))))"; res = true; } else if (strlen(str) == 3 && strncmp(str, "map", 3) == 0) { *code = "(define map (lambda (f xs)" - "(if (eq xs nil) nil" + "(if (eq xs nil) nil" "(cons (f (car xs)) (map f (cdr xs))))))"; res = true; } else if (strlen(str) == 6 && strncmp(str, "lookup", 6) == 0) { *code = "(define lookup (lambda (x xs)" - "(if (eq xs nil) nil" - "(if (eq (car (car xs)) x)" - "(car (cdr (car xs)))" + "(if (eq xs nil) nil" + "(if (eq (car (car xs)) x)" + "(car (cdr (car xs)))" "(lookup x (cdr xs))))))"; res = true; } else if (strlen(str) == 5 && strncmp(str, "foldr", 5) == 0) { *code = "(define foldr (lambda (f i xs)" - "(if (eq xs nil) i" + "(if (eq xs nil) i" "(f (car xs) (foldr f i (cdr xs))))))"; res = true; } else if (strlen(str) == 5 && strncmp(str, "foldl", 5) == 0) { @@ -212,7 +212,7 @@ LBM_EXTENSION(ext_numbers, args, argn) { break; } } - return lbm_enc_sym(b ? SYM_TRUE : SYM_NIL); + return lbm_enc_sym(b ? SYM_TRUE : SYM_NIL); } @@ -225,7 +225,7 @@ int main(int argc, char **argv) { // bool compress_decompress = false; bool stream_source = false; - + pthread_t lispbm_thd; lbm_cons_t *heap_storage = NULL; @@ -378,7 +378,7 @@ int main(int argc, char **argv) { 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); @@ -427,6 +427,11 @@ int main(int argc, char **argv) { //lbm_create_char_stream_from_string(&string_tok_state, // &string_tok, // code_buffer); + + lbm_pause_eval_with_gc(20); + while (lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) { + sleep_callback(1000); + } if (stream_source) { lbm_create_buffered_char_channel(&buffered_tok_state, &string_tok); @@ -455,7 +460,7 @@ int main(int argc, char **argv) { break; } int ch_res = lbm_channel_write(&string_tok, code_buffer[i]); - + if (ch_res == CHANNEL_SUCCESS) { //printf("wrote: %c\n", code_buffer[i]); i ++;