mirror of https://github.com/rusefi/bldc.git
Updated lispbm, fixed dual motor flash motor stop
This commit is contained in:
commit
8cccadae6a
|
@ -127,10 +127,10 @@ uint16_t flash_helper_erase_new_app(uint32_t new_app_size) {
|
||||||
|
|
||||||
new_app_size += flash_addr[NEW_APP_BASE];
|
new_app_size += flash_addr[NEW_APP_BASE];
|
||||||
|
|
||||||
mc_interface_release_motor_override();
|
|
||||||
mc_interface_ignore_input_both(5000);
|
mc_interface_ignore_input_both(5000);
|
||||||
|
mc_interface_release_motor_override_both();
|
||||||
|
|
||||||
if (!mc_interface_wait_for_motor_release(3.0)) {
|
if (!mc_interface_wait_for_motor_release_both(3.0)) {
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,10 +375,10 @@ static uint16_t erase_sector(uint32_t sector) {
|
||||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||||
|
|
||||||
mc_interface_release_motor_override();
|
|
||||||
mc_interface_ignore_input_both(5000);
|
mc_interface_ignore_input_both(5000);
|
||||||
|
mc_interface_release_motor_override_both();
|
||||||
|
|
||||||
if (!mc_interface_wait_for_motor_release(3.0)) {
|
if (!mc_interface_wait_for_motor_release_both(3.0)) {
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ static uint16_t erase_sector(uint32_t sector) {
|
||||||
|
|
||||||
FLASH_Lock();
|
FLASH_Lock();
|
||||||
timeout_configure_IWDT();
|
timeout_configure_IWDT();
|
||||||
mc_interface_ignore_input_both(5000);
|
mc_interface_ignore_input_both(1000);
|
||||||
utils_sys_unlock_cnt();
|
utils_sys_unlock_cnt();
|
||||||
|
|
||||||
return FLASH_COMPLETE;
|
return FLASH_COMPLETE;
|
||||||
|
@ -408,10 +408,10 @@ static uint16_t write_data(uint32_t base, uint8_t *data, uint32_t len) {
|
||||||
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
FLASH_ClearFlag(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |
|
||||||
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
|
||||||
|
|
||||||
mc_interface_release_motor_override();
|
|
||||||
mc_interface_ignore_input_both(5000);
|
mc_interface_ignore_input_both(5000);
|
||||||
|
mc_interface_release_motor_override_both();
|
||||||
|
|
||||||
if (!mc_interface_wait_for_motor_release(3.0)) {
|
if (!mc_interface_wait_for_motor_release_both(3.0)) {
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -598,7 +598,7 @@ The following example shows how to spawn a thread that handles SID (standard-id)
|
||||||
)))
|
)))
|
||||||
|
|
||||||
; Spawn the event handler thread and pass the ID it returns to C
|
; Spawn the event handler thread and pass the ID it returns to C
|
||||||
(event-register-handler (spawn '(event-handler)))
|
(event-register-handler (spawn event-handler))
|
||||||
|
|
||||||
; Enable the CAN event for standard ID (SID) frames
|
; Enable the CAN event for standard ID (SID) frames
|
||||||
(event-enable "event-can-sid")
|
(event-enable "event-can-sid")
|
||||||
|
|
|
@ -67,9 +67,8 @@ There are [demonstrations on YouTube](https://youtube.com/playlist?list=PLtf_3Ta
|
||||||
17. (DONE) Rename files with names that may conflict with common stuff (memory.h, memory.c).
|
17. (DONE) Rename files with names that may conflict with common stuff (memory.h, memory.c).
|
||||||
18. (DONE) It should be possible to reset the runtime system.
|
18. (DONE) It should be possible to reset the runtime system.
|
||||||
19. (DONE) Add messages to lisp process mailbox from C to unlock blocked proc.
|
19. (DONE) Add messages to lisp process mailbox from C to unlock blocked proc.
|
||||||
20. Make uniform how to return success or failure. It is sometimes bool and sometimes int right now.
|
20. Spawn closures specifically instead of expressions in general.
|
||||||
21. Spawn closures specifically instead of expressions in general.
|
21. Implement some looping structure for speed or just ease of use.
|
||||||
22. Implement some looping structure for speed or just ease of use.
|
|
||||||
|
|
||||||
## Vague or continuosly ongoing todos
|
## Vague or continuosly ongoing todos
|
||||||
1. Doxygen?
|
1. Doxygen?
|
||||||
|
@ -77,9 +76,8 @@ There are [demonstrations on YouTube](https://youtube.com/playlist?list=PLtf_3Ta
|
||||||
3. Be much more stringent on checking of error conditions etc.
|
3. Be much more stringent on checking of error conditions etc.
|
||||||
4. More built in arithmetic.
|
4. More built in arithmetic.
|
||||||
5. More built in comparisons.
|
5. More built in comparisons.
|
||||||
|
6. Make uniform how to return success or failure. It is sometimes bool and sometimes int right now.
|
||||||
|
|
||||||
## Very platform dependent TODOs
|
|
||||||
1. Save images (heap + symbol memory) to flash or sd-card.
|
|
||||||
|
|
||||||
## Compile for linux (Requires 32bit libraries. May need something like "multilib" on a 64bit linux)
|
## Compile for linux (Requires 32bit libraries. May need something like "multilib" on a 64bit linux)
|
||||||
1. Build the library: `make`
|
1. Build the library: `make`
|
||||||
|
|
|
@ -137,6 +137,7 @@ LBMSRC = ../../src/compression.c \
|
||||||
../../src/symrepr.c \
|
../../src/symrepr.c \
|
||||||
../../src/tokpar.c \
|
../../src/tokpar.c \
|
||||||
../../src/lispbm.c \
|
../../src/lispbm.c \
|
||||||
|
../../src/lbm_c_interop.c \
|
||||||
../../platform/chibios/src/platform_mutex.c
|
../../platform/chibios/src/platform_mutex.c
|
||||||
|
|
||||||
CSRC = $(ALLCSRC) \
|
CSRC = $(ALLCSRC) \
|
||||||
|
|
|
@ -35,9 +35,13 @@
|
||||||
|
|
||||||
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
#define HEAP_SIZE 2048
|
#define HEAP_SIZE 2048
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
||||||
|
|
||||||
static uint32_t memory_array[LBM_MEMORY_SIZE_8K];
|
static uint32_t memory_array[LBM_MEMORY_SIZE_8K];
|
||||||
|
@ -196,8 +200,10 @@ int main(void) {
|
||||||
chThdSleepMilliseconds(2000);
|
chThdSleepMilliseconds(2000);
|
||||||
|
|
||||||
if (!lbm_init(heap, HEAP_SIZE,
|
if (!lbm_init(heap, HEAP_SIZE,
|
||||||
memory_array, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K)) {
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE)) {
|
||||||
chprintf(chp,"LispBM Init failed.\r\n");
|
chprintf(chp,"LispBM Init failed.\r\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -306,8 +312,10 @@ int main(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_init(heap, HEAP_SIZE,
|
lbm_init(heap, HEAP_SIZE,
|
||||||
memory_array, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K);
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_add_extension("print", ext_print);
|
lbm_add_extension("print", ext_print);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
File, Load time (s), Eval time (s), GC avg time (us), GC min time (us), GC max time (us), GC invocations, GC least free
|
||||||
|
q2.lisp, 0.001799999, 1.817800045, 616.470581054, 600, 700, 85, 1931
|
||||||
|
dec_cnt2.lisp, 0.001099999, 3.414499998, 510.738250732, 500, 600, 149, 2011
|
||||||
|
dec_cnt1.lisp, 0.001099999, 4.270999908, 513.422790527, 500, 600, 149, 2012
|
||||||
|
fibonacci.lisp, 0.001200000, 4.533899784, 562.857116699, 500, 600, 140, 1966
|
||||||
|
dec_cnt3.lisp, 0.001399999, 1.554200053, 538.095214843, 500, 600, 21, 1994
|
||||||
|
tak.lisp, 0.001900000, 4.262000083, 641.666687011, 600, 700, 300, 1890
|
||||||
|
fibonacci_tail.lisp, 0.001900000, 0.005299999, 0.000000000, 4294967295, 0, 0, 2048
|
||||||
|
insertionsort.lisp, 0.002799999, 0.006099999, 0.000000000, 4294967295, 0, 0, 2048
|
|
@ -29,9 +29,13 @@
|
||||||
|
|
||||||
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
#define HEAP_SIZE 2048
|
#define HEAP_SIZE 2048
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
||||||
|
|
||||||
static uint32_t memory_array[LBM_MEMORY_SIZE_8K];
|
static uint32_t memory_array[LBM_MEMORY_SIZE_8K];
|
||||||
|
@ -188,8 +192,10 @@ int main(void) {
|
||||||
chThdSleepMilliseconds(2000);
|
chThdSleepMilliseconds(2000);
|
||||||
|
|
||||||
if (!lbm_init(heap, HEAP_SIZE,
|
if (!lbm_init(heap, HEAP_SIZE,
|
||||||
memory_array, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K)) {
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE)) {
|
||||||
chprintf(chp,"LispBM Init failed.\r\n");
|
chprintf(chp,"LispBM Init failed.\r\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -298,8 +304,10 @@ int main(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_init(heap, HEAP_SIZE,
|
lbm_init(heap, HEAP_SIZE,
|
||||||
memory_array, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K);
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_add_extension("print", ext_print);
|
lbm_add_extension("print", ext_print);
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,14 @@
|
||||||
|
|
||||||
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
#define EVAL_WA_SIZE THD_WORKING_AREA_SIZE(1024)
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
|
|
||||||
#define HEAP_SIZE 8192
|
#define HEAP_SIZE 8192
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[256];
|
||||||
|
uint32_t print_stack_storage[256];
|
||||||
|
|
||||||
lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
||||||
|
|
||||||
static lbm_tokenizer_string_state_t string_tok_state;
|
static lbm_tokenizer_string_state_t string_tok_state;
|
||||||
|
@ -316,8 +321,10 @@ int main(void) {
|
||||||
|
|
||||||
|
|
||||||
if (!lbm_init(heap, HEAP_SIZE,
|
if (!lbm_init(heap, HEAP_SIZE,
|
||||||
memory_array, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K)) {
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE)) {
|
||||||
chprintf(chp,"Initializing LispBM failed\r\n");
|
chprintf(chp,"Initializing LispBM failed\r\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -406,7 +413,7 @@ int main(void) {
|
||||||
chprintf(chp, "received %d bytes\r\n", strlen(file_buffer));
|
chprintf(chp, "received %d bytes\r\n", strlen(file_buffer));
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
lbm_value t;
|
//lbm_value t;
|
||||||
|
|
||||||
lbm_create_char_stream_from_string(&string_tok_state,
|
lbm_create_char_stream_from_string(&string_tok_state,
|
||||||
&string_tok,
|
&string_tok,
|
||||||
|
|
|
@ -1,9 +1,74 @@
|
||||||
/** \page lbmdoc Introduction to LispBM programming
|
/** \page lbmdoc Introduction to LispBM programming
|
||||||
\tableofcontents
|
\tableofcontents
|
||||||
|
|
||||||
|
|
||||||
\section sec_intro Introduction
|
\section sec_intro Introduction
|
||||||
|
|
||||||
|
LispBM is a lisp-like language implemented by a non-lisper. The inspiration for LispBM came from watching the <a
|
||||||
|
href="https://www.youtube.com/watch?v=-J_xL4IGhJA&list=PLE18841CABEA24090">
|
||||||
|
SICP course on youtube </a> and a tiny amount of experimenting with EMACS
|
||||||
|
lisp. I strongly recommend that you watch the SICP course, it is a lot of fun!<br>
|
||||||
|
|
||||||
|
LispBM does not try to implement any particular Lisp or Scheme standard but may
|
||||||
|
be more scheme-like in nature.
|
||||||
|
|
||||||
|
|
||||||
|
\section sec_repl Using a REPL
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :info
|
||||||
|
--(LISP HEAP)-----------------------------------------------
|
||||||
|
Heap size: 16384 Bytes
|
||||||
|
Used cons cells: 11
|
||||||
|
Free cons cells: 2037
|
||||||
|
GC counter: 0
|
||||||
|
Recovered: 0
|
||||||
|
Recovered arrays: 0
|
||||||
|
Marked: 0
|
||||||
|
--(Symbol and Array memory)---------------------------------
|
||||||
|
Memory size: 2048 Words
|
||||||
|
Memory free: 2024 Words
|
||||||
|
Allocated arrays: 0
|
||||||
|
Symbol table size: 40 Bytes
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :env
|
||||||
|
Environment:
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :ctxs
|
||||||
|
****** Running contexts ******
|
||||||
|
****** Blocked contexts ******
|
||||||
|
****** Done contexts ******
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :pause
|
||||||
|
Evaluator paused
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :step
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :step 10
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\code
|
||||||
|
# :continue
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\section sec_program A first program
|
||||||
|
|
||||||
|
\section sec_c Integration into C code
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -49,7 +49,7 @@ Multiplying an arbitrary number of values. The form of a * expression is
|
||||||
\note
|
\note
|
||||||
Example 2pi.
|
Example 2pi.
|
||||||
\code
|
\code
|
||||||
(* 2 3.14)
|
(* 2 3.14)
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,16 +69,17 @@ The following example evaluates to 1.
|
||||||
(/ 128 2 2 2 2 2 2 2)
|
(/ 128 2 2 2 2 2 2 2)
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="mod"> <h3>mod</h3> </a>
|
<a name="mod"> <h3>mod</h3> </a>
|
||||||
|
|
||||||
Modulo operation. The form of a mod expression is <code>(mode expr1 ... exprN)</code>.
|
Modulo operation. The form of a mod expression is <code>(mod expr1 ... exprN)</code>.
|
||||||
|
|
||||||
\note
|
\note
|
||||||
Compute 5 % 3, evaluates to 2.
|
Compute 5 % 3, evaluates to 2.
|
||||||
\code
|
\code
|
||||||
(mod 5 3)
|
(mod 5 3)
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,17 +169,176 @@ Example
|
||||||
|
|
||||||
<a name="and"> <h3>and</h3> </a>
|
<a name="and"> <h3>and</h3> </a>
|
||||||
|
|
||||||
|
Boolean <code>and</code> operation between n arguments. The form
|
||||||
|
of an <code>and</code> expression is <code>(and expr1 ... exprN)</code>.
|
||||||
|
This operation treats all non-nil values as true. Boolean <code>and</code>
|
||||||
|
is "shirt-circuiting" and only evaluates until a false is encountered.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The example below evaluates to <code>t</code>
|
||||||
|
\code
|
||||||
|
(and t t)
|
||||||
|
\endcode
|
||||||
|
The folowing example evaluates to 3
|
||||||
|
\code
|
||||||
|
(and t t (+ 1 2))
|
||||||
|
\endcode
|
||||||
|
And lastly an example that evaluates to nil (for false).
|
||||||
|
\code
|
||||||
|
(and t (< 5 3))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="or"> <h3>or</h3> </a>
|
<a name="or"> <h3>or</h3> </a>
|
||||||
|
|
||||||
|
Boolean <code>or</code> operation between n arguments. The form
|
||||||
|
of an <code>or</code> expression is <code>(or expr1 ... exprN)</code>.
|
||||||
|
This operation treats all non-nil values as true. Boolean <code>or</code>
|
||||||
|
is "short-circuiting" and only evaluates until a true is encountered.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The example below evaluates to <code>t</code>.
|
||||||
|
\code
|
||||||
|
(or t nil)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="not"> <h3>not</h3> </a>
|
<a name="not"> <h3>not</h3> </a>
|
||||||
|
|
||||||
|
Boolean <code>not</code> takes one argument. The form of a <code>not</code>
|
||||||
|
expression is <code>(not expr)</code>. All non-nil values are considered
|
||||||
|
true.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The following example evaluates to <code>t</code>
|
||||||
|
\code
|
||||||
|
(not nil)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
\section sec_bitwise Bit level operations
|
||||||
|
|
||||||
|
<a name="shl"><h3>shl</h3></a>
|
||||||
|
|
||||||
|
The shift left operation takes two arguments. The first argument is a value to shift and the
|
||||||
|
second argument is the number of bit positions to shift the value.
|
||||||
|
\note
|
||||||
|
The example below evaluates to 4.
|
||||||
|
\code
|
||||||
|
(shl 1 2)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<a name="shr"><h3>shr</h3></a>
|
||||||
|
|
||||||
|
The shift right operation takes two arguments. The first argument is a value to shift and the
|
||||||
|
second argument in the number of bit positions to shift the value.
|
||||||
|
\note
|
||||||
|
The example below evaluates to 1.
|
||||||
|
\code
|
||||||
|
(shr 4 2)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<a name="bitwise-and"><h3>bitwise-and</h3></a>
|
||||||
|
|
||||||
|
Performs the bitwise and operation between two values. The type of the result
|
||||||
|
is the same type as the first of the arguments.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<a name="bitwise-or"><h3>bitwise-or</h3></a>
|
||||||
|
|
||||||
|
Performs the bitwise or operation between two values. The type of the result
|
||||||
|
is the same type as the first of the arguments.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
<a name="bitwise-xor"><h3>bitwise-xor</h3></a>
|
||||||
|
|
||||||
|
Performs the bitwise xor operation between two values. The type of the result
|
||||||
|
is the same type as the first of the arguments.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="bitwise-not"><h3>bitwise-not</h3></a>
|
||||||
|
|
||||||
|
Performs the bitwise not operations on a value. The result is of same type as
|
||||||
|
the argument.
|
||||||
|
|
||||||
|
\section sec_low_level Low level operations
|
||||||
|
|
||||||
|
<a name="encode-i32"> <h3>encode-i32</h3> </a>
|
||||||
|
|
||||||
|
The <code>encode-i32</code> function converts a list of four (byte sized) values
|
||||||
|
into an i32 value.
|
||||||
|
\note
|
||||||
|
Example that evaluates to the i32 value 1024.
|
||||||
|
\code
|
||||||
|
(encode-i32 (list 0 0 4 0))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="encode-u32"> <h3>encode-u32</h3> </a>
|
||||||
|
|
||||||
|
The <code>encode-u32</code> function converts a list of four (byte sized) values
|
||||||
|
into an u32 value.
|
||||||
|
\note
|
||||||
|
Example that evaluates to the u32 value 1024.
|
||||||
|
\code
|
||||||
|
(encode-u32 (list 0 0 4 0))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="encode-float"> <h3>encode-float</h3> </a>
|
||||||
|
|
||||||
|
The <code>encode-float</code> function converts a list four (byte sized) values
|
||||||
|
into a float value.
|
||||||
|
\note
|
||||||
|
Example that evaluates to 3.14.
|
||||||
|
\code
|
||||||
|
(encode-float (list 64 72 245 195))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="decode"> <h3>decode</h3> </a>
|
||||||
|
|
||||||
|
The <code>decode</code> function decodes a value into a list of four (byte sized) values.
|
||||||
|
\note
|
||||||
|
Example that decodes float 3.14 into the list (64 72 245 195).
|
||||||
|
\code
|
||||||
|
(decode 3.14)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section sec_nil nil and t
|
\section sec_nil nil and t
|
||||||
|
|
||||||
<a name="nil"><h3>nil</h3></a>
|
<a name="nil"><h3>nil</h3></a>
|
||||||
|
@ -203,9 +363,15 @@ explicit true makes sense.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
\section sec_forms Special forms
|
\section sec_quote Quotes and Quasiquotation
|
||||||
|
|
||||||
<a name="quote"> <h3>quote</h3> </a>
|
Code and data share the same representation, it is only a matter of how
|
||||||
|
you look at it. The tools for changing how your view are the quotation and
|
||||||
|
quasiquotation operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="'"><h3>'</h3></a> <a name="quote"></a>
|
||||||
|
|
||||||
Usages of the ' quote symbol in input code is replaced with the symbol quote
|
Usages of the ' quote symbol in input code is replaced with the symbol quote
|
||||||
by the reader. <br>
|
by the reader. <br>
|
||||||
|
@ -214,9 +380,154 @@ Evaluating a quoted expression, (quote a), results in a unevaluated.<br>
|
||||||
The program string <code>'(+ 1 2) </code> gets read into the heap as the list <code>(quote (+ 1 2))</code>.<br>
|
The program string <code>'(+ 1 2) </code> gets read into the heap as the list <code>(quote (+ 1 2))</code>.<br>
|
||||||
Evaluating the expression <code>(quote (+ 1 2))</code> results in the value <code>(+ 1 2)</code>.
|
Evaluating the expression <code>(quote (+ 1 2))</code> results in the value <code>(+ 1 2)</code>.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="`"><h3>`</h3></a>
|
||||||
|
|
||||||
|
The backwards tick <code>`</code> is called the quasiquote. It is similar to the <code>'</code> but
|
||||||
|
allows splicing in results of computations using the <a href="#,">,</a> and the <a href="#commaat">,\@</a>
|
||||||
|
operators.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The result of <code>'(+ 1 2)</code> and <code>`(+ 1 2)</code> are similar in
|
||||||
|
effect. Both result in the result value of <code>(+ 1 2)</code>, that is a list containing
|
||||||
|
+, 1 and 2. <br>
|
||||||
|
When <code>`(+ 1 2)</code> is read into the heap it is expanded into the
|
||||||
|
expression <code>(append (quote (+)) (append (quote (1)) (append (quote (2)) (quote nil))))</code>
|
||||||
|
which evaluates to the list <code>(+ 1 2)</code>.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<a name=","><h3>,</h3></a>
|
||||||
|
|
||||||
|
The comma is used to splice the result of a computation into a quasiquotation.
|
||||||
|
\note
|
||||||
|
The expression <code>`(+ 1 ,(+ 1 1))</code> is expanded by the reader into
|
||||||
|
<code>(append (quote (+)) (append (quote (1)) (append (list (+ 1 1)) (quote nil))))</code>.
|
||||||
|
Evaluating the expression above results in the list <code>(+ 1 2)</code>.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="commaat"><h3>,\@</h3></a>
|
||||||
|
|
||||||
|
The comma-at operation is used to splice in the result of a computation (that
|
||||||
|
returns a list) into a list.
|
||||||
|
\note
|
||||||
|
Example:
|
||||||
|
\code
|
||||||
|
(define mylist (list 1 2 3 4 5)
|
||||||
|
`(9 6 5 ,@mylist)
|
||||||
|
\endcode
|
||||||
|
Evaluates to the list <code>(9 6 5 1 2 3 4 5)</code>.
|
||||||
|
|
||||||
|
|
||||||
|
\section sec_builtin Built-in operations
|
||||||
|
|
||||||
|
|
||||||
|
<a name="eval"> <h3>eval</h3> </a>
|
||||||
|
|
||||||
|
Evaluate data as an expression. The data must represent a valid expression.
|
||||||
|
\note
|
||||||
|
Example that evaluates to 3.
|
||||||
|
\code
|
||||||
|
(eval (list + 1 2))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="eval-program"> <h3>eval-program</h3> </a>
|
||||||
|
|
||||||
|
Evaluate a list of data where each element represents an expression.
|
||||||
|
\note
|
||||||
|
This function is quite awkward as it replaces the program in the running
|
||||||
|
context with the program provided in the list. Avoid using this
|
||||||
|
function if possible.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="type-of"> <h3>type-of</h3> </a>
|
||||||
|
|
||||||
|
The <code>type-of</code> function returns a symbol that indicates what type the
|
||||||
|
argument is. The form of a <code>type-of</code> expression is <code>(type-of expr)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that evaluates to <code>type-float</code>.
|
||||||
|
\code
|
||||||
|
(type-of 3.14)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="sym-to-str"> <h3>sym-to-str</h3> </a>
|
||||||
|
|
||||||
|
The <code>sym-to-str</code> function converts a symbol to its string representation.
|
||||||
|
The resulting string is a copy of the original so you cannot destroy built in symbols using
|
||||||
|
this function.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that returns the string <code>"lambda"</code>.
|
||||||
|
\code
|
||||||
|
(sym-to-str 'lambda)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="str-to-sym"> <h3>str-to-sym</h3> </a>
|
||||||
|
|
||||||
|
The <code>str-to-sym</code> function converts a string to a symbol.
|
||||||
|
\note
|
||||||
|
Example that returns the symbol <code>hello</code>.
|
||||||
|
\code
|
||||||
|
(str-to-sym "hello")
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="sym-to-u"> <h3>sym-to-u</h3> </a>
|
||||||
|
|
||||||
|
The <code>sym-to-u</code> function returns the numerical value used by the runtime system
|
||||||
|
for a symbol.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that evaluates to 4.
|
||||||
|
\code
|
||||||
|
(sym-to-u 'lambda)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="u-to-sym"> <h3>u-to-sym</h3> </a>
|
||||||
|
|
||||||
|
The <code>u-to-sym</code> function returns the symbol associated with the
|
||||||
|
numerical value provided. This symbol may be undefined in which case you
|
||||||
|
get as result a unnamed symbol.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="is-fundamental"> <h3>is-fundamental</h3> </a>
|
||||||
|
|
||||||
|
The <code>is-funamental</code> function returns true for built-in functions.
|
||||||
|
\note
|
||||||
|
Example that returns true.
|
||||||
|
\code
|
||||||
|
(is-fundamental '+)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
\section sec_forms Special forms
|
||||||
|
|
||||||
|
|
||||||
<a name="if"> <h3>if</h3> </a>
|
<a name="if"> <h3>if</h3> </a>
|
||||||
|
|
||||||
Conditionals are written as <code>(if cond-expr then-expr else-expr)</code>.
|
Conditionals are written as <code>(if cond-expr then-expr else-expr)</code>.
|
||||||
|
@ -399,38 +710,165 @@ has been extended with the binding <code>(apa 1)</code>.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
\section sec_lists Lists
|
\section sec_lists Lists and cons cells
|
||||||
|
|
||||||
|
Lists are build using cons cells. A cons cell is represented by the \ref lbm_cons_t struct in the
|
||||||
|
implementation and consists of two fields named the <code>car</code> and the <code>cdr</code>.
|
||||||
|
There is no special meaning associated with the <code>car</code> and the <code>cdr</code> each can hold
|
||||||
|
a \ref lbm_value. See <a href="#cons">cons</a> and <a href="#list">list</a> for two ways to create structures of
|
||||||
|
cons cells on the heap.
|
||||||
|
|
||||||
<a name="car"> <h3>car</h3> </a>
|
<a name="car"> <h3>car</h3> </a>
|
||||||
|
|
||||||
|
Use <code>car</code> to access the <code>car</code> field of a cons cell. A
|
||||||
|
<code>car</code> expression has the form <code>(car expr)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Taking the <code>car</code> of a number of symbol type is in general a <a href="#type_error">type_error</a>.
|
||||||
|
The following program results in <code>type_error</code>.
|
||||||
|
\code
|
||||||
|
(car 1)
|
||||||
|
\endcode
|
||||||
|
The next example evaluates to 1.
|
||||||
|
\code
|
||||||
|
(car (cons 1 2))
|
||||||
|
\endcode
|
||||||
|
The <code>car</code> operation accesses the head element of a list. The following program evaluates to 9.
|
||||||
|
\code
|
||||||
|
(car (list 9 8 7))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="cdr"> <h3>cdr</h3> </a>
|
<a name="cdr"> <h3>cdr</h3> </a>
|
||||||
|
|
||||||
|
Use <code>cdr</code> to access the <code>cdr</code> field of a cons cell. A
|
||||||
|
<code>cdr</code> expression has the form <code>(cdr expr)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The example below evaluates to 2.
|
||||||
|
\code
|
||||||
|
(cdr (cons 1 2))
|
||||||
|
\endcode
|
||||||
|
The <code>cdr</code> operation gives you the rest of a list. The example below evaluates to the list (8 7).
|
||||||
|
\code
|
||||||
|
(cdr (list 9 8 7))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="cons"> <h3>cons</h3> </a>
|
<a name="cons"> <h3>cons</h3> </a>
|
||||||
|
|
||||||
|
The <code>cons</code> operation allocates a cons cell from the heap and populates the
|
||||||
|
<code>car</code> and the <code>cdr</code> fields of this cell with its two arguments.
|
||||||
|
The form of a <code>cons</code> expression is <code>(cons expr1 expr2)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Build the list <code>(1 2 3)</code> using cons. <a href="#nil">nil</a> terminates a proper list.
|
||||||
|
\code
|
||||||
|
(cons 1 (cons 2 (cons 3 nil)))
|
||||||
|
\endcode
|
||||||
|
Construct the pair <code>(+ . 1)</code> using cons.
|
||||||
|
\code
|
||||||
|
(cons + 1)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<a name="."> <h3>.</h3> </a>
|
||||||
|
|
||||||
|
The dot, <code>.</code>, operation creates a pair. The form of a dot expression
|
||||||
|
is <code>(expr1 . expr2)</code>. By default the evaluator will attempt to evaluate the
|
||||||
|
result of <code>(expr1 . expr2)</code> unless it is prefixed with <code>'</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that creates the pair (1 . 2)
|
||||||
|
\code
|
||||||
|
'(1 . 2)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="list"> <h3>list</h3> </a>
|
<a name="list"> <h3>list</h3> </a>
|
||||||
|
|
||||||
|
The <code>list</code> function is used to create proper lists. The function
|
||||||
|
takes n arguments and is of the form <code>(list expr1 ... exprN)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that creates the list (1 2 3 4).
|
||||||
|
\code
|
||||||
|
(list 1 2 3 4)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="append"> <h3>append</h3> </a>
|
<a name="append"> <h3>append</h3> </a>
|
||||||
|
|
||||||
|
The <code>append</code> function combines two lists into a longer list.
|
||||||
|
An <code>append</code> expression is of the form <code>(append expr1 expr2)</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that combines to lists.
|
||||||
|
\code
|
||||||
|
(append (list 1 2 3) (list 4 5 6))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="ix"> <h3>ix</h3> </a>
|
<a name="ix"> <h3>ix</h3> </a>
|
||||||
|
|
||||||
|
Index into a list using the <code>ix</code>. the form of an <code>ix</code> expression
|
||||||
|
is <code>(ix index-expr list-expr)</code>. Indexing starts from 0 and if you index out of bounds the result is nil.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that evaluates to 2.
|
||||||
|
\code
|
||||||
|
(ix 1 (list 1 2 3))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="set-car"> <h3>set-car</h3> </a>
|
<a name="set-car"> <h3>set-car</h3> </a>
|
||||||
|
|
||||||
|
The <code>set-car</code> is a destructive update of the car field
|
||||||
|
of a cons-cell.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Define <code>apa</code> to be the pair <code>(1 . 2)</code>
|
||||||
|
\code
|
||||||
|
(define apa '(1 . 2))
|
||||||
|
\endcode
|
||||||
|
Now change the value in the car field of apa to 42.
|
||||||
|
\code
|
||||||
|
(set-car apa 42)
|
||||||
|
\endcode
|
||||||
|
The <code>apa</code> pair is now <code>(42 . 2)</code>.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="set-cdr"> <h3>set-cdr</h3> </a>
|
<a name="set-cdr"> <h3>set-cdr</h3> </a>
|
||||||
|
|
||||||
|
The <code>set-cdr</code> is a destructive update of the cdr field of a cons-cell.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Define <code>apa</code> to be the pair <code>(1 . 2)</code>
|
||||||
|
\code
|
||||||
|
(define apa '(1 . 2))
|
||||||
|
\endcode
|
||||||
|
Now change the value in the cdr field of apa to 42.
|
||||||
|
\code
|
||||||
|
(set-cdr apa 42)
|
||||||
|
\endcode
|
||||||
|
The <code>apa</code> pair is now <code>(1 . 42)</code>.
|
||||||
|
|
||||||
|
|
||||||
\section sec_arrays Arrays
|
\section sec_arrays Arrays
|
||||||
|
@ -438,10 +876,37 @@ has been extended with the binding <code>(apa 1)</code>.
|
||||||
|
|
||||||
<a name="array-read"> <h3>array-read</h3> </a>
|
<a name="array-read"> <h3>array-read</h3> </a>
|
||||||
|
|
||||||
|
Read one or many elements from an array. The form of
|
||||||
|
an <code>array-read</code> expression is either <code>(array-read array-expr index-expr)</code>
|
||||||
|
of <code>(array-read array-expr start-index-expr end-index-expr)</code> for reading a range
|
||||||
|
of values into a list.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that evaluates to the character l.
|
||||||
|
\code
|
||||||
|
(array-read "hello" 3)
|
||||||
|
\endcode
|
||||||
|
The next example reads a range values
|
||||||
|
\code
|
||||||
|
(array-read "hello" 1 3)
|
||||||
|
\endcode
|
||||||
|
and results in the list <code>(\#e \#l \#l)</code>.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="array-write"> <h3>array-write</h3> </a>
|
<a name="array-write"> <h3>array-write</h3> </a>
|
||||||
|
|
||||||
|
The <code>array-write</code> function performs a destructive update
|
||||||
|
of an array.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example that turns array "hello" into "heflo"
|
||||||
|
\code
|
||||||
|
(array-write "hello" 2 \#f)
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
\section sec_pattern Pattern-matching
|
\section sec_pattern Pattern-matching
|
||||||
|
@ -454,7 +919,7 @@ the shape of an expression to each of the <code>pat1</code> ... <code>patN</code
|
||||||
and evaluates the expression <code>exprM</code> of the pattern that matches.
|
and evaluates the expression <code>exprM</code> of the pattern that matches.
|
||||||
In a pattern you can use a number of match-binders or wildcards: <a href="#_">_</a>,
|
In a pattern you can use a number of match-binders or wildcards: <a href="#_">_</a>,
|
||||||
<a href="#?">?</a>, <a href="#?i28">?i28</a>, <a href="#?u28">?u28</a>, <a href="#?float">?float</a>,
|
<a href="#?">?</a>, <a href="#?i28">?i28</a>, <a href="#?u28">?u28</a>, <a href="#?float">?float</a>,
|
||||||
<a href="#?cons">?cons</a>.
|
<a href="#?cons">?cons</a>.
|
||||||
|
|
||||||
\note
|
\note
|
||||||
For example the match expression below evaluates to 2.
|
For example the match expression below evaluates to 2.
|
||||||
|
@ -491,7 +956,7 @@ Using the ? pattern is done as <code>(? var)</code> and the part of the expressi
|
||||||
that matches is bound to <code>var</code>.
|
that matches is bound to <code>var</code>.
|
||||||
|
|
||||||
\note
|
\note
|
||||||
An example that evaluates to 19.
|
An example that evaluates to 19.
|
||||||
\code
|
\code
|
||||||
(match '(orange 17)
|
(match '(orange 17)
|
||||||
((green (? n)) (+ n 1))
|
((green (? n)) (+ n 1))
|
||||||
|
@ -499,21 +964,47 @@ An example that evaluates to 19.
|
||||||
((blue (? n)) (+ n 3)))
|
((blue (? n)) (+ n 3)))
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="?i28"> <h3>?i28</h3> </a>
|
<a name="?i28"> <h3>?i28</h3> </a>
|
||||||
|
|
||||||
|
The ?i28 pattern matches any i28 and binds that value to a variable.
|
||||||
|
Using the ?i28 pattern is done as <code>(?i28 var)</code> and the part of the expression
|
||||||
|
that matches is bound to the <code>var</code>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
The following example evaluates to <code>not-an-i28</code>.
|
||||||
|
\code
|
||||||
|
(match 3.14
|
||||||
|
( (i28 n) (+ n 1))
|
||||||
|
( _ 'not-an-i28))
|
||||||
|
\endcode
|
||||||
|
The example below evaluates to 5.
|
||||||
|
\code
|
||||||
|
(match 4
|
||||||
|
( (i28 n) (+ n 1))
|
||||||
|
( _ 'not-an-i28))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="?u28"> <h3>?u28</h3> </a>
|
<a name="?u28"> <h3>?u28</h3> </a>
|
||||||
|
|
||||||
|
The ?u28 pattern matches any u28 and binds that value to a variable.
|
||||||
|
Using the ?u28 pattern is done as <code>(?u28 var)</code> and the part of the expression
|
||||||
|
that matches is bound to the <code>var</code>.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="?float"> <h3>?float</h3> </a>
|
<a name="?float"> <h3>?float</h3> </a>
|
||||||
|
|
||||||
---
|
The ?float pattern matches any float and binds that value to a variable.
|
||||||
|
Using the ?float pattern is done as <code>(?float var)</code> and the part of the expression
|
||||||
|
that matches is bound to the <code>var</code>.
|
||||||
|
|
||||||
<a name="?cons"> <h3>?cons</h3> </a>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -521,97 +1012,136 @@ An example that evaluates to 19.
|
||||||
|
|
||||||
<a name="spawn"> <h3>spawn</h3> </a>
|
<a name="spawn"> <h3>spawn</h3> </a>
|
||||||
|
|
||||||
|
Use <code>spawn</code> to spawn a concurrent task. The concurrency implemented
|
||||||
|
by LispBM is called cooperative concurrency and it means that processes must
|
||||||
|
sleep using <a href="#yield">yield</a> or they will starve out other processes.
|
||||||
|
The form of a spawn expression is <code>(spawn closure arg1 ... argN)</code>
|
||||||
|
The return value is a process ID.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="wait"> <h3>wait</h3> </a>
|
<a name="wait"> <h3>wait</h3> </a>
|
||||||
|
|
||||||
|
Use <code>wait</code> to wait for a spawned process to finish.
|
||||||
|
The argument to <code>wait</code> should be a process id.
|
||||||
|
The <code>wait</code> blocks until the process with the given process id finishes.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Be careful to only wait for processes that actually exist and do finish. Otherwise
|
||||||
|
you will wait forever.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="yield"> <h3>yield</h3> </a>
|
<a name="yield"> <h3>yield</h3> </a>
|
||||||
|
|
||||||
|
To put a process to sleep, call <code>yield</code>. The argument to <code>yield</code>
|
||||||
|
is number indicating at least how many microseconds the process should sleep.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
\section sec_messages Message-passing
|
\section sec_messages Message-passing
|
||||||
|
|
||||||
<a name="send"> <h3>send</h3> </a>
|
<a name="send"> <h3>send</h3> </a>
|
||||||
|
|
||||||
|
Messages can be sent to a process by using <code>send</code>. The form
|
||||||
|
of a <code>send</code> expression is <code>(send pid msg)</code>. The message, msg,
|
||||||
|
can be any LispBM value.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="recv"> <h3>recv</h3> </a>
|
<a name="recv"> <h3>recv</h3> </a>
|
||||||
|
|
||||||
|
To receive a message use the <code>recv</code> command. A process
|
||||||
|
will block on a <code>recv</code> until there is a matching message in
|
||||||
|
the mailbox. <br>
|
||||||
|
The <code>recv</code> syntax is very similar to <a href="#match">match</a>.
|
||||||
|
|
||||||
|
\note
|
||||||
|
Example where a process waits for an i28
|
||||||
|
\code
|
||||||
|
(recv ( (?i28 n) (+ n 1) ))
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section sec_unparse Unparsable symbols
|
\section sec_unparse Unparsable symbols
|
||||||
|
|
||||||
|
Unparsable symbols cannot be written into a program. The unparsable symbols
|
||||||
|
signals different kinds of error conditions that may point at something
|
||||||
|
being wrong in the code (or that it is exhausting all resources).
|
||||||
|
|
||||||
<a name="no_match"> <h3>no_match</h3> </a>
|
<a name="no_match"> <h3>no_match</h3> </a>
|
||||||
|
|
||||||
|
The <code>no_match</code> symbol is returned from pattern matching if
|
||||||
|
no case matches the expression.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="read_error"> <h3>read_error</h3> </a>
|
<a name="read_error"> <h3>read_error</h3> </a>
|
||||||
|
|
||||||
|
The <code>read_error</code> symbol is returned if the reader cannot
|
||||||
|
parse the input code.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="type_error"> <h3>type_error</h3> </a>
|
<a name="type_error"> <h3>type_error</h3> </a>
|
||||||
|
|
||||||
|
The <code>type_error</code> symbol is returned byt built-in functions
|
||||||
|
if the values passed in are of incompatible types.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="eval_error"> <h3>eval_error</h3> </a>
|
<a name="eval_error"> <h3>eval_error</h3> </a>
|
||||||
|
|
||||||
|
The <code>eval_error</code> symbol is returned if evaluation could
|
||||||
|
not proceed to evaluate the expression. This could be because the
|
||||||
|
expression is malformed.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="out_of_memory"> <h3>out_of_memory</h3> </a>
|
<a name="out_of_memory"> <h3>out_of_memory</h3> </a>
|
||||||
|
|
||||||
|
The <code>out_of_memory</code> symbol is returned if the heap is full and running
|
||||||
|
the garbage collector was not able to free any memory up. The program
|
||||||
|
uses more memory than the size of the heap. Make the heap larger.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="fatal_error"> <h3>fatal_error</h3> </a>
|
<a name="fatal_error"> <h3>fatal_error</h3> </a>
|
||||||
|
|
||||||
|
The <code>fatal_error</code> symbol is returned in cases where the
|
||||||
|
LispBM runtime system cannot proceed. Something is corrupt and it is
|
||||||
|
not safe to continue.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="out_of_stack"> <h3>out_of_stack</h3> </a>
|
<a name="out_of_stack"> <h3>out_of_stack</h3> </a>
|
||||||
|
|
||||||
|
The <code>out_of_stack</code> symbol is returned if the evaluator
|
||||||
|
runs out of continuation stack (this is its runtime-stack). You are
|
||||||
|
most likely writing a non-tail-recursive function that is exhausting all
|
||||||
|
the resources.
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
<a name="division_by_zero"> <h3>division_by_zero</h3> </a>
|
<a name="division_by_zero"> <h3>division_by_zero</h3> </a>
|
||||||
|
|
||||||
|
The <code>division_by_zero</code> symbol is returned when dividing by zero.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="variable_not_bound"> <h3>variable_not_bound</h3> </a>
|
<a name="variable_not_bound"> <h3>variable_not_bound</h3> </a>
|
||||||
|
|
||||||
\section sec_builtin Built-in operations
|
The <code>variable_not_bound</code> symbol is returned when evaluating a
|
||||||
|
variable (symbol) that is neighter bound nor special (built-in function).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="eval"> <h3>eval</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="eval-program"> <h3>eval-program</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="type-of"> <h3>type-of</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="sym-to-str"> <h3>sym-to-str</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="str-to-sym"> <h3>str-to-sym</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="sym-to-u"> <h3>sym-to-u</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="u-to-sym"> <h3>u-to-sym</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="is-fundamental"> <h3>is-fundamental</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
\section sec_types Types
|
\section sec_types Types
|
||||||
|
|
||||||
<a name="type-list"> <h3>type-list</h3> </a>
|
<a name="type-list"> <h3>type-list</h3> </a>
|
||||||
|
@ -658,6 +1188,11 @@ An example that evaluates to 19.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
\section sec_internal Internal symbols
|
\section sec_internal Internal symbols
|
||||||
|
|
||||||
<a name="sym_openpar"> <h3>sym_openpar</h3> </a>
|
<a name="sym_openpar"> <h3>sym_openpar</h3> </a>
|
||||||
|
@ -715,29 +1250,6 @@ An example that evaluates to 19.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
\section sec_low_level Low level operations
|
|
||||||
|
|
||||||
<a name="encode-i32"> <h3>encode-i32</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="encode-u32"> <h3>encode-u32</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="encode-float"> <h3>encode-float</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<a name="decode"> <h3>decode</h3> </a>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="array-create"> <h3>array-create</h3> </a>
|
<a name="array-create"> <h3>array-create</h3> </a>
|
||||||
|
@ -761,7 +1273,7 @@ An example that evaluates to 19.
|
||||||
|
|
||||||
<a name="stream-drop"> <h3>stream-drop</h3> </a>
|
<a name="stream-drop"> <h3>stream-drop</h3> </a>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a name="stream-put"> <h3>stream-put</h3> </a>
|
<a name="stream-put"> <h3>stream-put</h3> </a>
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,13 @@
|
||||||
|
|
||||||
https://github.com/svenssonjoel/lispBM
|
https://github.com/svenssonjoel/lispBM
|
||||||
|
|
||||||
|
<h2> LispBM Language </h2>
|
||||||
|
\ref lbmdoc <br>
|
||||||
|
\ref lbmref <br>
|
||||||
|
|
||||||
<h2> Implementation documentation </h2>
|
<h2> Implementation documentation </h2>
|
||||||
|
|
||||||
|
C Interoperation: \ref lbm_c_interop.h <br>
|
||||||
Environment: \ref env.h <br>
|
Environment: \ref env.h <br>
|
||||||
Evaluator: \ref eval_cps.h <br>
|
Evaluator: \ref eval_cps.h <br>
|
||||||
Extensions: \ref extensions.h <br>
|
Extensions: \ref extensions.h <br>
|
||||||
|
@ -19,17 +24,12 @@ LispBM: \ref lispbm.h <br>
|
||||||
Printing values: \ref print.h <br>
|
Printing values: \ref print.h <br>
|
||||||
Stacks: \ref stack.h <br>
|
Stacks: \ref stack.h <br>
|
||||||
Streams: \ref streams.h <br>
|
Streams: \ref streams.h <br>
|
||||||
Symbol and array memory: \ref lispbm_memory.h <br>
|
Symbol and array memory: \ref lbm_memory.h <br>
|
||||||
Symbol table: \ref symrepr.h <br>
|
Symbol table: \ref symrepr.h <br>
|
||||||
Types: \ref lispbm_types.h <br>
|
Types: \ref lbm_types.h <br>
|
||||||
|
Version: \ref lbm_version.h <br>
|
||||||
Quasiquotation: \ref qq_expand.h <br>
|
Quasiquotation: \ref qq_expand.h <br>
|
||||||
|
|
||||||
<h2> LispBM Language </h2>
|
|
||||||
\ref lbmdoc <br>
|
|
||||||
\ref lbmref <br>
|
|
||||||
|
|
||||||
<h2> LispBM integration</h2>
|
|
||||||
|
|
||||||
\image html lispbm_llama_small.png
|
\image html lispbm_llama_small.png
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,6 @@ extern void lbm_kill_eval(void);
|
||||||
* \return Current state of the evaluator.
|
* \return Current state of the evaluator.
|
||||||
*/
|
*/
|
||||||
extern uint32_t lbm_get_eval_state(void);
|
extern uint32_t lbm_get_eval_state(void);
|
||||||
|
|
||||||
/** Create a context and enqueue it as runnable.
|
/** Create a context and enqueue it as runnable.
|
||||||
*
|
*
|
||||||
* \param program The program to evaluate in the context.
|
* \param program The program to evaluate in the context.
|
||||||
|
@ -148,8 +147,6 @@ extern uint32_t lbm_get_eval_state(void);
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
extern lbm_cid lbm_create_ctx(lbm_value program, lbm_value env, uint32_t stack_size);
|
extern lbm_cid lbm_create_ctx(lbm_value program, lbm_value env, uint32_t stack_size);
|
||||||
|
|
||||||
/* statistics interface */
|
|
||||||
/** Iterate over all ready contexts and apply function on each context.
|
/** Iterate over all ready contexts and apply function on each context.
|
||||||
*
|
*
|
||||||
* \param f Function to apply to each context.
|
* \param f Function to apply to each context.
|
||||||
|
@ -171,12 +168,6 @@ extern void lbm_blocked_iterator(ctx_fun f, void*, void*);
|
||||||
* \param arg2 Same as above
|
* \param arg2 Same as above
|
||||||
*/
|
*/
|
||||||
extern void lbm_done_iterator(ctx_fun f, void*, void*);
|
extern void lbm_done_iterator(ctx_fun f, void*, void*);
|
||||||
|
|
||||||
/*
|
|
||||||
Callback routines for sleeping and timestamp generation.
|
|
||||||
Depending on target platform these will be implemented in different ways.
|
|
||||||
Todo: It may become necessary to also add a mutex callback.
|
|
||||||
*/
|
|
||||||
/** Set a usleep callback for use by the evaluator thread.
|
/** Set a usleep callback for use by the evaluator thread.
|
||||||
*
|
*
|
||||||
* \param fptr Pointer to a sleep function.
|
* \param fptr Pointer to a sleep function.
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "lbm_types.h"
|
#include "lbm_types.h"
|
||||||
#include "symrepr.h"
|
#include "symrepr.h"
|
||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Planning for a more space efficient heap representation.
|
Planning for a more space efficient heap representation.
|
||||||
|
@ -210,6 +211,7 @@ Aux bits could be used for storing vector size. Up to 30bits should be available
|
||||||
#define LBM_VAL_TYPE_SYMBOL 0x00000000u // 00 0 0
|
#define LBM_VAL_TYPE_SYMBOL 0x00000000u // 00 0 0
|
||||||
/// Character or byte.
|
/// Character or byte.
|
||||||
#define LBM_VAL_TYPE_CHAR 0x00000004u // 01 0 0
|
#define LBM_VAL_TYPE_CHAR 0x00000004u // 01 0 0
|
||||||
|
#define LBM_VAL_TYPE_BYTE 0x00000004u
|
||||||
#define LBM_VAL_TYPE_U 0x00000008u // 10 0 0
|
#define LBM_VAL_TYPE_U 0x00000008u // 10 0 0
|
||||||
#define LBM_VAL_TYPE_I 0x0000000Cu // 11 0 0
|
#define LBM_VAL_TYPE_I 0x0000000Cu // 11 0 0
|
||||||
|
|
||||||
|
@ -222,23 +224,24 @@ typedef struct {
|
||||||
} lbm_cons_t;
|
} lbm_cons_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heap statistics struct.
|
* Heap state
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
lbm_cons_t *heap;
|
lbm_cons_t *heap;
|
||||||
lbm_value freelist; // list of free cons cells.
|
lbm_value freelist; // list of free cons cells.
|
||||||
|
lbm_stack_t gc_stack;
|
||||||
|
|
||||||
unsigned int heap_size; // In number of cells.
|
uint32_t heap_size; // In number of cells.
|
||||||
unsigned int heap_bytes; // In bytes.
|
uint32_t heap_bytes; // In bytes.
|
||||||
|
|
||||||
unsigned int num_alloc; // Number of cells allocated.
|
uint32_t num_alloc; // Number of cells allocated.
|
||||||
unsigned int num_alloc_arrays; // Number of arrays allocated.
|
uint32_t num_alloc_arrays; // Number of arrays allocated.
|
||||||
|
|
||||||
unsigned int gc_num; // Number of times gc has been performed.
|
uint32_t gc_num; // Number of times gc has been performed.
|
||||||
unsigned int gc_marked; // Number of cells marked by mark phase.
|
uint32_t gc_marked; // Number of cells marked by mark phase.
|
||||||
unsigned int gc_recovered; // Number of cells recovered by sweep phase.
|
uint32_t gc_recovered; // Number of cells recovered by sweep phase.
|
||||||
unsigned int gc_recovered_arrays;// Number of arrays recovered by sweep.
|
uint32_t gc_recovered_arrays;// Number of arrays recovered by sweep.
|
||||||
unsigned int gc_least_free; // The smallest length of the freelist.
|
uint32_t gc_least_free; // The smallest length of the freelist.
|
||||||
|
|
||||||
uint64_t gc_time_acc;
|
uint64_t gc_time_acc;
|
||||||
uint32_t gc_min_duration;
|
uint32_t gc_min_duration;
|
||||||
|
@ -255,12 +258,14 @@ typedef struct {
|
||||||
} lbm_array_header_t;
|
} lbm_array_header_t;
|
||||||
|
|
||||||
/** Initialize heap storage.
|
/** Initialize heap storage.
|
||||||
*
|
|
||||||
* \param addr Pointer to an array of lbm_cons_t elements. This array must at least be aligned 4.
|
* \param addr Pointer to an array of lbm_cons_t elements. This array must at least be aligned 4.
|
||||||
* \param num_cells Number of lbm_cons_t elements in the array.
|
* \param num_cells Number of lbm_cons_t elements in the array.
|
||||||
|
* \param gc_stack_storage uint32_t pointer to space to use as "recursion" stack for GC
|
||||||
|
* \param gc_stack_size Size of the gc_stack in number of words.
|
||||||
* \return 1 on success or 0 for failure.
|
* \return 1 on success or 0 for failure.
|
||||||
*/
|
*/
|
||||||
extern int lbm_heap_init(lbm_cons_t *addr, unsigned int num_cells);
|
extern int lbm_heap_init(lbm_cons_t *addr, uint32_t num_cells,
|
||||||
|
uint32_t *gc_stack_storage, uint32_t gc_stack_size);
|
||||||
|
|
||||||
/** Add GC time statistics to heap_stats
|
/** Add GC time statistics to heap_stats
|
||||||
*
|
*
|
||||||
|
@ -428,6 +433,8 @@ extern int lbm_gc_mark_freelist(void);
|
||||||
* \return 1 on success and 0 if the stack used internally is full.
|
* \return 1 on success and 0 if the stack used internally is full.
|
||||||
*/
|
*/
|
||||||
extern int lbm_gc_mark_phase(lbm_value v);
|
extern int lbm_gc_mark_phase(lbm_value v);
|
||||||
|
extern int lbm_gc_mark_phase2(lbm_value env);
|
||||||
|
|
||||||
/** Performs lbm_gc_mark_phase on all the values of an array.
|
/** Performs lbm_gc_mark_phase on all the values of an array.
|
||||||
*
|
*
|
||||||
* \param data Array of roots to traverse from.
|
* \param data Array of roots to traverse from.
|
||||||
|
|
|
@ -87,6 +87,17 @@ extern int lbm_send_message(lbm_cid cid, lbm_value msg);
|
||||||
* \return 1 on success and 0 on failure.
|
* \return 1 on success and 0 on failure.
|
||||||
*/
|
*/
|
||||||
extern int lbm_define(char *symbol, lbm_value value);
|
extern int lbm_define(char *symbol, lbm_value value);
|
||||||
|
/** Create a LispBM array from a C array. The array should be created while the evaluator
|
||||||
|
* is paused and the array should be bound to something before un-pausing. Send the array in
|
||||||
|
* a message with \ref lbm_send_message or define it in the global with \ref lbm_define.
|
||||||
|
* The data is stored in the array as C values (not encoded as lbm values).
|
||||||
|
*
|
||||||
|
* \param value Result array value.
|
||||||
|
* \param data Pointer to the C array
|
||||||
|
* \param type What type are the elements of the array.
|
||||||
|
* \param num_elt Number of elements in the array.
|
||||||
|
*/
|
||||||
|
extern int lbm_create_array(lbm_value *value, char *data, lbm_type type, uint32_t num_elt);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 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
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file lbm_version.h */
|
||||||
|
|
||||||
|
#ifndef LBM_VERSION_H_
|
||||||
|
#define LBM_VERSION_H_
|
||||||
|
|
||||||
|
/* Approach to versions.
|
||||||
|
* Major version changes when there are interface breaking changes.
|
||||||
|
* Minor Backwards compatible additions.
|
||||||
|
* Patch Backwards compatible bug fixes or tweaks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** LBM major version */
|
||||||
|
#define LBM_MAJOR_VERSION 0
|
||||||
|
/** LBM minor version */
|
||||||
|
#define LBM_MINOR_VERSION 1
|
||||||
|
/** LBM patch revision */
|
||||||
|
#define LBM_PATCH_VERSION 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Change log */
|
||||||
|
|
||||||
|
/* Feb 11 2022: First state to be given a numbered version (0.1.0) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -34,6 +34,7 @@
|
||||||
#include "lbm_c_interop.h"
|
#include "lbm_c_interop.h"
|
||||||
|
|
||||||
/** Initialize lispBM. This function initials all subsystems by calling:
|
/** Initialize lispBM. This function initials all subsystems by calling:
|
||||||
|
* - \ref lbm_print_init
|
||||||
* - \ref lbm_memory_init
|
* - \ref lbm_memory_init
|
||||||
* - \ref lbm_symrepr_init
|
* - \ref lbm_symrepr_init
|
||||||
* - \ref lbm_heap_init
|
* - \ref lbm_heap_init
|
||||||
|
@ -47,10 +48,14 @@
|
||||||
* \param memory_size Size of the memory array.
|
* \param memory_size Size of the memory array.
|
||||||
* \param memory_bitmap Pointer to uint32_t array to use for the memory subsystem meta-data.
|
* \param memory_bitmap Pointer to uint32_t array to use for the memory subsystem meta-data.
|
||||||
* \param bitmap_size Size of the memory meta-data array.
|
* \param bitmap_size Size of the memory meta-data array.
|
||||||
|
* \param print_stack_storage Pointer to uint32_t array to use as print_value stack.
|
||||||
|
* \param print_stack_size Size in number of uint32_t values of the print stack.
|
||||||
* \return 1 on success and 0 on failure.
|
* \return 1 on success and 0 on failure.
|
||||||
*/
|
*/
|
||||||
extern int lbm_init(lbm_cons_t *heap_storage, uint32_t heap_size,
|
extern int lbm_init(lbm_cons_t *heap_storage, uint32_t heap_size,
|
||||||
|
uint32_t *gc_stack_storage, uint32_t gc_stack_size,
|
||||||
uint32_t *memory, uint32_t memory_size,
|
uint32_t *memory, uint32_t memory_size,
|
||||||
uint32_t *memory_bitmap, uint32_t bitmap_size);
|
uint32_t *memory_bitmap, uint32_t bitmap_size,
|
||||||
|
uint32_t *print_stack_storage, uint32_t print_stack_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,14 @@
|
||||||
|
|
||||||
#include "lbm_types.h"
|
#include "lbm_types.h"
|
||||||
|
|
||||||
|
/** Initialize the print_value subsystem.
|
||||||
|
* print value depends on a stack and that stack is initialized here using a storage array provided by the user.
|
||||||
|
* \param print_stack_storage Array to use as storage for stack data.
|
||||||
|
* \param print_stack_size The number of uint32_t elements in the array.
|
||||||
|
* \return 1 for success and 0 for failure.
|
||||||
|
*/
|
||||||
|
extern int lbm_print_init(uint32_t *print_stack_storage, uint32_t print_stack_size);
|
||||||
|
|
||||||
/** Print an lbm_value into a buffer provided by the user.
|
/** Print an lbm_value into a buffer provided by the user.
|
||||||
* If printing fails, the buffer may contain an error message.
|
* If printing fails, the buffer may contain an error message.
|
||||||
*
|
*
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
#define SYM_COMMAAT 0x74
|
#define SYM_COMMAAT 0x74
|
||||||
#define SYM_TOKENIZER_DONE 0x75
|
#define SYM_TOKENIZER_DONE 0x75
|
||||||
#define SYM_DOT 0x76
|
#define SYM_DOT 0x76
|
||||||
|
#define SYM_QUOTE_IT 0x77
|
||||||
|
|
||||||
// Fundamental Operations
|
// Fundamental Operations
|
||||||
#define FUNDAMENTALS_START 0x100
|
#define FUNDAMENTALS_START 0x100
|
||||||
|
@ -150,6 +151,15 @@
|
||||||
//#define SYM_STREAM_DROP 0x163
|
//#define SYM_STREAM_DROP 0x163
|
||||||
//#define SYM_STREAM_PUT 0x164
|
//#define SYM_STREAM_PUT 0x164
|
||||||
|
|
||||||
|
#define SYM_SHL 0x170
|
||||||
|
#define SYM_SHR 0x171
|
||||||
|
#define SYM_BITWISE_AND 0x172
|
||||||
|
#define SYM_BITWISE_OR 0x173
|
||||||
|
#define SYM_BITWISE_XOR 0x174
|
||||||
|
#define SYM_BITWISE_NOT 0x175
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define SYM_TYPE_OF 0x200
|
#define SYM_TYPE_OF 0x200
|
||||||
#define FUNDAMENTALS_END 0x200
|
#define FUNDAMENTALS_END 0x200
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "lispbm.h"
|
#include "lispbm.h"
|
||||||
|
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
static volatile bool allow_print = true;
|
static volatile bool allow_print = true;
|
||||||
|
|
||||||
|
@ -138,6 +143,9 @@ void done_callback(eval_context_t *ctx) {
|
||||||
//}
|
//}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
// remove the state associated with the context.
|
||||||
|
lbm_wait_ctx(cid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t timestamp_callback() {
|
uint32_t timestamp_callback() {
|
||||||
|
@ -300,6 +308,10 @@ void ctx_exists(eval_context_t *ctx, void *arg1, void *arg2) {
|
||||||
static uint32_t memory[LBM_MEMORY_SIZE_8K];
|
static uint32_t memory[LBM_MEMORY_SIZE_8K];
|
||||||
static uint32_t bitmap[LBM_MEMORY_BITMAP_SIZE_8K];
|
static uint32_t bitmap[LBM_MEMORY_BITMAP_SIZE_8K];
|
||||||
|
|
||||||
|
char char_array[1024];
|
||||||
|
uint32_t word_array[1024];
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
char str[1024];
|
char str[1024];
|
||||||
unsigned int len = 1024;
|
unsigned int len = 1024;
|
||||||
|
@ -311,6 +323,11 @@ int main(int argc, char **argv) {
|
||||||
unsigned int heap_size = 2048;
|
unsigned int heap_size = 2048;
|
||||||
lbm_cons_t *heap_storage = NULL;
|
lbm_cons_t *heap_storage = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 1024; i ++) {
|
||||||
|
char_array[i] = (char)i;
|
||||||
|
word_array[i] = (uint32_t)i;
|
||||||
|
}
|
||||||
|
|
||||||
//setup_terminal();
|
//setup_terminal();
|
||||||
|
|
||||||
heap_storage = (lbm_cons_t*)malloc(sizeof(lbm_cons_t) * heap_size);
|
heap_storage = (lbm_cons_t*)malloc(sizeof(lbm_cons_t) * heap_size);
|
||||||
|
@ -319,8 +336,10 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_init(heap_storage, heap_size,
|
lbm_init(heap_storage, heap_size,
|
||||||
memory, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap, LBM_MEMORY_BITMAP_SIZE_8K);
|
memory, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_set_ctx_done_callback(done_callback);
|
lbm_set_ctx_done_callback(done_callback);
|
||||||
lbm_set_timestamp_us_callback(timestamp_callback);
|
lbm_set_timestamp_us_callback(timestamp_callback);
|
||||||
|
@ -439,8 +458,10 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_init(heap_storage, heap_size,
|
lbm_init(heap_storage, heap_size,
|
||||||
memory, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap, LBM_MEMORY_BITMAP_SIZE_8K);
|
memory, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_add_extension("print", ext_print);
|
lbm_add_extension("print", ext_print);
|
||||||
} else if (strncmp(str, ":prelude", 8) == 0) {
|
} else if (strncmp(str, ":prelude", 8) == 0) {
|
||||||
|
@ -454,7 +475,7 @@ int main(int argc, char **argv) {
|
||||||
&string_tok);
|
&string_tok);
|
||||||
|
|
||||||
|
|
||||||
lbm_load_and_define_program(&string_tok, "prelude");
|
lbm_load_and_eval_program(&string_tok);
|
||||||
|
|
||||||
lbm_continue_eval();
|
lbm_continue_eval();
|
||||||
/* Something better is needed.
|
/* Something better is needed.
|
||||||
|
@ -495,6 +516,22 @@ int main(int argc, char **argv) {
|
||||||
int num = atoi(str + 5);
|
int num = atoi(str + 5);
|
||||||
|
|
||||||
lbm_step_n_eval((uint32_t)num);
|
lbm_step_n_eval((uint32_t)num);
|
||||||
|
} else if (strncmp(str, ":array", 6) == 0) {
|
||||||
|
lbm_pause_eval_with_gc(30);
|
||||||
|
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||||
|
sleep_callback(10);
|
||||||
|
}
|
||||||
|
printf("Evaluator paused\n");
|
||||||
|
|
||||||
|
lbm_value arr_val;
|
||||||
|
lbm_create_array(&arr_val, char_array, LBM_VAL_TYPE_CHAR,1024);
|
||||||
|
lbm_define("c-arr", arr_val);
|
||||||
|
|
||||||
|
lbm_create_array(&arr_val, (char *)word_array, LBM_PTR_TYPE_BOXED_I,1024);
|
||||||
|
lbm_define("i-arr", arr_val);
|
||||||
|
|
||||||
|
lbm_continue_eval();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Get exclusive access to the heap */
|
/* Get exclusive access to the heap */
|
||||||
lbm_pause_eval();
|
lbm_pause_eval();
|
||||||
|
|
|
@ -5,16 +5,41 @@
|
||||||
( (bepa (?i28 x)) (print "fred received bepa " x \#newline)))
|
( (bepa (?i28 x)) (print "fred received bepa " x \#newline)))
|
||||||
(fred))))
|
(fred))))
|
||||||
|
|
||||||
(define bella (lambda (pid x)
|
(let ((apa 1000))
|
||||||
(progn (print "bella iteration" x \#newline)
|
(define bella (lambda (pid x)
|
||||||
(send pid `(apa ,x 107))
|
(progn (print "bella " apa " iteration" x \#newline)
|
||||||
(yield 500000)
|
(send pid `(apa ,x 107))
|
||||||
(print "bella waking up" \#newline)
|
(yield 500000)
|
||||||
(send pid '(bepa 2))
|
(print "bella waking up" \#newline)
|
||||||
(yield 500000)
|
(send pid '(bepa 2))
|
||||||
(bella pid (+ x 1)))))
|
(yield 500000)
|
||||||
|
(bella pid (+ x 1)))))
|
||||||
|
)
|
||||||
|
|
||||||
(define fredpid (spawn '(fred)))
|
(let ((silly-greeter
|
||||||
|
(lambda ()
|
||||||
|
(progn (print "GREETINGS!" \#newline)
|
||||||
|
(yield 2500000)
|
||||||
|
(silly-greeter)))))
|
||||||
|
(spawn silly-greeter))
|
||||||
|
|
||||||
(spawn '(bella (car fredpid) 0))
|
|
||||||
|
(spawn (let ((mogwai
|
||||||
|
(lambda ()
|
||||||
|
(progn (print "GIZMO!" \#newline)
|
||||||
|
(yield 2500000)
|
||||||
|
(mogwai)))))
|
||||||
|
mogwai))
|
||||||
|
|
||||||
|
(spawn (let ((space
|
||||||
|
(lambda ()
|
||||||
|
(progn (print \#newline \#newline)
|
||||||
|
(yield 2500000)
|
||||||
|
(space)))))
|
||||||
|
space))
|
||||||
|
|
||||||
|
|
||||||
|
(define fredpid (spawn fred))
|
||||||
|
|
||||||
|
(spawn bella fredpid 0)
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
#define AND 8
|
#define AND 8
|
||||||
#define OR 9
|
#define OR 9
|
||||||
#define WAIT 10
|
#define WAIT 10
|
||||||
#define SPAWN_ALL 11
|
|
||||||
#define MATCH 12
|
#define MATCH 12
|
||||||
#define MATCH_MANY 13
|
#define MATCH_MANY 13
|
||||||
#define READ 14
|
#define READ 14
|
||||||
|
@ -79,7 +78,7 @@ static lbm_value NONSENSE;
|
||||||
static void error_ctx(lbm_value);
|
static void error_ctx(lbm_value);
|
||||||
static eval_context_t *ctx_running = NULL;
|
static eval_context_t *ctx_running = NULL;
|
||||||
|
|
||||||
static lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember) {
|
static inline lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember) {
|
||||||
lbm_value res = lbm_cons(head, tail);
|
lbm_value res = lbm_cons(head, tail);
|
||||||
if (lbm_is_symbol_merror(res)) {
|
if (lbm_is_symbol_merror(res)) {
|
||||||
gc(remember, NIL);
|
gc(remember, NIL);
|
||||||
|
@ -98,9 +97,6 @@ static lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERROR
|
|
||||||
//#define ERROR printf("Line: %d\n", __LINE__);
|
|
||||||
|
|
||||||
#define DEFAULT_SLEEP_US 1000
|
#define DEFAULT_SLEEP_US 1000
|
||||||
|
|
||||||
#define EVAL_CPS_DEFAULT_STACK_SIZE 256
|
#define EVAL_CPS_DEFAULT_STACK_SIZE 256
|
||||||
|
@ -883,7 +879,6 @@ static inline void eval_define(eval_context_t *ctx) {
|
||||||
|
|
||||||
if (lbm_type_of(key) != LBM_VAL_TYPE_SYMBOL ||
|
if (lbm_type_of(key) != LBM_VAL_TYPE_SYMBOL ||
|
||||||
key == NIL) {
|
key == NIL) {
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -904,7 +899,6 @@ static inline void eval_progn(eval_context_t *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lbm_is_error(exps)) {
|
if (lbm_is_error(exps)) {
|
||||||
ERROR
|
|
||||||
error_ctx(exps);
|
error_ctx(exps);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -913,23 +907,6 @@ static inline void eval_progn(eval_context_t *ctx) {
|
||||||
ctx->curr_env = env;
|
ctx->curr_env = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void eval_spawn(eval_context_t *ctx) {
|
|
||||||
lbm_value prgs = lbm_cdr(ctx->curr_exp);
|
|
||||||
lbm_value env = ctx->curr_env;
|
|
||||||
|
|
||||||
if (lbm_type_of(prgs) == LBM_VAL_TYPE_SYMBOL && prgs == NIL) {
|
|
||||||
ctx->r = NIL;
|
|
||||||
ctx->app_cont = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbm_value cid_list = NIL;
|
|
||||||
CHECK_STACK(lbm_push_u32_3(&ctx->K, env, prgs, lbm_enc_u(SPAWN_ALL)));
|
|
||||||
ctx->r = cid_list;
|
|
||||||
ctx->app_cont = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline void eval_lambda(eval_context_t *ctx) {
|
static inline void eval_lambda(eval_context_t *ctx) {
|
||||||
|
|
||||||
lbm_value env_cpy = lbm_env_copy_shallow(ctx->curr_env);
|
lbm_value env_cpy = lbm_env_copy_shallow(ctx->curr_env);
|
||||||
|
@ -1132,7 +1109,6 @@ static inline void cont_progn_rest(eval_context_t *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lbm_is_error(rest)) {
|
if (lbm_is_error(rest)) {
|
||||||
ERROR
|
|
||||||
error_ctx(rest);
|
error_ctx(rest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1148,30 +1124,6 @@ static inline void cont_progn_rest(eval_context_t *ctx) {
|
||||||
ctx->curr_env = env;
|
ctx->curr_env = env;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cont_spawn_all(eval_context_t *ctx) {
|
|
||||||
lbm_value rest;
|
|
||||||
lbm_value env;
|
|
||||||
lbm_pop_u32_2(&ctx->K, &rest, &env);
|
|
||||||
if (lbm_type_of(rest) == LBM_VAL_TYPE_SYMBOL && rest == NIL) {
|
|
||||||
ctx->app_cont = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbm_value cid_val = lbm_enc_u((lbm_uint)next_ctx_id); /* CIDS range from 0 - 65535, so this is fine */
|
|
||||||
lbm_value cid_list;
|
|
||||||
WITH_GC(cid_list, lbm_cons(cid_val, ctx->r), rest, env);
|
|
||||||
|
|
||||||
lbm_cid cid = lbm_create_ctx(lbm_car(rest),
|
|
||||||
env,
|
|
||||||
EVAL_CPS_DEFAULT_STACK_SIZE);
|
|
||||||
if (!cid) {
|
|
||||||
lbm_set_car(cid_list, lbm_enc_sym(SYM_NIL));
|
|
||||||
}
|
|
||||||
CHECK_STACK(lbm_push_u32_3(&ctx->K, env, lbm_cdr(rest), lbm_enc_u(SPAWN_ALL)));
|
|
||||||
ctx->r = cid_list;
|
|
||||||
ctx->app_cont = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void cont_wait(eval_context_t *ctx) {
|
static inline void cont_wait(eval_context_t *ctx) {
|
||||||
|
|
||||||
lbm_value cid_val;
|
lbm_value cid_val;
|
||||||
|
@ -1205,54 +1157,42 @@ static inline void cont_application(eval_context_t *ctx) {
|
||||||
lbm_value fun = fun_args[0];
|
lbm_value fun = fun_args[0];
|
||||||
|
|
||||||
if (lbm_type_of(fun) == LBM_PTR_TYPE_CONS) { // a closure (it better be)
|
if (lbm_type_of(fun) == LBM_PTR_TYPE_CONS) { // a closure (it better be)
|
||||||
lbm_value args = NIL;
|
|
||||||
for (lbm_uint i = lbm_dec_u(count); i > 0; i --) {
|
lbm_value cdr_fun = lbm_cdr(fun);
|
||||||
CONS_WITH_GC(args, fun_args[i], args, args);
|
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_uint i = 1;
|
||||||
|
while (lbm_type_of(curr_param) == LBM_PTR_TYPE_CONS &&
|
||||||
|
i <= lbm_dec_u(count)) {
|
||||||
|
|
||||||
|
lbm_value entry;
|
||||||
|
WITH_GC(entry,lbm_cons(lbm_car(curr_param),fun_args[i]), clo_env,NIL);
|
||||||
|
|
||||||
|
lbm_value aug_env;
|
||||||
|
WITH_GC(aug_env,lbm_cons(entry, clo_env),clo_env,entry);
|
||||||
|
clo_env = aug_env;
|
||||||
|
|
||||||
|
curr_param = lbm_cdr(curr_param);
|
||||||
|
i ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_value params = lbm_car(lbm_cdr(fun));
|
|
||||||
lbm_value exp = lbm_car(lbm_cdr(lbm_cdr(fun)));
|
|
||||||
lbm_value clo_env = lbm_car(lbm_cdr(lbm_cdr(lbm_cdr(fun))));
|
|
||||||
|
|
||||||
if (lbm_list_length(params) != lbm_list_length(args)) { // programmer error
|
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbm_value local_env;
|
|
||||||
WITH_GC(local_env, lbm_env_build_params_args(params, args, clo_env), args, NIL);
|
|
||||||
|
|
||||||
if (lbm_dec_sym(local_env) == SYM_FATAL_ERROR) {
|
|
||||||
ctx->r = local_env;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************
|
|
||||||
Odd area! It feels like the callers environment should be
|
|
||||||
explicitly restored after an application of a closure.
|
|
||||||
However, if the callers environment is pushed onto the stack
|
|
||||||
here, it will make the stack grow proportional to the call
|
|
||||||
depth.
|
|
||||||
|
|
||||||
I am very unsure about the correctness here.
|
|
||||||
|
|
||||||
Jan 2022:
|
|
||||||
This is ok. Only if this function is part of a progn
|
|
||||||
is there a need to restore the environment after the call.
|
|
||||||
progn is responsible for this saving and restoring.
|
|
||||||
************************************************************ */
|
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
ctx->curr_exp = exp;
|
ctx->curr_exp = exp;
|
||||||
ctx->curr_env = local_env;
|
ctx->curr_env = clo_env; // local_env;
|
||||||
return;
|
return;
|
||||||
} else if (lbm_type_of(fun) == LBM_VAL_TYPE_SYMBOL) {
|
} else if (lbm_type_of(fun) == LBM_VAL_TYPE_SYMBOL) {
|
||||||
|
|
||||||
lbm_value res;
|
|
||||||
|
|
||||||
/* eval_cps specific operations */
|
/* eval_cps specific operations */
|
||||||
lbm_uint dfun = lbm_dec_sym(fun);
|
lbm_uint dfun = lbm_dec_sym(fun);
|
||||||
if (dfun == SYM_READ || dfun == SYM_READ_PROGRAM) {
|
|
||||||
|
switch(dfun) {
|
||||||
|
case SYM_READ: /* fall through */
|
||||||
|
case SYM_READ_PROGRAM:
|
||||||
if (lbm_dec_u(count) == 1) {
|
if (lbm_dec_u(count) == 1) {
|
||||||
lbm_value stream = NIL;
|
lbm_value stream = NIL;
|
||||||
if (lbm_type_of(fun_args[1]) == LBM_PTR_TYPE_ARRAY) {
|
if (lbm_type_of(fun_args[1]) == LBM_PTR_TYPE_ARRAY) {
|
||||||
|
@ -1264,27 +1204,64 @@ static inline void cont_application(eval_context_t *ctx) {
|
||||||
stream = fun_args[1];
|
stream = fun_args[1];
|
||||||
} else {
|
} else {
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
CHECK_STACK(lbm_push_u32_3(&ctx->K, stream, fun, lbm_enc_u(READ)));
|
CHECK_STACK(lbm_push_u32_3(&ctx->K, stream, fun, lbm_enc_u(READ)));
|
||||||
ctx->r = NIL;
|
ctx->r = NIL;
|
||||||
ctx->app_cont = true;
|
ctx->app_cont = true;
|
||||||
} else {
|
break;
|
||||||
|
case SYM_SPAWN: {
|
||||||
|
if (!lbm_is_closure(fun_args[1]) ||
|
||||||
|
lbm_dec_u(count) < 1) {
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
} else if (dfun == SYM_YIELD) {
|
lbm_value cdr_fun = lbm_cdr(fun_args[1]);
|
||||||
|
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_uint i = 2;
|
||||||
|
while (lbm_type_of(curr_param) == LBM_PTR_TYPE_CONS &&
|
||||||
|
i <= lbm_dec_u(count)) {
|
||||||
|
|
||||||
|
lbm_value entry;
|
||||||
|
WITH_GC(entry,lbm_cons(lbm_car(curr_param),fun_args[i]), clo_env,NIL);
|
||||||
|
|
||||||
|
lbm_value aug_env;
|
||||||
|
WITH_GC(aug_env,lbm_cons(entry, clo_env),clo_env,entry);
|
||||||
|
clo_env = aug_env;
|
||||||
|
|
||||||
|
curr_param = lbm_cdr(curr_param);
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
|
|
||||||
|
lbm_value program = NIL;
|
||||||
|
CONS_WITH_GC(program, exp, program, clo_env);
|
||||||
|
|
||||||
|
|
||||||
|
lbm_cid cid = lbm_create_ctx(program,
|
||||||
|
clo_env,
|
||||||
|
EVAL_CPS_DEFAULT_STACK_SIZE);
|
||||||
|
ctx->r = lbm_enc_i(cid);
|
||||||
|
ctx->app_cont = true;
|
||||||
|
} break;
|
||||||
|
case SYM_YIELD:
|
||||||
if (lbm_dec_u(count) == 1 && lbm_is_number(fun_args[1])) {
|
if (lbm_dec_u(count) == 1 && lbm_is_number(fun_args[1])) {
|
||||||
lbm_uint ts = lbm_dec_as_u(fun_args[1]);
|
lbm_uint ts = lbm_dec_as_u(fun_args[1]);
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
yield_ctx(ts);
|
yield_ctx(ts);
|
||||||
} else {
|
} else {
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
} else if (dfun == SYM_WAIT) {
|
case SYM_WAIT:
|
||||||
if (lbm_type_of(fun_args[1]) == LBM_VAL_TYPE_I) {
|
if (lbm_type_of(fun_args[1]) == LBM_VAL_TYPE_I) {
|
||||||
lbm_cid cid = (lbm_cid)lbm_dec_u(fun_args[1]);
|
lbm_cid cid = (lbm_cid)lbm_dec_u(fun_args[1]);
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
|
@ -1293,32 +1270,29 @@ static inline void cont_application(eval_context_t *ctx) {
|
||||||
ctx->app_cont = true;
|
ctx->app_cont = true;
|
||||||
yield_ctx(50000);
|
yield_ctx(50000);
|
||||||
} else {
|
} else {
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
} else if (dfun == SYM_EVAL) {
|
case SYM_EVAL:
|
||||||
ctx->curr_exp = fun_args[1];
|
ctx->curr_exp = fun_args[1];
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
return;
|
break;
|
||||||
} else if (dfun == SYM_EVAL_PROGRAM) {
|
case SYM_EVAL_PROGRAM: {
|
||||||
lbm_value prg = fun_args[1];
|
lbm_value prg = fun_args[1];
|
||||||
prg = lbm_list_append(prg, ctx->program);
|
prg = lbm_list_append(prg, ctx->program);
|
||||||
|
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
|
|
||||||
if (lbm_type_of(prg) != LBM_PTR_TYPE_CONS) {
|
if (lbm_type_of(prg) != LBM_PTR_TYPE_CONS) {
|
||||||
ctx->r = lbm_enc_sym(SYM_EERROR);
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
ctx->app_cont = true;
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->program = lbm_cdr(prg);
|
ctx->program = lbm_cdr(prg);
|
||||||
ctx->curr_exp = lbm_car(prg);
|
ctx->curr_exp = lbm_car(prg);
|
||||||
return;
|
} break;
|
||||||
} else if (dfun == SYM_SEND) {
|
case SYM_SEND: {
|
||||||
lbm_value status = lbm_enc_sym(SYM_EERROR);
|
lbm_value status = lbm_enc_sym(SYM_EERROR);
|
||||||
|
|
||||||
if (lbm_dec_u(count) == 2) {
|
if (lbm_dec_u(count) == 2) {
|
||||||
|
|
||||||
if (lbm_type_of(fun_args[1]) == LBM_VAL_TYPE_U) { /* CID is of U type */
|
if (lbm_type_of(fun_args[1]) == LBM_VAL_TYPE_U) { /* CID is of U type */
|
||||||
|
@ -1332,39 +1306,41 @@ static inline void cont_application(eval_context_t *ctx) {
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
ctx->r = status;
|
ctx->r = status;
|
||||||
ctx->app_cont = true;
|
ctx->app_cont = true;
|
||||||
return;
|
} break;
|
||||||
}
|
default:
|
||||||
else if (lbm_is_fundamental(fun)) {
|
if (lbm_is_fundamental(fun)) {
|
||||||
/* If it is not a eval_cps specific function, it may be a fundamental operation */
|
/* If it is not a eval_cps specific function, it may be a fundamental operation */
|
||||||
WITH_GC(res, lbm_fundamental(&fun_args[1], lbm_dec_u(count), fun), NIL, NIL);
|
lbm_value res;
|
||||||
if (lbm_type_of(res) == LBM_VAL_TYPE_SYMBOL &&
|
WITH_GC(res, lbm_fundamental(&fun_args[1], lbm_dec_u(count), fun), NIL, NIL);
|
||||||
lbm_dec_sym(res) == SYM_EERROR) {
|
if (lbm_type_of(res) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
ERROR
|
lbm_is_error(res)) {
|
||||||
error_ctx(res);
|
error_ctx(res);
|
||||||
} else {
|
} else {
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count)+1);
|
||||||
|
ctx->app_cont = true;
|
||||||
|
ctx->r = res;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// It may be an extension
|
||||||
|
extension_fptr f = lbm_get_extension(lbm_dec_sym(fun));
|
||||||
|
if (f == NULL) {
|
||||||
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lbm_value ext_res;
|
||||||
|
WITH_GC(ext_res, f(&fun_args[1] , lbm_dec_u(count)), NIL, NIL);
|
||||||
|
|
||||||
|
lbm_stack_drop(&ctx->K, lbm_dec_u(count) + 1);
|
||||||
|
|
||||||
ctx->app_cont = true;
|
ctx->app_cont = true;
|
||||||
ctx->r = res;
|
ctx->r = ext_res;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// It may be an extension
|
|
||||||
extension_fptr f = lbm_get_extension(lbm_dec_sym(fun));
|
|
||||||
if (f == NULL) {
|
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lbm_value ext_res;
|
|
||||||
WITH_GC(ext_res, f(&fun_args[1] , lbm_dec_u(count)), NIL, NIL);
|
|
||||||
|
|
||||||
lbm_stack_drop(&ctx->K, lbm_dec_u(count) + 1);
|
|
||||||
|
|
||||||
ctx->app_cont = true;
|
|
||||||
ctx->r = ext_res;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cont_application_args(eval_context_t *ctx) {
|
static inline void cont_application_args(eval_context_t *ctx) {
|
||||||
|
@ -1784,7 +1760,7 @@ static inline void cont_read(eval_context_t *ctx) {
|
||||||
lbm_enc_u(APPEND_CONTINUE)));
|
lbm_enc_u(APPEND_CONTINUE)));
|
||||||
app_cont = false;
|
app_cont = false;
|
||||||
break;
|
break;
|
||||||
case SYM_QUOTE:
|
case SYM_QUOTE_IT:
|
||||||
CHECK_STACK(lbm_push_u32(&ctx->K,
|
CHECK_STACK(lbm_push_u32(&ctx->K,
|
||||||
lbm_enc_u(QUOTE_RESULT)));
|
lbm_enc_u(QUOTE_RESULT)));
|
||||||
app_cont = false;
|
app_cont = false;
|
||||||
|
@ -1841,7 +1817,6 @@ static void evaluation_step(void){
|
||||||
case DONE: advance_ctx(); return;
|
case DONE: advance_ctx(); return;
|
||||||
case SET_GLOBAL_ENV: cont_set_global_env(ctx); return;
|
case SET_GLOBAL_ENV: cont_set_global_env(ctx); return;
|
||||||
case PROGN_REST: cont_progn_rest(ctx); return;
|
case PROGN_REST: cont_progn_rest(ctx); return;
|
||||||
case SPAWN_ALL: cont_spawn_all(ctx); return;
|
|
||||||
case WAIT: cont_wait(ctx); return;
|
case WAIT: cont_wait(ctx); return;
|
||||||
case APPLICATION: cont_application(ctx); return;
|
case APPLICATION: cont_application(ctx); return;
|
||||||
case APPLICATION_ARGS: cont_application_args(ctx); return;
|
case APPLICATION_ARGS: cont_application_args(ctx); return;
|
||||||
|
@ -1853,7 +1828,6 @@ static void evaluation_step(void){
|
||||||
case MATCH_MANY: cont_match_many(ctx); return;
|
case MATCH_MANY: cont_match_many(ctx); return;
|
||||||
case READ: cont_read(ctx); return;
|
case READ: cont_read(ctx); return;
|
||||||
default:
|
default:
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1859,6 @@ static void evaluation_step(void){
|
||||||
case SYM_QUOTE: eval_quote(ctx); return;
|
case SYM_QUOTE: eval_quote(ctx); return;
|
||||||
case SYM_DEFINE: eval_define(ctx); return;
|
case SYM_DEFINE: eval_define(ctx); return;
|
||||||
case SYM_PROGN: eval_progn(ctx); return;
|
case SYM_PROGN: eval_progn(ctx); return;
|
||||||
case SYM_SPAWN: eval_spawn(ctx); return;
|
|
||||||
case SYM_LAMBDA: eval_lambda(ctx); return;
|
case SYM_LAMBDA: eval_lambda(ctx); return;
|
||||||
case SYM_IF: eval_if(ctx); return;
|
case SYM_IF: eval_if(ctx); return;
|
||||||
case SYM_LET: eval_let(ctx); return;
|
case SYM_LET: eval_let(ctx); return;
|
||||||
|
@ -1908,7 +1881,6 @@ static void evaluation_step(void){
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
// BUG No applicable case!
|
// BUG No applicable case!
|
||||||
ERROR
|
|
||||||
error_ctx(lbm_enc_sym(SYM_EERROR));
|
error_ctx(lbm_enc_sym(SYM_EERROR));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1989,9 +1961,6 @@ void lbm_run_eval(void){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (heap_size() - heap_num_allocated() < PRELIMINARY_GC_MEASURE) {
|
|
||||||
// gc(NIL, NIL);
|
|
||||||
//}
|
|
||||||
/* TODO: Logic for sleeping in case the evaluator has been using a lot of CPU
|
/* TODO: Logic for sleeping in case the evaluator has been using a lot of CPU
|
||||||
should go here */
|
should go here */
|
||||||
|
|
||||||
|
@ -2055,12 +2024,7 @@ int lbm_eval_init() {
|
||||||
NIL = lbm_enc_sym(SYM_NIL);
|
NIL = lbm_enc_sym(SYM_NIL);
|
||||||
NONSENSE = lbm_enc_sym(SYM_NONSENSE);
|
NONSENSE = lbm_enc_sym(SYM_NONSENSE);
|
||||||
|
|
||||||
lbm_value nil_entry = lbm_cons(NIL, NIL);
|
*lbm_get_env_ptr() = NIL;
|
||||||
*lbm_get_env_ptr() = lbm_cons(nil_entry, *lbm_get_env_ptr());
|
|
||||||
|
|
||||||
if (lbm_type_of(nil_entry) == LBM_VAL_TYPE_SYMBOL ||
|
|
||||||
lbm_type_of(*lbm_get_env_ptr()) == LBM_VAL_TYPE_SYMBOL) res = 0;
|
|
||||||
|
|
||||||
eval_running = true;
|
eval_running = true;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -25,6 +25,109 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
static lbm_uint shl(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a) && lbm_is_number(b))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) << lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) << lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(lbm_dec_U(a) << lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(lbm_dec_I(a) << lbm_dec_as_u(b)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lbm_uint shr(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a) && lbm_is_number(b))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) >> lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) >> lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(lbm_dec_U(a) >> lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(lbm_dec_I(a) >> lbm_dec_as_u(b)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lbm_uint bitwise_and(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a) && lbm_is_number(b))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) & lbm_dec_as_i(b)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) & lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(lbm_dec_U(a) & lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(lbm_dec_I(a) & lbm_dec_as_i(b)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lbm_uint bitwise_or(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a) && lbm_is_number(b))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) | lbm_dec_as_i(b)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) | lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(lbm_dec_U(a) | lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(lbm_dec_I(a) | lbm_dec_as_i(b)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lbm_uint bitwise_xor(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a) && lbm_is_number(b))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(lbm_dec_i(a) ^ lbm_dec_as_i(b)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(lbm_dec_u(a) ^ lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(lbm_dec_U(a) ^ lbm_dec_as_u(b)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(lbm_dec_I(a) ^ lbm_dec_as_i(b)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lbm_uint bitwise_not(lbm_uint a) {
|
||||||
|
|
||||||
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
|
||||||
|
if (!(lbm_is_number(a))) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lbm_type_of(a)) {
|
||||||
|
case LBM_VAL_TYPE_I: retval = lbm_enc_i(~lbm_dec_i(a)); break;
|
||||||
|
case LBM_VAL_TYPE_U: retval = lbm_enc_u(~lbm_dec_u(a)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U: retval = lbm_enc_U(~lbm_dec_U(a)); break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_I: retval = lbm_enc_I(~lbm_dec_I(a)); break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static lbm_uint add2(lbm_uint a, lbm_uint b) {
|
static lbm_uint add2(lbm_uint a, lbm_uint b) {
|
||||||
|
|
||||||
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
lbm_uint retval = lbm_enc_sym(SYM_TERROR);
|
||||||
|
@ -305,11 +408,8 @@ void array_read(lbm_value *args, lbm_uint nargs, lbm_uint *result) {
|
||||||
lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(arr);
|
lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(arr);
|
||||||
uint32_t* data = array->data;
|
uint32_t* data = array->data;
|
||||||
|
|
||||||
// printf("ix: %d, ix_end: %d\n", ix, ix_end);
|
|
||||||
for (lbm_int i = (lbm_int)ix_end; i >= (lbm_int)ix; i--) {
|
for (lbm_int i = (lbm_int)ix_end; i >= (lbm_int)ix; i--) {
|
||||||
// printf("%d\n", i);
|
|
||||||
if ((lbm_uint)i >= array->size){
|
if ((lbm_uint)i >= array->size){
|
||||||
// printf("hmm %d %d\n", i, array->size);
|
|
||||||
*result = lbm_enc_sym(SYM_NIL);
|
*result = lbm_enc_sym(SYM_NIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -576,9 +676,8 @@ lbm_value lbm_fundamental(lbm_value* args, lbm_uint nargs, lbm_value op) {
|
||||||
if (lbm_heap_allocate_array(&v, len+1, LBM_VAL_TYPE_CHAR)) {
|
if (lbm_heap_allocate_array(&v, len+1, LBM_VAL_TYPE_CHAR)) {
|
||||||
lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(v);
|
lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(v);
|
||||||
if (!arr) return lbm_enc_sym(SYM_MERROR);
|
if (!arr) return lbm_enc_sym(SYM_MERROR);
|
||||||
char *data = (char *)arr+8;
|
memset(arr->data,0,len+1);
|
||||||
memset(data,0,len+1);
|
memcpy(arr->data,sym_str,len);
|
||||||
memcpy(data,sym_str,len);
|
|
||||||
} else {
|
} else {
|
||||||
return lbm_enc_sym(SYM_MERROR);
|
return lbm_enc_sym(SYM_MERROR);
|
||||||
}
|
}
|
||||||
|
@ -593,7 +692,7 @@ lbm_value lbm_fundamental(lbm_value* args, lbm_uint nargs, lbm_value op) {
|
||||||
lbm_array_header_t *arr = (lbm_array_header_t *)lbm_car(args[0]);
|
lbm_array_header_t *arr = (lbm_array_header_t *)lbm_car(args[0]);
|
||||||
if (arr->elt_type != LBM_VAL_TYPE_CHAR)
|
if (arr->elt_type != LBM_VAL_TYPE_CHAR)
|
||||||
break;
|
break;
|
||||||
char *str = (char *)arr+8;
|
char *str = (char *)arr->data;
|
||||||
lbm_uint sym;
|
lbm_uint sym;
|
||||||
if (lbm_get_symbol_by_name(str, &sym)) {
|
if (lbm_get_symbol_by_name(str, &sym)) {
|
||||||
result = lbm_enc_sym(sym);
|
result = lbm_enc_sym(sym);
|
||||||
|
@ -843,10 +942,39 @@ lbm_value lbm_fundamental(lbm_value* args, lbm_uint nargs, lbm_value op) {
|
||||||
return lbm_enc_sym(SYM_TERROR);
|
return lbm_enc_sym(SYM_TERROR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
case SYM_SHL:
|
||||||
// printf("fundamental unknown\n");
|
if (nargs == 2) {
|
||||||
result = lbm_enc_sym(SYM_EERROR);
|
result = shl(args[0],args[1]);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
case SYM_SHR:
|
||||||
|
if (nargs == 2) {
|
||||||
|
result = shr(args[0],args[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SYM_BITWISE_AND:
|
||||||
|
if (nargs == 2) {
|
||||||
|
result = bitwise_and(args[0], args[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SYM_BITWISE_OR:
|
||||||
|
if (nargs == 2) {
|
||||||
|
result = bitwise_or(args[0], args[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SYM_BITWISE_XOR:
|
||||||
|
if (nargs == 2) {
|
||||||
|
result = bitwise_xor(args[0], args[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SYM_BITWISE_NOT:
|
||||||
|
if (nargs == 1) {
|
||||||
|
result = bitwise_not(args[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = lbm_enc_sym(SYM_EERROR);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -164,6 +164,22 @@ static inline bool get_gc_mark(lbm_cons_t* cell) {
|
||||||
return lbm_get_gc_mark(cdr);
|
return lbm_get_gc_mark(cdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void set_gc_flag(lbm_cons_t *cell) {
|
||||||
|
lbm_value v = read_car(cell);
|
||||||
|
set_car_(cell, lbm_set_gc_mark(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clr_gc_flag(lbm_cons_t *cell) {
|
||||||
|
lbm_value v = read_car(cell);
|
||||||
|
set_car_(cell, lbm_clr_gc_mark(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool get_gc_flag(lbm_cons_t* cell) {
|
||||||
|
lbm_value v = read_car(cell);
|
||||||
|
return lbm_get_gc_mark(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int generate_freelist(size_t num_cells) {
|
static int generate_freelist(size_t num_cells) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
|
@ -187,11 +203,15 @@ static int generate_freelist(size_t num_cells) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void heap_init_state(lbm_cons_t *addr, unsigned int num_cells) {
|
static void heap_init_state(lbm_cons_t *addr, unsigned int num_cells,
|
||||||
|
uint32_t *gc_stack_storage, unsigned int gc_stack_size) {
|
||||||
heap_state.heap = addr;
|
heap_state.heap = addr;
|
||||||
heap_state.heap_bytes = (unsigned int)(num_cells * sizeof(lbm_cons_t));
|
heap_state.heap_bytes = (unsigned int)(num_cells * sizeof(lbm_cons_t));
|
||||||
heap_state.heap_size = num_cells;
|
heap_state.heap_size = num_cells;
|
||||||
|
|
||||||
|
lbm_stack_create(&heap_state.gc_stack, gc_stack_storage, gc_stack_size);
|
||||||
|
|
||||||
|
|
||||||
heap_state.num_alloc = 0;
|
heap_state.num_alloc = 0;
|
||||||
heap_state.num_alloc_arrays = 0;
|
heap_state.num_alloc_arrays = 0;
|
||||||
heap_state.gc_num = 0;
|
heap_state.gc_num = 0;
|
||||||
|
@ -218,7 +238,8 @@ void lbm_heap_new_freelist_length(uint32_t l) {
|
||||||
heap_state.gc_least_free = l;
|
heap_state.gc_least_free = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lbm_heap_init(lbm_cons_t *addr, unsigned int num_cells) {
|
int lbm_heap_init(lbm_cons_t *addr, uint32_t num_cells,
|
||||||
|
uint32_t *gc_stack_storage, uint32_t gc_stack_size) {
|
||||||
|
|
||||||
NIL = lbm_enc_sym(SYM_NIL);
|
NIL = lbm_enc_sym(SYM_NIL);
|
||||||
RECOVERED = lbm_enc_sym(SYM_RECOVERED);
|
RECOVERED = lbm_enc_sym(SYM_RECOVERED);
|
||||||
|
@ -227,7 +248,8 @@ int lbm_heap_init(lbm_cons_t *addr, unsigned int num_cells) {
|
||||||
|
|
||||||
memset(addr,0, sizeof(lbm_cons_t) * num_cells);
|
memset(addr,0, sizeof(lbm_cons_t) * num_cells);
|
||||||
|
|
||||||
heap_init_state(addr, num_cells);
|
heap_init_state(addr, num_cells,
|
||||||
|
gc_stack_storage, gc_stack_size);
|
||||||
|
|
||||||
return generate_freelist(num_cells);
|
return generate_freelist(num_cells);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +279,7 @@ lbm_value lbm_heap_allocate_cell(lbm_type ptr_type) {
|
||||||
if (!lbm_is_ptr(heap_state.freelist)) {
|
if (!lbm_is_ptr(heap_state.freelist)) {
|
||||||
// Free list not a ptr (should be Symbol NIL)
|
// Free list not a ptr (should be Symbol NIL)
|
||||||
if ((lbm_type_of(heap_state.freelist) == LBM_VAL_TYPE_SYMBOL) &&
|
if ((lbm_type_of(heap_state.freelist) == LBM_VAL_TYPE_SYMBOL) &&
|
||||||
(heap_state.freelist == NIL)) {
|
(lbm_dec_sym(heap_state.freelist) == SYM_NIL)) {
|
||||||
// all is as it should be (but no free cells)
|
// all is as it should be (but no free cells)
|
||||||
return lbm_enc_sym(SYM_MERROR);
|
return lbm_enc_sym(SYM_MERROR);
|
||||||
} else {
|
} else {
|
||||||
|
@ -316,23 +338,20 @@ void lbm_get_heap_state(lbm_heap_state_t *res) {
|
||||||
res->gc_min_duration = heap_state.gc_min_duration;
|
res->gc_min_duration = heap_state.gc_min_duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lbm_value stack_storage[1024];
|
|
||||||
|
|
||||||
int lbm_gc_mark_phase(lbm_value env) {
|
int lbm_gc_mark_phase(lbm_value env) {
|
||||||
|
|
||||||
lbm_stack_t s;
|
lbm_stack_t *s = &heap_state.gc_stack;
|
||||||
lbm_stack_create(&s, stack_storage, 1024);
|
|
||||||
|
|
||||||
if (!lbm_is_ptr(env)) {
|
if (!lbm_is_ptr(env)) {
|
||||||
return 1; // Nothing to mark here
|
return 1; // Nothing to mark here
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_push_u32(&s, env);
|
lbm_push_u32(s, env);
|
||||||
|
|
||||||
while (!lbm_stack_is_empty(&s)) {
|
while (!lbm_stack_is_empty(s)) {
|
||||||
lbm_value curr;
|
lbm_value curr;
|
||||||
int res = 1;
|
int res = 1;
|
||||||
lbm_pop_u32(&s, &curr);
|
lbm_pop_u32(s, &curr);
|
||||||
|
|
||||||
if (!lbm_is_ptr(curr)) {
|
if (!lbm_is_ptr(curr)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -357,8 +376,8 @@ int lbm_gc_mark_phase(lbm_value env) {
|
||||||
t_ptr == LBM_PTR_TYPE_STREAM) {
|
t_ptr == LBM_PTR_TYPE_STREAM) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res &= lbm_push_u32(&s, lbm_cdr(curr));
|
res &= lbm_push_u32(s, lbm_cdr(curr));
|
||||||
res &= lbm_push_u32(&s, lbm_car(curr));
|
res &= lbm_push_u32(s, lbm_car(curr));
|
||||||
|
|
||||||
if (!res) return 0;
|
if (!res) return 0;
|
||||||
}
|
}
|
||||||
|
@ -478,8 +497,8 @@ lbm_value lbm_cons(lbm_value car, lbm_value cdr) {
|
||||||
lbm_value lbm_car(lbm_value c){
|
lbm_value lbm_car(lbm_value c){
|
||||||
|
|
||||||
if (lbm_type_of(c) == LBM_VAL_TYPE_SYMBOL &&
|
if (lbm_type_of(c) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
c == NIL) {
|
lbm_dec_sym(c) == SYM_NIL) {
|
||||||
return c; // if nil, return nil.
|
return lbm_enc_sym(SYM_NIL); // if nil, return nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lbm_is_ptr(c) ){
|
if (lbm_is_ptr(c) ){
|
||||||
|
@ -492,8 +511,8 @@ lbm_value lbm_car(lbm_value c){
|
||||||
lbm_value lbm_cdr(lbm_value c){
|
lbm_value lbm_cdr(lbm_value c){
|
||||||
|
|
||||||
if (lbm_type_of(c) == LBM_VAL_TYPE_SYMBOL &&
|
if (lbm_type_of(c) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
c == NIL) {
|
lbm_dec_sym(c) == SYM_NIL) {
|
||||||
return c; // if nil, return nil.
|
return lbm_enc_sym(SYM_NIL); // if nil, return nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lbm_type_of(c) == LBM_PTR_TYPE_CONS) {
|
if (lbm_type_of(c) == LBM_PTR_TYPE_CONS) {
|
||||||
|
@ -537,7 +556,7 @@ unsigned int lbm_list_length(lbm_value c) {
|
||||||
/* reverse a proper list */
|
/* reverse a proper list */
|
||||||
lbm_value lbm_list_reverse(lbm_value list) {
|
lbm_value lbm_list_reverse(lbm_value list) {
|
||||||
if (lbm_type_of(list) == LBM_VAL_TYPE_SYMBOL &&
|
if (lbm_type_of(list) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
list == NIL) {
|
lbm_dec_sym(list) == SYM_NIL) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,33 @@ int lbm_define(char *symbol, lbm_value value) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lbm_env_set(lbm_get_env(), lbm_enc_sym(sym_id), value);
|
*lbm_get_env_ptr() = lbm_env_set(lbm_get_env(), lbm_enc_sym(sym_id), value);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lbm_create_array(lbm_value *value, char *data, lbm_type type, uint32_t num_elt) {
|
||||||
|
|
||||||
|
lbm_array_header_t *array = NULL;
|
||||||
|
lbm_value cell = lbm_heap_allocate_cell(LBM_PTR_TYPE_CONS);
|
||||||
|
|
||||||
|
if (lbm_type_of(cell) == LBM_VAL_TYPE_SYMBOL) { // Out of heap memory
|
||||||
|
*value = cell;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
array = (lbm_array_header_t*)lbm_memory_allocate(sizeof(lbm_array_header_t) / 4);
|
||||||
|
|
||||||
|
if (array == NULL) return 0;
|
||||||
|
|
||||||
|
array->data = (uint32_t*)data;
|
||||||
|
array->elt_type = type;
|
||||||
|
array->size = num_elt;
|
||||||
|
|
||||||
|
lbm_set_car(cell, (lbm_uint)array);
|
||||||
|
lbm_set_cdr(cell, lbm_enc_sym(SYM_ARRAY_TYPE));
|
||||||
|
|
||||||
|
cell = cell | LBM_PTR_TYPE_ARRAY;
|
||||||
|
*value = cell;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,13 @@
|
||||||
#include "lispbm.h"
|
#include "lispbm.h"
|
||||||
|
|
||||||
int lbm_init(lbm_cons_t *heap_storage, uint32_t heap_size,
|
int lbm_init(lbm_cons_t *heap_storage, uint32_t heap_size,
|
||||||
uint32_t *memory, uint32_t memory_size,
|
uint32_t *gc_stack_storage, uint32_t gc_stack_size,
|
||||||
uint32_t *memory_bitmap, uint32_t bitmap_size) {
|
uint32_t *memory, uint32_t memory_size,
|
||||||
|
uint32_t *memory_bitmap, uint32_t bitmap_size,
|
||||||
|
uint32_t *print_stack_storage, uint32_t print_stack_size) {
|
||||||
|
|
||||||
|
if (lbm_print_init(print_stack_storage, print_stack_size) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (lbm_memory_init(memory, memory_size,
|
if (lbm_memory_init(memory, memory_size,
|
||||||
memory_bitmap, bitmap_size) == 0)
|
memory_bitmap, bitmap_size) == 0)
|
||||||
|
@ -29,7 +33,7 @@ int lbm_init(lbm_cons_t *heap_storage, uint32_t heap_size,
|
||||||
if (lbm_symrepr_init() == 0)
|
if (lbm_symrepr_init() == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lbm_heap_init(heap_storage, heap_size) == 0)
|
if (lbm_heap_init(heap_storage, heap_size, gc_stack_storage, gc_stack_size) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lbm_init_env() == 0)
|
if (lbm_init_env() == 0)
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "symrepr.h"
|
#include "symrepr.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
|
||||||
#define PRINT_STACK_SIZE 128 /* 1 KB */
|
|
||||||
|
|
||||||
#define PRINT 1
|
#define PRINT 1
|
||||||
#define PRINT_SPACE 2
|
#define PRINT_SPACE 2
|
||||||
#define START_LIST 3
|
#define START_LIST 3
|
||||||
|
@ -35,14 +33,24 @@
|
||||||
#define END_LIST 5
|
#define END_LIST 5
|
||||||
#define PRINT_DOT 6
|
#define PRINT_DOT 6
|
||||||
|
|
||||||
static lbm_value stack_storage[PRINT_STACK_SIZE];
|
static lbm_stack_t print_stack = { NULL, 0, 0, 0};
|
||||||
|
static bool print_has_stack = false;
|
||||||
|
|
||||||
const char *failed_str = "Error: print failed\n";
|
const char *failed_str = "Error: print failed\n";
|
||||||
|
|
||||||
int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
int lbm_print_init(uint32_t *print_stack_storage, uint32_t print_stack_size) {
|
||||||
|
|
||||||
lbm_stack_t s;
|
if (!print_stack_storage || print_stack_size == 0)
|
||||||
lbm_stack_create(&s, stack_storage, PRINT_STACK_SIZE);
|
return 0;
|
||||||
|
|
||||||
|
if (lbm_stack_create(&print_stack, print_stack_storage, print_stack_size)) {
|
||||||
|
print_has_stack = true;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
|
@ -50,19 +58,20 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
const char *str_ptr;
|
const char *str_ptr;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
lbm_push_u32_2(&s, t, PRINT);
|
lbm_stack_clear(&print_stack);
|
||||||
|
lbm_push_u32_2(&print_stack, t, PRINT);
|
||||||
|
|
||||||
while (!lbm_stack_is_empty(&s) && offset <= len - 5) {
|
while (!lbm_stack_is_empty(&print_stack) && offset <= len - 5) {
|
||||||
|
|
||||||
lbm_value curr;
|
lbm_value curr;
|
||||||
lbm_uint instr;
|
lbm_uint instr;
|
||||||
lbm_pop_u32(&s, &instr);
|
lbm_pop_u32(&print_stack, &instr);
|
||||||
|
|
||||||
switch(instr) {
|
switch(instr) {
|
||||||
|
|
||||||
case START_LIST: {
|
case START_LIST: {
|
||||||
res = 1;
|
res = 1;
|
||||||
lbm_pop_u32(&s, &curr);
|
lbm_pop_u32(&print_stack, &curr);
|
||||||
|
|
||||||
r = snprintf(buf + offset, len - offset, "(");
|
r = snprintf(buf + offset, len - offset, "(");
|
||||||
if ( r >= 0 ) {
|
if ( r >= 0 ) {
|
||||||
|
@ -77,19 +86,19 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
lbm_value cdr_val = lbm_cdr(curr);
|
lbm_value cdr_val = lbm_cdr(curr);
|
||||||
|
|
||||||
if (lbm_type_of(cdr_val) == LBM_PTR_TYPE_CONS) {
|
if (lbm_type_of(cdr_val) == LBM_PTR_TYPE_CONS) {
|
||||||
res &= lbm_push_u32(&s, cdr_val);
|
res &= lbm_push_u32(&print_stack, cdr_val);
|
||||||
res &= lbm_push_u32(&s, CONTINUE_LIST);
|
res &= lbm_push_u32(&print_stack, CONTINUE_LIST);
|
||||||
} else if (lbm_type_of(cdr_val) == LBM_VAL_TYPE_SYMBOL &&
|
} else if (lbm_type_of(cdr_val) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
lbm_dec_sym(cdr_val) == SYM_NIL) {
|
lbm_dec_sym(cdr_val) == SYM_NIL) {
|
||||||
res &= lbm_push_u32(&s, END_LIST);
|
res &= lbm_push_u32(&print_stack, END_LIST);
|
||||||
} else {
|
} else {
|
||||||
res &= lbm_push_u32(&s, END_LIST);
|
res &= lbm_push_u32(&print_stack, END_LIST);
|
||||||
res &= lbm_push_u32(&s, cdr_val);
|
res &= lbm_push_u32(&print_stack, cdr_val);
|
||||||
res &= lbm_push_u32(&s, PRINT);
|
res &= lbm_push_u32(&print_stack, PRINT);
|
||||||
res &= lbm_push_u32(&s, PRINT_DOT);
|
res &= lbm_push_u32(&print_stack, PRINT_DOT);
|
||||||
}
|
}
|
||||||
res &= lbm_push_u32(&s, car_val);
|
res &= lbm_push_u32(&print_stack, car_val);
|
||||||
res &= lbm_push_u32(&s, PRINT);
|
res &= lbm_push_u32(&print_stack, PRINT);
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snprintf(buf, len, "Error: Out of print stack\n");
|
snprintf(buf, len, "Error: Out of print stack\n");
|
||||||
|
@ -101,7 +110,7 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
case CONTINUE_LIST: {
|
case CONTINUE_LIST: {
|
||||||
|
|
||||||
res = 1;
|
res = 1;
|
||||||
lbm_pop_u32(&s, &curr);
|
lbm_pop_u32(&print_stack, &curr);
|
||||||
|
|
||||||
if (lbm_type_of(curr) == LBM_VAL_TYPE_SYMBOL &&
|
if (lbm_type_of(curr) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
lbm_dec_sym(curr) == SYM_NIL) {
|
lbm_dec_sym(curr) == SYM_NIL) {
|
||||||
|
@ -121,19 +130,19 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
offset += n;
|
offset += n;
|
||||||
|
|
||||||
if (lbm_type_of(cdr_val) == LBM_PTR_TYPE_CONS) {
|
if (lbm_type_of(cdr_val) == LBM_PTR_TYPE_CONS) {
|
||||||
res &= lbm_push_u32(&s, cdr_val);
|
res &= lbm_push_u32(&print_stack, cdr_val);
|
||||||
res &= lbm_push_u32(&s, CONTINUE_LIST);
|
res &= lbm_push_u32(&print_stack, CONTINUE_LIST);
|
||||||
} else if (lbm_type_of(cdr_val) == LBM_VAL_TYPE_SYMBOL &&
|
} else if (lbm_type_of(cdr_val) == LBM_VAL_TYPE_SYMBOL &&
|
||||||
lbm_dec_sym(cdr_val) == SYM_NIL) {
|
lbm_dec_sym(cdr_val) == SYM_NIL) {
|
||||||
res &= lbm_push_u32(&s, END_LIST);
|
res &= lbm_push_u32(&print_stack, END_LIST);
|
||||||
} else {
|
} else {
|
||||||
res &= lbm_push_u32(&s, END_LIST);
|
res &= lbm_push_u32(&print_stack, END_LIST);
|
||||||
res &= lbm_push_u32(&s, cdr_val);
|
res &= lbm_push_u32(&print_stack, cdr_val);
|
||||||
res &= lbm_push_u32(&s, PRINT);
|
res &= lbm_push_u32(&print_stack, PRINT);
|
||||||
res &= lbm_push_u32(&s, PRINT_DOT);
|
res &= lbm_push_u32(&print_stack, PRINT_DOT);
|
||||||
}
|
}
|
||||||
res &= lbm_push_u32(&s, car_val);
|
res &= lbm_push_u32(&print_stack, car_val);
|
||||||
res &= lbm_push_u32(&s, PRINT);
|
res &= lbm_push_u32(&print_stack, PRINT);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snprintf(buf, len, "Error: Out of print stack\n");
|
snprintf(buf, len, "Error: Out of print stack\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -175,14 +184,14 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
|
|
||||||
case PRINT:
|
case PRINT:
|
||||||
|
|
||||||
lbm_pop_u32(&s, &curr);
|
lbm_pop_u32(&print_stack, &curr);
|
||||||
|
|
||||||
switch(lbm_type_of(curr)) {
|
switch(lbm_type_of(curr)) {
|
||||||
|
|
||||||
case LBM_PTR_TYPE_CONS:{
|
case LBM_PTR_TYPE_CONS:{
|
||||||
res = 1;
|
res = 1;
|
||||||
res &= lbm_push_u32(&s, curr);
|
res &= lbm_push_u32(&print_stack, curr);
|
||||||
res &= lbm_push_u32(&s, START_LIST);
|
res &= lbm_push_u32(&print_stack, START_LIST);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snprintf(buf, len, "Error: Out of print stack\n");
|
snprintf(buf, len, "Error: Out of print stack\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -246,7 +255,7 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(curr);
|
lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(curr);
|
||||||
switch (array->elt_type){
|
switch (array->elt_type){
|
||||||
case LBM_VAL_TYPE_CHAR:
|
case LBM_VAL_TYPE_CHAR:
|
||||||
r = snprintf(buf + offset, len - offset, "\"%s\"", (char *)array->data);
|
r = snprintf(buf + offset, len - offset, "\"%.*s\"", (int)array->size, (char *)array->data);
|
||||||
if ( r > 0) {
|
if ( r > 0) {
|
||||||
n = (unsigned int) r;
|
n = (unsigned int) r;
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,10 +264,38 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
}
|
}
|
||||||
offset += n;
|
offset += n;
|
||||||
break;
|
break;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
snprintf(buf, len, "Error: Array type not supported\n");
|
r = snprintf(buf + offset, len - offset, "{");
|
||||||
return -1;
|
if (r == 1) {
|
||||||
|
offset += 1;
|
||||||
|
} else {
|
||||||
|
snprintf(buf, len, "%s", failed_str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < array->size; i ++) {
|
||||||
|
switch(array->elt_type) {
|
||||||
|
case LBM_PTR_TYPE_BOXED_I:
|
||||||
|
r = snprintf(buf+offset, len - offset, "%lu%s", (int32_t)array->data[i], i == array->size - 1 ? "" : ", ");
|
||||||
|
break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_U:
|
||||||
|
r = snprintf(buf+offset, len - offset, "%lu%s", (uint32_t)array->data[i], i == array->size - 1 ? "" : ", ");
|
||||||
|
break;
|
||||||
|
case LBM_PTR_TYPE_BOXED_F:
|
||||||
|
r = snprintf(buf+offset, len - offset, "%f%s", (double)((float)array->data[i]), i == array->size - 1 ? "" : ", ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (r > 0) {
|
||||||
|
offset += (unsigned int)r;
|
||||||
|
} else {
|
||||||
|
snprintf(buf, len, "%s", failed_str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(buf + offset, len - offset, "}");
|
||||||
|
offset ++;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -337,14 +374,11 @@ int lbm_print_value(char *buf,unsigned int len, lbm_value t) {
|
||||||
}// Switch instruction
|
}// Switch instruction
|
||||||
}//While not empty stack
|
}//While not empty stack
|
||||||
|
|
||||||
|
if (!lbm_stack_is_empty(&print_stack)) {
|
||||||
if (!lbm_stack_is_empty(&s)) {
|
|
||||||
snprintf(buf + (len - 5), 4, "...");
|
snprintf(buf + (len - 5), 4, "...");
|
||||||
buf[len-1] = 0;
|
buf[len-1] = 0;
|
||||||
return (int)len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (int)n;
|
return (int)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
|
|
||||||
#include "symrepr.h"
|
#include "symrepr.h"
|
||||||
|
|
||||||
#define NUM_SPECIAL_SYMBOLS 94
|
#define NUM_SPECIAL_SYMBOLS 101
|
||||||
|
|
||||||
#define NAME 0
|
#define NAME 0
|
||||||
#define ID 1
|
#define ID 1
|
||||||
#define NEXT 2
|
#define NEXT 2
|
||||||
|
@ -88,6 +87,7 @@ special_sym const special_symbols[NUM_SPECIAL_SYMBOLS] = {
|
||||||
{"sym_commaat" , SYM_COMMAAT},
|
{"sym_commaat" , SYM_COMMAAT},
|
||||||
{"sym_dot" , SYM_DOT},
|
{"sym_dot" , SYM_DOT},
|
||||||
{"sym_tok_done" , SYM_TOKENIZER_DONE},
|
{"sym_tok_done" , SYM_TOKENIZER_DONE},
|
||||||
|
{"sym_quote_it" , SYM_QUOTE_IT},
|
||||||
|
|
||||||
// special symbols with parseable names
|
// special symbols with parseable names
|
||||||
{"type-list" , SYM_TYPE_LIST},
|
{"type-list" , SYM_TYPE_LIST},
|
||||||
|
@ -135,6 +135,13 @@ special_sym const special_symbols[NUM_SPECIAL_SYMBOLS] = {
|
||||||
{"set-car" , SYM_SET_CAR},
|
{"set-car" , SYM_SET_CAR},
|
||||||
{"set-cdr" , SYM_SET_CDR},
|
{"set-cdr" , SYM_SET_CDR},
|
||||||
|
|
||||||
|
{"shl" , SYM_SHL},
|
||||||
|
{"shr" , SYM_SHR},
|
||||||
|
{"bitwise-and" , SYM_BITWISE_AND},
|
||||||
|
{"bitwise-or" , SYM_BITWISE_OR},
|
||||||
|
{"bitwise-xor" , SYM_BITWISE_XOR},
|
||||||
|
{"bitwise-not" , SYM_BITWISE_NOT},
|
||||||
|
|
||||||
// Streams
|
// Streams
|
||||||
// {"stream-get" , SYM_STREAM_GET},
|
// {"stream-get" , SYM_STREAM_GET},
|
||||||
// {"stream-more" , SYM_STREAM_MORE},
|
// {"stream-more" , SYM_STREAM_MORE},
|
||||||
|
|
|
@ -498,7 +498,7 @@ lbm_value lbm_get_next_token(lbm_tokenizer_char_stream_t *str) {
|
||||||
res = lbm_enc_sym(SYM_DONTCARE);
|
res = lbm_enc_sym(SYM_DONTCARE);
|
||||||
break;
|
break;
|
||||||
case TOKQUOTE:
|
case TOKQUOTE:
|
||||||
res = lbm_enc_sym(SYM_QUOTE);
|
res = lbm_enc_sym(SYM_QUOTE_IT);
|
||||||
break;
|
break;
|
||||||
case TOKBACKQUOTE:
|
case TOKBACKQUOTE:
|
||||||
res = lbm_enc_sym(SYM_BACKQUOTE);
|
res = lbm_enc_sym(SYM_BACKQUOTE);
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "symrepr.h"
|
#include "symrepr.h"
|
||||||
|
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
@ -27,7 +30,7 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = lbm_heap_init(heap_storage,heap_size);
|
res = lbm_heap_init(heap_storage,heap_size, gc_stack_storage, GC_STACK_SIZE);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
printf("Error initializing heap\n");
|
printf("Error initializing heap\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#include "lispbm.h"
|
#include "lispbm.h"
|
||||||
|
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
|
|
||||||
|
uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
/* Tokenizer state for strings */
|
/* Tokenizer state for strings */
|
||||||
static lbm_tokenizer_string_state_t string_tok_state;
|
static lbm_tokenizer_string_state_t string_tok_state;
|
||||||
|
@ -165,6 +170,15 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = lbm_print_init(print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
if (res)
|
||||||
|
printf("Printing initialized.\n");
|
||||||
|
else {
|
||||||
|
printf("Error initializing printing!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
res = lbm_symrepr_init();
|
res = lbm_symrepr_init();
|
||||||
if (res)
|
if (res)
|
||||||
printf("Symrepr initialized.\n");
|
printf("Symrepr initialized.\n");
|
||||||
|
@ -178,7 +192,7 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = lbm_heap_init(heap_storage, heap_size);
|
res = lbm_heap_init(heap_storage, heap_size, gc_stack_storage, GC_STACK_SIZE);
|
||||||
if (res)
|
if (res)
|
||||||
printf("Heap initialized. Heap size: %f MiB. Free cons cells: %d\n", lbm_heap_size_bytes() / 1024.0 / 1024.0, lbm_heap_num_free());
|
printf("Heap initialized. Heap size: %f MiB. Free cons cells: %d\n", lbm_heap_size_bytes() / 1024.0 / 1024.0, lbm_heap_num_free());
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
|
||||||
(define prg "(define a 10) (+ a 10)")
|
;; eval-program takes over the current context completely.
|
||||||
|
|
||||||
(= (eval-program (read-program prg)) 20)
|
(define prg "(define a 10) (define r (+ a 10))")
|
||||||
|
|
||||||
|
(eval-program (read-program prg))
|
||||||
|
|
||||||
|
(= r 20)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019,2021 Joel Svensson svenssonjoel@yahoo.se
|
Copyright 2019 - 2022 Joel Svensson svenssonjoel@yahoo.se
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -26,35 +26,40 @@
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
|
|
||||||
#define LISPBM_HEAP_SIZE 2048
|
#define LISPBM_HEAP_SIZE 2048
|
||||||
#define LISPBM_OUTPUT_BUFFER_SIZE 4096
|
#define LISPBM_OUTPUT_BUFFER_SIZE 1024
|
||||||
#define LISPBM_ERROR_BUFFER_SIZE 1024
|
|
||||||
#define LISPBM_INPUT_BUFFER_SIZE 1024
|
#define LISPBM_INPUT_BUFFER_SIZE 1024
|
||||||
#define EVAL_CPS_STACK_SIZE 256
|
#define EVAL_CPS_STACK_SIZE 256
|
||||||
|
#define GC_STACK_SIZE 256
|
||||||
|
#define PRINT_STACK_SIZE 256
|
||||||
|
|
||||||
static char str[LISPBM_INPUT_BUFFER_SIZE];
|
static char str[LISPBM_INPUT_BUFFER_SIZE];
|
||||||
static char outbuf[LISPBM_OUTPUT_BUFFER_SIZE];
|
static char outbuf[LISPBM_OUTPUT_BUFFER_SIZE];
|
||||||
static char error[LISPBM_ERROR_BUFFER_SIZE];
|
|
||||||
|
|
||||||
static uint32_t memory[LBM_MEMORY_SIZE_8K];
|
static uint32_t memory[LBM_MEMORY_SIZE_8K];
|
||||||
static uint32_t bitmap[LBM_MEMORY_BITMAP_SIZE_8K];
|
static uint32_t bitmap[LBM_MEMORY_BITMAP_SIZE_8K];
|
||||||
|
|
||||||
static lbm_cons_t heap[LISPBM_HEAP_SIZE];
|
static lbm_cons_t heap[LISPBM_HEAP_SIZE];
|
||||||
|
static uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
static uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
|
|
||||||
|
static lbm_tokenizer_string_state_t string_tok_state;
|
||||||
|
static lbm_tokenizer_char_stream_t string_tok;
|
||||||
|
|
||||||
|
|
||||||
void done_callback(eval_context_t *ctx) {
|
void done_callback(eval_context_t *ctx) {
|
||||||
|
|
||||||
static char print_output[1024];
|
static char print_output[1024];
|
||||||
static char error_output[1024];
|
|
||||||
|
|
||||||
lbm_cid cid = ctx->id;
|
lbm_cid cid = ctx->id;
|
||||||
lbm_value t = ctx->r;
|
lbm_value t = ctx->r;
|
||||||
|
|
||||||
int print_ret = lbm_print_value(print_output, 1024, error_output, 1024, t);
|
int print_ret = lbm_print_value(print_output, 1024, t);
|
||||||
|
|
||||||
if (print_ret >= 0) {
|
if (print_ret >= 0) {
|
||||||
usb_printf("<< Context %d finished with value %s >>\r\n# ", cid, print_output);
|
usb_printf("<< Context %d finished with value %s >>\r\n# ", cid, print_output);
|
||||||
} else {
|
} else {
|
||||||
usb_printf("<< Context %d finished with value %s >>\r\n# ", cid, error_output);
|
usb_printf("<< Context %d finished with value %s >>\r\n# ", cid, print_output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,17 +83,28 @@ void main(void)
|
||||||
lbm_heap_state_t heap_state;
|
lbm_heap_state_t heap_state;
|
||||||
|
|
||||||
lbm_init(heap, LISPBM_HEAP_SIZE,
|
lbm_init(heap, LISPBM_HEAP_SIZE,
|
||||||
memory, LBM_MEMORY_SIZE_8K,
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
bitmap, LBM_MEMORY_BITMAP_SIZE_8K);
|
memory, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE
|
||||||
|
);
|
||||||
|
|
||||||
lbm_set_ctx_done_callback(done_callback);
|
lbm_set_ctx_done_callback(done_callback);
|
||||||
lbm_set_timestamp_us_callback(timestamp_callback);
|
lbm_set_timestamp_us_callback(timestamp_callback);
|
||||||
lbm_set_usleep_callback(sleep_callback);
|
lbm_set_usleep_callback(sleep_callback);
|
||||||
|
|
||||||
|
|
||||||
lbm_value prelude = prelude_load();
|
|
||||||
eval_cps_program_nc(prelude);
|
|
||||||
|
|
||||||
|
lbm_pause_eval();
|
||||||
|
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
}
|
||||||
|
prelude_load(&string_tok_state,
|
||||||
|
&string_tok);
|
||||||
|
|
||||||
|
lbm_cid cid = lbm_load_and_eval_program(&string_tok);
|
||||||
|
|
||||||
|
lbm_continue_eval();
|
||||||
|
lbm_wait_ctx((lbm_cid)cid);
|
||||||
|
|
||||||
usb_printf("Lisp REPL started (ZephyrOS)!\r\n");
|
usb_printf("Lisp REPL started (ZephyrOS)!\r\n");
|
||||||
|
|
||||||
|
@ -108,11 +124,11 @@ void main(void)
|
||||||
if (strncmp(str, ":info", 5) == 0) {
|
if (strncmp(str, ":info", 5) == 0) {
|
||||||
usb_printf("##(REPL - ZephyrOS)#########################################\r\n");
|
usb_printf("##(REPL - ZephyrOS)#########################################\r\n");
|
||||||
usb_printf("Used cons cells: %lu \r\n", LISPBM_HEAP_SIZE - lbm_heap_num_free());
|
usb_printf("Used cons cells: %lu \r\n", LISPBM_HEAP_SIZE - lbm_heap_num_free());
|
||||||
res = lbm_print_value(outbuf, LISPBM_OUTPUT_BUFFER_SIZE, error, LISPBM_ERROR_BUFFER_SIZE, *lbm_get_env_ptr());
|
res = lbm_print_value(outbuf, LISPBM_OUTPUT_BUFFER_SIZE, lbm_get_env());
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
usb_printf("ENV: %s \r\n", outbuf);
|
usb_printf("ENV: %s \r\n", outbuf);
|
||||||
} else {
|
} else {
|
||||||
usb_printf("%s\n", error);
|
usb_printf("%s\n", outbuf);
|
||||||
}
|
}
|
||||||
lbm_get_heap_state(&heap_state);
|
lbm_get_heap_state(&heap_state);
|
||||||
usb_printf("GC counter: %lu\r\n", heap_state.gc_num);
|
usb_printf("GC counter: %lu\r\n", heap_state.gc_num);
|
||||||
|
@ -125,19 +141,23 @@ void main(void)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
lbm_value t;
|
if (strlen(str) == 0) {
|
||||||
t = tokpar_parse(str);
|
continue;
|
||||||
|
|
||||||
t = eval_cps_program_nc(t);
|
|
||||||
|
|
||||||
res = lbm_print_value(outbuf, LISPBM_OUTPUT_BUFFER_SIZE, error, LISPBM_ERROR_BUFFER_SIZE, t);
|
|
||||||
if (res >= 0) {
|
|
||||||
usb_printf("> %s\r\n", outbuf);
|
|
||||||
} else {
|
|
||||||
usb_printf("%s\r\n", error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbm_pause_eval();
|
||||||
|
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||||
|
k_sleep(K_MSEC(1));
|
||||||
|
}
|
||||||
|
lbm_create_char_stream_from_string(&string_tok_state,
|
||||||
|
&string_tok,
|
||||||
|
str);
|
||||||
|
|
||||||
|
lbm_cid cid = lbm_load_and_eval_expression(&string_tok);
|
||||||
|
|
||||||
|
lbm_continue_eval();
|
||||||
|
|
||||||
|
lbm_wait_ctx((lbm_cid)cid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
symrepr_del();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,15 @@
|
||||||
#define HEAP_SIZE 1536
|
#define HEAP_SIZE 1536
|
||||||
#define LISP_MEM_SIZE LBM_MEMORY_SIZE_8K
|
#define LISP_MEM_SIZE LBM_MEMORY_SIZE_8K
|
||||||
#define LISP_MEM_BITMAP_SIZE LBM_MEMORY_BITMAP_SIZE_8K
|
#define LISP_MEM_BITMAP_SIZE LBM_MEMORY_BITMAP_SIZE_8K
|
||||||
|
#define GC_STACK_SIZE 160
|
||||||
|
#define PRINT_STACK_SIZE 128
|
||||||
|
|
||||||
__attribute__((section(".ram4"))) static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
__attribute__((section(".ram4"))) static lbm_cons_t heap[HEAP_SIZE] __attribute__ ((aligned (8)));
|
||||||
static uint32_t memory_array[LISP_MEM_SIZE];
|
static uint32_t memory_array[LISP_MEM_SIZE];
|
||||||
static uint32_t bitmap_array[LISP_MEM_BITMAP_SIZE];
|
static uint32_t bitmap_array[LISP_MEM_BITMAP_SIZE];
|
||||||
|
static uint32_t gc_stack_storage[GC_STACK_SIZE];
|
||||||
|
static uint32_t print_stack_storage[PRINT_STACK_SIZE];
|
||||||
|
|
||||||
static lbm_tokenizer_string_state_t string_tok_state;
|
static lbm_tokenizer_string_state_t string_tok_state;
|
||||||
static lbm_tokenizer_char_stream_t string_tok;
|
static lbm_tokenizer_char_stream_t string_tok;
|
||||||
|
|
||||||
|
@ -180,7 +185,11 @@ static bool start_lisp(bool print) {
|
||||||
|
|
||||||
if (code_data != 0 && code_len > 0) {
|
if (code_data != 0 && code_len > 0) {
|
||||||
if (!lisp_thd_running) {
|
if (!lisp_thd_running) {
|
||||||
lbm_init(heap, HEAP_SIZE, memory_array, LISP_MEM_SIZE, bitmap_array, LISP_MEM_BITMAP_SIZE);
|
lbm_init(heap, HEAP_SIZE,
|
||||||
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_set_timestamp_us_callback(timestamp_callback);
|
lbm_set_timestamp_us_callback(timestamp_callback);
|
||||||
lbm_set_usleep_callback(sleep_callback);
|
lbm_set_usleep_callback(sleep_callback);
|
||||||
|
@ -193,7 +202,11 @@ static bool start_lisp(bool print) {
|
||||||
chThdSleepMilliseconds(100);
|
chThdSleepMilliseconds(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbm_init(heap, HEAP_SIZE, memory_array, LISP_MEM_SIZE, bitmap_array, LISP_MEM_BITMAP_SIZE);
|
lbm_init(heap, HEAP_SIZE,
|
||||||
|
gc_stack_storage, GC_STACK_SIZE,
|
||||||
|
memory_array, LBM_MEMORY_SIZE_8K,
|
||||||
|
bitmap_array, LBM_MEMORY_BITMAP_SIZE_8K,
|
||||||
|
print_stack_storage, PRINT_STACK_SIZE);
|
||||||
|
|
||||||
lbm_pause_eval();
|
lbm_pause_eval();
|
||||||
while (lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
while (lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||||
|
|
|
@ -560,7 +560,7 @@ static lbm_value ext_can_get_current(lbm_value *args, lbm_uint argn) {
|
||||||
if (stat0) {
|
if (stat0) {
|
||||||
return lbm_enc_F(stat0->current);
|
return lbm_enc_F(stat0->current);
|
||||||
} else {
|
} else {
|
||||||
return lbm_enc_sym(SYM_EERROR);
|
return lbm_enc_F(0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +570,7 @@ static lbm_value ext_can_get_current_dir(lbm_value *args, lbm_uint argn) {
|
||||||
if (stat0) {
|
if (stat0) {
|
||||||
return lbm_enc_F(stat0->current * SIGN(stat0->duty));
|
return lbm_enc_F(stat0->current * SIGN(stat0->duty));
|
||||||
} else {
|
} else {
|
||||||
return lbm_enc_sym(SYM_EERROR);
|
return lbm_enc_F(0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1636,6 +1636,33 @@ void mc_interface_ignore_input_both(int time_ms) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mc_interface_release_motor_override_both(void) {
|
||||||
|
int motor_last = mc_interface_get_motor_thread();
|
||||||
|
mc_interface_select_motor_thread(1);
|
||||||
|
mc_interface_release_motor_override();
|
||||||
|
mc_interface_select_motor_thread(2);
|
||||||
|
mc_interface_release_motor_override();
|
||||||
|
mc_interface_select_motor_thread(motor_last);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mc_interface_wait_for_motor_release_both(float timeout) {
|
||||||
|
int motor_last = mc_interface_get_motor_thread();
|
||||||
|
|
||||||
|
mc_interface_select_motor_thread(1);
|
||||||
|
if (!mc_interface_wait_for_motor_release(timeout)) {
|
||||||
|
mc_interface_select_motor_thread(motor_last);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mc_interface_select_motor_thread(2);
|
||||||
|
if (!mc_interface_wait_for_motor_release(timeout)) {
|
||||||
|
mc_interface_select_motor_thread(motor_last);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void mc_interface_set_current_off_delay(float delay_sec) {
|
void mc_interface_set_current_off_delay(float delay_sec) {
|
||||||
if (mc_interface_try_input()) {
|
if (mc_interface_try_input()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -97,10 +97,13 @@ uint64_t mc_interface_get_odometer(void);
|
||||||
void mc_interface_set_odometer(uint64_t new_odometer_meters);
|
void mc_interface_set_odometer(uint64_t new_odometer_meters);
|
||||||
|
|
||||||
void mc_interface_ignore_input(int time_ms);
|
void mc_interface_ignore_input(int time_ms);
|
||||||
void mc_interface_ignore_input_both(int time_ms);
|
|
||||||
|
|
||||||
void mc_interface_set_current_off_delay(float delay_sec);
|
void mc_interface_set_current_off_delay(float delay_sec);
|
||||||
|
|
||||||
|
void mc_interface_ignore_input_both(int time_ms);
|
||||||
|
void mc_interface_release_motor_override_both(void);
|
||||||
|
bool mc_interface_wait_for_motor_release_both(float timeout);
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
float mc_interface_stat_speed_avg(void);
|
float mc_interface_stat_speed_avg(void);
|
||||||
float mc_interface_stat_speed_max(void);
|
float mc_interface_stat_speed_max(void);
|
||||||
|
|
Loading…
Reference in New Issue