Merge commit 'dccfe151354c45e77946b6b41a09d97b521c14e4'

This commit is contained in:
Benjamin Vedder 2022-10-06 13:58:38 +02:00
commit 3f2d79394c
7 changed files with 81 additions and 143 deletions

View File

@ -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)

View File

@ -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')

View File

@ -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

View File

@ -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.
*
*/

View File

@ -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;

View File

@ -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);

View File

@ -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 ++;