mirror of https://github.com/rusefi/bldc.git
Squashed 'lispBM/lispBM/' changes from c53ee21f..c1b12e9d
c1b12e9d Fix bug: Attempt GC if creation of a symbol fails. Also added error reasons to string extensions and changed some eval_errors to type_error 141e7fb1 update lbmref ae677d30 added a section about flash directives and functions in flash memory git-subtree-dir: lispBM/lispBM git-subtree-split: c1b12e9d2e30d6d6f611ed0edf905b067a43c9ac
This commit is contained in:
parent
7b5d568437
commit
7bbb5e9f26
|
@ -45,6 +45,8 @@ Note that the global environment is not "saved" in the same way inside the closu
|
||||||
Currently no (efficient) solution in mind for this gotcha. Just be careful if you use `undefine`.
|
Currently no (efficient) solution in mind for this gotcha. Just be careful if you use `undefine`.
|
||||||
|
|
||||||
|
|
||||||
|
## Flash memory
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
142
doc/lbmref.md
142
doc/lbmref.md
|
@ -953,68 +953,6 @@ Example that evaluates to 20:
|
||||||
```
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
### @const-start
|
|
||||||
|
|
||||||
`@const-start` opens a block of code where each global definition is
|
|
||||||
moved to constant memory (flash) automatically. This can be used only together with the
|
|
||||||
incremental reader (such as `read-eval-program`).
|
|
||||||
|
|
||||||
A `@const-start` opened block should be closed with a `@const-end`. Constant blocks
|
|
||||||
cannot be nested.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```clj
|
|
||||||
@const-start
|
|
||||||
|
|
||||||
(defun f (x) (+ x 1)) ; a function stored in constant memory
|
|
||||||
|
|
||||||
@const-end
|
|
||||||
|
|
||||||
(+ f 2)
|
|
||||||
```
|
|
||||||
|
|
||||||
### @const-end
|
|
||||||
|
|
||||||
`@const-end` closes an block opened by `@const-start`.
|
|
||||||
|
|
||||||
|
|
||||||
### move-to-flash
|
|
||||||
|
|
||||||
A value can be moved to flash storage to save space on the normal evaluation heap or lbm memory.
|
|
||||||
A `move-to-flash` expression is of the form `(move-to-flash sym opt-sym1 ... opt-symN)`.
|
|
||||||
The symbols `sym`, `opt-sym1 ... opt-symN` should be globally bound to the values you want moved
|
|
||||||
to flash. After the value has been moved, the environment binding is updated to point into flash
|
|
||||||
memory. **CAUTION** This function should be used carefully. Ideally a value should be moved
|
|
||||||
to flash immediately after it is created so there is no chance that other references to original value
|
|
||||||
exists.
|
|
||||||
|
|
||||||
Example that moves an array to flash storage:
|
|
||||||
|
|
||||||
```clj
|
|
||||||
(define a [1 2 3 4 5 6])
|
|
||||||
|
|
||||||
(move-to-flash a)
|
|
||||||
```
|
|
||||||
|
|
||||||
Example that moves a list to flash storage:
|
|
||||||
|
|
||||||
```clj
|
|
||||||
(define ls '(1 2 3 4 5))
|
|
||||||
|
|
||||||
(move-to-flash ls)
|
|
||||||
```
|
|
||||||
|
|
||||||
Functions can be moved to flash storage as well:
|
|
||||||
|
|
||||||
```clj
|
|
||||||
(defun f (x) (+ x 1))
|
|
||||||
|
|
||||||
(move-to-flash f)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Lists and cons cells
|
## Lists and cons cells
|
||||||
|
|
||||||
Lists are built using cons cells. A cons cell is represented by the lbm_cons_t struct in the
|
Lists are built using cons cells. A cons cell is represented by the lbm_cons_t struct in the
|
||||||
|
@ -1897,6 +1835,86 @@ The `variable_not_bound` symbol is returned when evaluating a
|
||||||
variable (symbol) that is neighter bound nor special (built-in function).
|
variable (symbol) that is neighter bound nor special (built-in function).
|
||||||
|
|
||||||
|
|
||||||
|
## Flash memory
|
||||||
|
|
||||||
|
Flash memory can be used to store data and functions that are constant.
|
||||||
|
Things can be moved to flash explicitly using the `move-to-flash` function
|
||||||
|
or as part of the reading procedure. To move things automatically to flash during
|
||||||
|
reading, there are `@`directives.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### @const-symbol-strings
|
||||||
|
|
||||||
|
if `@const-symbol-strings` directive is placed in a file, symbols will be created
|
||||||
|
in flash memory instead of the arrays memory.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### @const-start
|
||||||
|
|
||||||
|
`@const-start` opens a block of code where each global definition is
|
||||||
|
moved to constant memory (flash) automatically. This can be used only together with the
|
||||||
|
incremental reader (such as `read-eval-program`).
|
||||||
|
|
||||||
|
A `@const-start` opened block should be closed with a `@const-end`. Constant blocks
|
||||||
|
cannot be nested.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
@const-start
|
||||||
|
|
||||||
|
(defun f (x) (+ x 1)) ; a function stored in constant memory
|
||||||
|
|
||||||
|
@const-end
|
||||||
|
|
||||||
|
(+ f 2)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### @const-end
|
||||||
|
|
||||||
|
`@const-end` closes an block opened by `@const-start`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### move-to-flash
|
||||||
|
|
||||||
|
A value can be moved to flash storage to save space on the normal evaluation heap or lbm memory.
|
||||||
|
A `move-to-flash` expression is of the form `(move-to-flash sym opt-sym1 ... opt-symN)`.
|
||||||
|
The symbols `sym`, `opt-sym1 ... opt-symN` should be globally bound to the values you want moved
|
||||||
|
to flash. After the value has been moved, the environment binding is updated to point into flash
|
||||||
|
memory. **CAUTION** This function should be used carefully. Ideally a value should be moved
|
||||||
|
to flash immediately after it is created so there is no chance that other references to original value
|
||||||
|
exists.
|
||||||
|
|
||||||
|
Example that moves an array to flash storage:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(define a [1 2 3 4 5 6])
|
||||||
|
|
||||||
|
(move-to-flash a)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example that moves a list to flash storage:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(define ls '(1 2 3 4 5))
|
||||||
|
|
||||||
|
(move-to-flash ls)
|
||||||
|
```
|
||||||
|
|
||||||
|
Functions can be moved to flash storage as well:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(defun f (x) (+ x 1))
|
||||||
|
|
||||||
|
(move-to-flash f)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Types
|
## Types
|
||||||
|
|
||||||
|
|
|
@ -3102,6 +3102,10 @@ static void cont_read_next_token(eval_context_t *ctx) {
|
||||||
r = lbm_add_symbol_flash(tokpar_sym_str, &symbol_id);
|
r = lbm_add_symbol_flash(tokpar_sym_str, &symbol_id);
|
||||||
} else {
|
} else {
|
||||||
r = lbm_add_symbol(tokpar_sym_str, &symbol_id);
|
r = lbm_add_symbol(tokpar_sym_str, &symbol_id);
|
||||||
|
if (!r) {
|
||||||
|
gc();
|
||||||
|
r = lbm_add_symbol(tokpar_sym_str, &symbol_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|
|
@ -43,12 +43,16 @@ static size_t strlen_max(const char *s, size_t maxlen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static lbm_value ext_str_from_n(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_from_n(lbm_value *args, lbm_uint argn) {
|
||||||
if ((argn != 1 && argn != 2) || !lbm_is_number(args[0])) {
|
if (argn != 1 && argn != 2) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
if (!lbm_is_number(args[0])) {
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (argn == 2 && !lbm_is_array_r(args[1])) {
|
if (argn == 2 && !lbm_is_array_r(args[1])) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *format = 0;
|
char *format = 0;
|
||||||
|
@ -97,7 +101,7 @@ static lbm_value ext_str_merge(lbm_value *args, lbm_uint argn) {
|
||||||
if (str) {
|
if (str) {
|
||||||
len_tot += strlen(str);
|
len_tot += strlen(str);
|
||||||
} else {
|
} else {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,18 +121,19 @@ static lbm_value ext_str_merge(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_to_i(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_to_i(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 1 && argn != 2) {
|
if (argn != 1 && argn != 2) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = lbm_dec_str(args[0]);
|
char *str = lbm_dec_str(args[0]);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int base = 0;
|
int base = 0;
|
||||||
if (argn == 2) {
|
if (argn == 2) {
|
||||||
if (!lbm_is_number(args[1])) {
|
if (!lbm_is_number(args[1])) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = (int)lbm_dec_as_u32(args[1]);
|
base = (int)lbm_dec_as_u32(args[1]);
|
||||||
|
@ -139,12 +144,13 @@ static lbm_value ext_str_to_i(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_to_f(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_to_f(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 1) {
|
if (argn != 1) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = lbm_dec_str(args[0]);
|
char *str = lbm_dec_str(args[0]);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lbm_enc_float(strtof(str, NULL));
|
return lbm_enc_float(strtof(str, NULL));
|
||||||
|
@ -152,12 +158,13 @@ static lbm_value ext_str_to_f(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_part(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_part(lbm_value *args, lbm_uint argn) {
|
||||||
if ((argn != 2 && argn != 3) || !lbm_is_number(args[1])) {
|
if ((argn != 2 && argn != 3) || !lbm_is_number(args[1])) {
|
||||||
return ENC_SYM_EERROR;
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = lbm_dec_str(args[0]);
|
char *str = lbm_dec_str(args[0]);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t len = (uint32_t)strlen(str);
|
uint32_t len = (uint32_t)strlen(str);
|
||||||
|
@ -171,7 +178,7 @@ static lbm_value ext_str_part(lbm_value *args, lbm_uint argn) {
|
||||||
uint32_t n = len - start;
|
uint32_t n = len - start;
|
||||||
if (argn == 3) {
|
if (argn == 3) {
|
||||||
if (!lbm_is_number(args[2])) {
|
if (!lbm_is_number(args[2])) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = MIN(lbm_dec_as_u32(args[2]), n);
|
n = MIN(lbm_dec_as_u32(args[2]), n);
|
||||||
|
@ -190,12 +197,13 @@ static lbm_value ext_str_part(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_split(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_split(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 2) {
|
if (argn != 2) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str = lbm_dec_str(args[0]);
|
char *str = lbm_dec_str(args[0]);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *split = lbm_dec_str(args[1]);
|
char *split = lbm_dec_str(args[1]);
|
||||||
|
@ -204,7 +212,7 @@ static lbm_value ext_str_split(lbm_value *args, lbm_uint argn) {
|
||||||
if (lbm_is_number(args[1])) {
|
if (lbm_is_number(args[1])) {
|
||||||
step = MAX(lbm_dec_as_i32(args[1]), 1);
|
step = MAX(lbm_dec_as_i32(args[1]), 1);
|
||||||
} else {
|
} else {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +268,7 @@ static lbm_value ext_str_split(lbm_value *args, lbm_uint argn) {
|
||||||
// Todo: Clean this up for 64bit
|
// Todo: Clean this up for 64bit
|
||||||
static lbm_value ext_str_replace(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_replace(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 2 && argn != 3) {
|
if (argn != 2 && argn != 3) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,6 +340,7 @@ static lbm_value ext_str_replace(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_to_lower(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_to_lower(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 1) {
|
if (argn != 1) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,6 +365,7 @@ static lbm_value ext_str_to_lower(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_str_to_upper(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_str_to_upper(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn != 1) {
|
if (argn != 1) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,12 +396,12 @@ static lbm_value ext_str_cmp(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
char *str1 = lbm_dec_str(args[0]);
|
char *str1 = lbm_dec_str(args[0]);
|
||||||
if (!str1) {
|
if (!str1) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str2 = lbm_dec_str(args[1]);
|
char *str2 = lbm_dec_str(args[1]);
|
||||||
if (!str2) {
|
if (!str2) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = -1;
|
int n = -1;
|
||||||
|
@ -467,12 +478,13 @@ static lbm_value ext_to_str(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
static lbm_value ext_to_str_delim(lbm_value *args, lbm_uint argn) {
|
static lbm_value ext_to_str_delim(lbm_value *args, lbm_uint argn) {
|
||||||
if (argn < 1) {
|
if (argn < 1) {
|
||||||
|
lbm_set_error_reason((char*)lbm_error_str_num_args);
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_EERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *delim = lbm_dec_str(args[0]);
|
char *delim = lbm_dec_str(args[0]);
|
||||||
if (!delim) {
|
if (!delim) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return to_str(delim, args + 1, argn - 1);
|
return to_str(delim, args + 1, argn - 1);
|
||||||
|
@ -483,7 +495,7 @@ static lbm_value ext_str_len(lbm_value *args, lbm_uint argn) {
|
||||||
|
|
||||||
char *str = lbm_dec_str(args[0]);
|
char *str = lbm_dec_str(args[0]);
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ENC_SYM_EERROR;
|
return ENC_SYM_TERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
|
lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(args[0]);
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
(defun repeat_eval (c n)
|
||||||
|
(if ( = n 0)
|
||||||
|
()
|
||||||
|
(progn
|
||||||
|
(c n)
|
||||||
|
(bufcreate 10)
|
||||||
|
(repeat_eval c (- n 1)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(defun code (x) (def apa (eval `(read (str-merge "bepa" (str-from-n x))))))
|
||||||
|
|
||||||
|
; Create just enough symbols and symbols and arrays to trigger GC.
|
||||||
|
(repeat_eval code 432)
|
||||||
|
|
||||||
|
(check (eq apa 'bepa1))
|
Loading…
Reference in New Issue