mirror of https://github.com/rusefi/bldc.git
Squashed 'lispBM/lispBM/' changes from e76a3deb..fe7a709d
fe7a709d added some benchresults and twear benchmark code to remove the reference to the stepping functionality 965c2543 uninlined stack popping procedures 7ea5f3bd Change GC treatment of freelist when GC is invoked and freelist is non-empty 7bc24eef update changelog d7d158e0 added 5 tests related to quasiquotation b26bf5f8 update 5309b8e7 Update README 918b4aee update README git-subtree-dir: lispBM/lispBM git-subtree-split: fe7a709d1942fbc88461e9313d91220ba97ab3e8
This commit is contained in:
parent
898e4df503
commit
b924552400
48
README.md
48
README.md
|
@ -7,8 +7,8 @@ process monitoring. The LispBM runtime system can be compiled for
|
|||
either 32 or 64 bit platforms and runs on a wide range of hardware
|
||||
such as for example STM32, NRF52, ESP32 or X86. When running the
|
||||
LispBM runtime system on a microcontroller it can be built on top of
|
||||
ChibiOS, FreeRTOS or ZephyrOS and it can also be built to run on top
|
||||
of a regular linux.
|
||||
ChibiOS, FreeRTOS or ZephyrOS or, if you are adventurous, on bare-metal.
|
||||
LispBM can also be built to run on topof a regular linux.
|
||||
|
||||
![LispBM mascot](https://github.com/svenssonjoel/lispBM/blob/master/mascot/lispbm_llama_small.png)
|
||||
|
||||
|
@ -32,48 +32,32 @@ LispBM runtime system.
|
|||
- LispBM's internals are documented as a series of [blog posts](http://svenssonjoel.github.io).
|
||||
- There are [demonstrations on YouTube](https://youtube.com/playlist?list=PLtf_3TaqZoDOQqZcB9Yj-R1zS2DWDZ9q9).
|
||||
|
||||
## Purpose
|
||||
1. Have fun.
|
||||
2. Learn about lisp.
|
||||
3. Learn about microcontrollers.
|
||||
4. An interactive REPL for devboards.
|
||||
5. ...
|
||||
|
||||
## Features
|
||||
1. heap consisting of cons-cells with mark and sweep garbage collection.
|
||||
2. Built-in functions: cons, car, cdr, eval, list, +, -, >, <, = and more.
|
||||
3. Some special forms: Lambdas, closures, lets (letrecs), define and quote.
|
||||
4. 28-Bit signed/unsigned integers and boxed 32-Bit Float, 32-Bit signed/unsigned values.
|
||||
5. Arrays (in progress), string is an array.
|
||||
6. Compiles for, and runs on linux-x86.
|
||||
7. Compiles for, and runs on Zynq 7000.
|
||||
8. Compiles for, and runs on STM32f4.
|
||||
9. Compiles for, and runs on NRF52840.
|
||||
10. Compiles for, and runs on ESP32 (ARM - WROOM).
|
||||
11. Compiles for, and runs on ESP32C3 (RISC-V).
|
||||
12. Compiles for, and runs on Raspberry PI (Tested on 32bit Raspbian OS)
|
||||
13. Quasiquotation.
|
||||
14. Concurrency.
|
||||
15. Message-passing.
|
||||
16. Pattern-matching.
|
||||
6. Quasiquotation.
|
||||
7. Concurrency.
|
||||
8. Message-passing.
|
||||
9. Pattern-matching.
|
||||
|
||||
## Vague or continuosly ongoing todos
|
||||
1. Doxygen?
|
||||
2. Tutorials?
|
||||
3. Be much more stringent on checking of error conditions etc.
|
||||
4. More built in arithmetic.
|
||||
5. More built in comparisons.
|
||||
6. Make uniform how to return success or failure. It is sometimes bool and sometimes int right now.
|
||||
|
||||
## Compile a 32bit binary for linux (Requires 32bit libraries. May need something like "multilib" on a 64bit linux)
|
||||
|
||||
1. Build the repl: `cd repl-cps` and then `make`
|
||||
|
||||
2. Run the repl: `./repl`
|
||||
4. Make uniform how to return success or failure. It is sometimes bool and sometimes int right now.
|
||||
|
||||
## Compile a 64bit binary for linux
|
||||
|
||||
1. Build the repl: `cd repl-cps` and then `make all64`
|
||||
1. Build the repl: `cd repl` and then `make all64`
|
||||
|
||||
2. Run the repl: `./repl`
|
||||
|
||||
## Compile a 32bit binary for linux (Requires 32bit libraries. May need something like "multilib" on a 64bit linux)
|
||||
|
||||
1. Build the repl: `cd repl` and then `make`
|
||||
|
||||
2. Run the repl: `./repl`
|
||||
|
||||
|
@ -85,10 +69,10 @@ To build the library exeute the following command in the lispbm folder:
|
|||
PLATFORM=pi make
|
||||
```
|
||||
|
||||
To build the `repl-cps` example repl do:
|
||||
To build the `repl` example repl do:
|
||||
|
||||
```
|
||||
cd repl-cps
|
||||
cd repl
|
||||
make pirepl
|
||||
```
|
||||
|
||||
|
|
|
@ -308,15 +308,9 @@ int main(void) {
|
|||
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||
sleep_callback(10);
|
||||
}
|
||||
chprintf(chp, "Evaluator paused\r\nEnter command :continue to unpause or :step to perform single stepping\r\n");
|
||||
chprintf(chp, "Evaluator paused\r\nEnter command :continue to unpause\r\n");
|
||||
} else if (strncmp(str, ":continue", 9) == 0) {
|
||||
lbm_continue_eval();
|
||||
} else if (strncmp(str, ":step", 5) == 0) {
|
||||
lbm_step_eval();
|
||||
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||
chThdSleepMilliseconds(1);
|
||||
}
|
||||
chprintf(chp, "Evaluator paused\r\nEnter command :continue to unpause or :step to perform single stepping\r\n");
|
||||
} else if (strncmp(str, ":reset", 6) == 0) {
|
||||
lbm_pause_eval();
|
||||
while(lbm_get_eval_state() != EVAL_CPS_STATE_PAUSED) {
|
||||
|
|
|
@ -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
|
||||
insertionsort.lisp, 0.004000000, 0.006000000, 300.000000000, 300, 300, 2, 2047
|
||||
fibonacci.lisp, 0.001799999, 3.269000053, 486.170227050, 300, 500, 94, 1968
|
||||
tak.lisp, 0.002799999, 2.888799905, 527.586181640, 300, 600, 203, 1854
|
||||
dec_cnt2.lisp, 0.001500000, 2.536499977, 472.000000000, 300, 500, 100, 2014
|
||||
dec_cnt3.lisp, 0.002000000, 1.104599952, 453.333343505, 300, 500, 15, 1996
|
||||
dec_cnt1.lisp, 0.001500000, 3.108999967, 471.000000000, 300, 500, 100, 2014
|
||||
fibonacci_tail.lisp, 0.002799999, 0.004699999, 3, 300, 300, 1, 2047
|
||||
q2.lisp, 0.002700000, 1.347000002, 513.793090820, 300, 600, 58, 1920
|
|
@ -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
|
||||
insertionsort.lisp, 0.004000000, 0.005900000, 300.000000000, 300, 300, 2, 2047
|
||||
fibonacci.lisp, 0.001799999, 3.177500009, 481.914886474, 300, 500, 94, 1968
|
||||
tak.lisp, 0.002799999, 2.796099901, 526.108398437, 300, 600, 203, 1854
|
||||
dec_cnt2.lisp, 0.001500000, 2.449100017, 470.000000000, 300, 500, 100, 2014
|
||||
dec_cnt3.lisp, 0.002000000, 1.075600028, 473.333343505, 300, 500, 15, 1996
|
||||
dec_cnt1.lisp, 0.001500000, 3.019200086, 468.000000000, 300, 500, 100, 2014
|
||||
fibonacci_tail.lisp, 0, 0.004699999, 300.000000000, 300, 300, 1, 2047
|
||||
q2.lisp, 0.002700000, 1.305099964, 515.517211914, 300, 600, 58, 1920
|
|
@ -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
|
||||
insertionsort.lisp, 0.004100000, 0.006000000, 400.000000000, 400, 400, 2, 2048
|
||||
fibonacci.lisp, 0.002099999, 3.133500099, 446.808502197, 400, 500, 94, 2048
|
||||
tak.lisp, 0.003100000, 2.760799884, 492.610839843, 400, 600, 203, 2048
|
||||
dec_cnt2.lisp, 0.001700000, 2.426599979, 435.000000000, 400, 500, 100, 2048
|
||||
dec_cnt3.lisp, 0.002199999, 1.052199959, 440.000000000, 400, 500, 15, 2048
|
||||
dec_cnt1.lisp, 0.001700000, 2.979099988, 432.000000000, 400, 500, 100, 2048
|
||||
fibonacci_tail.lisp, 0.003100000, 0.004999999, 4, 400, 400, 1, 2048
|
||||
q2.lisp, 0.002899999, 1.287600040, 475.862060546, 400, 500, 58, 2048
|
|
@ -467,6 +467,10 @@ void lbm_get_heap_state(lbm_heap_state_t *);
|
|||
*
|
||||
*/
|
||||
void lbm_gc_state_inc(void);
|
||||
/** Set the freelist to NIL. Means that no memory will be available
|
||||
* until after a garbage collection.
|
||||
*/
|
||||
void lbm_nil_freelist(void);
|
||||
/** Mark all heap cells that are on the free-list.
|
||||
*
|
||||
* \return 1 on success or 0 if the free-list is corrupted.
|
||||
|
|
|
@ -32,7 +32,10 @@ extern "C" {
|
|||
#define LBM_PATCH_VERSION 0
|
||||
|
||||
/*! \page changelog Changelog
|
||||
Oct 1: Version 0.7.0
|
||||
Oct 16: Version 0.7.0
|
||||
- Refactoring for evaluation speed.
|
||||
- Removed possibility to step through code.
|
||||
- Oldest message is removed on mailbox full.
|
||||
- Added spawn-trap inspired by Erlang (but simplified).
|
||||
|
||||
Sep 25: Version 0.7.0
|
||||
|
|
|
@ -118,12 +118,7 @@ static inline int lbm_stack_is_empty(lbm_stack_t *s) {
|
|||
* \param val1 Is pushed last.
|
||||
* \return 1 on success and 0 on failure (stack is full).
|
||||
*/
|
||||
static inline int lbm_push_2(lbm_stack_t *s, lbm_uint val0, lbm_uint val1) {
|
||||
int res = 1;
|
||||
res &= lbm_push(s,val0);
|
||||
res &= lbm_push(s,val1);
|
||||
return res;
|
||||
}
|
||||
int lbm_push_2(lbm_stack_t *s, lbm_uint val0, lbm_uint val1);
|
||||
|
||||
/** Push 3 values to a stack.
|
||||
*
|
||||
|
@ -133,13 +128,7 @@ static inline int lbm_push_2(lbm_stack_t *s, lbm_uint val0, lbm_uint val1) {
|
|||
* \param val2
|
||||
* \return 1 on success and 0 on failure (stack is full).
|
||||
*/
|
||||
static inline int lbm_push_3(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2) {
|
||||
int res = 1;
|
||||
res &= lbm_push(s,val0);
|
||||
res &= lbm_push(s,val1);
|
||||
res &= lbm_push(s,val2);
|
||||
return res;
|
||||
}
|
||||
int lbm_push_3(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2);
|
||||
|
||||
/** Push 4 values to a stack.
|
||||
*
|
||||
|
@ -150,14 +139,7 @@ static inline int lbm_push_3(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_u
|
|||
* \param val3
|
||||
* \return 1 on success and 0 on failure (stack is full).
|
||||
*/
|
||||
static inline int lbm_push_4(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2, lbm_uint val3) {
|
||||
int res = 1;
|
||||
res &= lbm_push(s,val0);
|
||||
res &= lbm_push(s,val1);
|
||||
res &= lbm_push(s,val2);
|
||||
res &= lbm_push(s,val3);
|
||||
return res;
|
||||
}
|
||||
int lbm_push_4(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2, lbm_uint val3);
|
||||
|
||||
/** Push 5 values to a stack.
|
||||
*
|
||||
|
@ -169,15 +151,7 @@ static inline int lbm_push_4(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_u
|
|||
* \param val4
|
||||
* \return 1 on success and 0 on failure (stack is full).
|
||||
*/
|
||||
static inline int lbm_push_5(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2, lbm_uint val3, lbm_uint val4) {
|
||||
int res = 1;
|
||||
res &= lbm_push(s,val0);
|
||||
res &= lbm_push(s,val1);
|
||||
res &= lbm_push(s,val2);
|
||||
res &= lbm_push(s,val3);
|
||||
res &= lbm_push(s,val4);
|
||||
return res;
|
||||
}
|
||||
int lbm_push_5(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_uint val2, lbm_uint val3, lbm_uint val4);
|
||||
|
||||
/** Pop 2 values from a stack.
|
||||
*
|
||||
|
@ -186,12 +160,7 @@ static inline int lbm_push_5(lbm_stack_t *s, lbm_uint val0, lbm_uint val1, lbm_u
|
|||
* \param r1 Pointer to lbm_value where the seconds pop:ed value will be stored.
|
||||
* \return 1 on success and 0 on failure (stack is empty).
|
||||
*/
|
||||
static inline int lbm_pop_2(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1) {
|
||||
int res = 1;
|
||||
res &= lbm_pop(s, r0);
|
||||
res &= lbm_pop(s, r1);
|
||||
return res;
|
||||
}
|
||||
int lbm_pop_2(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1);
|
||||
|
||||
/** Pop 3 values from a stack.
|
||||
*
|
||||
|
@ -201,51 +170,7 @@ static inline int lbm_pop_2(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1) {
|
|||
* \param r2
|
||||
* \return 1 on success and 0 on failure (stack is empty).
|
||||
*/
|
||||
static inline int lbm_pop_3(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1, lbm_uint *r2) {
|
||||
int res = 1;
|
||||
res &= lbm_pop(s, r0);
|
||||
res &= lbm_pop(s, r1);
|
||||
res &= lbm_pop(s, r2);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Pop 4 values from a stack.
|
||||
*
|
||||
* \param s Stack to pop values from.
|
||||
* \param r0
|
||||
* \param r1
|
||||
* \param r2
|
||||
* \param r3
|
||||
* \return 1 on success and 0 on failure (stack is empty).
|
||||
*/
|
||||
static inline int lbm_pop_4(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1, lbm_uint *r2, lbm_uint *r3) {
|
||||
int res = 1;
|
||||
res &= lbm_pop(s, r0);
|
||||
res &= lbm_pop(s, r1);
|
||||
res &= lbm_pop(s, r2);
|
||||
res &= lbm_pop(s, r3);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Pop 5 values from a stack.
|
||||
*
|
||||
* \param s Stack to pop values from.
|
||||
* \param r0
|
||||
* \param r1
|
||||
* \param r2
|
||||
* \param r3
|
||||
* \param r4
|
||||
* \return 1 on success and 0 on failure (stack is empty).
|
||||
*/
|
||||
static inline int lbm_pop_5(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1, lbm_uint *r2, lbm_uint *r3, lbm_uint *r4) {
|
||||
int res = 1;
|
||||
res &= lbm_pop(s, r0);
|
||||
res &= lbm_pop(s, r1);
|
||||
res &= lbm_pop(s, r2);
|
||||
res &= lbm_pop(s, r3);
|
||||
res &= lbm_pop(s, r4);
|
||||
return res;
|
||||
}
|
||||
int lbm_pop_3(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1, lbm_uint *r2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1087,8 +1087,8 @@ static int gc(void) {
|
|||
lbm_gc_mark_phase(variables[i]);
|
||||
}
|
||||
}
|
||||
|
||||
lbm_gc_mark_freelist();
|
||||
// The freelist should generally be NIL when GC runs.
|
||||
lbm_nil_freelist();
|
||||
lbm_gc_mark_phase(*lbm_get_env_ptr());
|
||||
|
||||
eval_context_t *curr = queue.first;
|
||||
|
@ -1355,15 +1355,15 @@ static void eval_if(eval_context_t *ctx) {
|
|||
lbm_value else_branch = lbm_cadr(cddr);
|
||||
|
||||
lbm_uint *sptr = lbm_stack_reserve(&ctx->K, 4);
|
||||
if (!sptr) {
|
||||
if (sptr) {
|
||||
sptr[0] = else_branch;
|
||||
sptr[1] = then_branch;
|
||||
sptr[2] = ctx->curr_env;
|
||||
sptr[3] = IF;
|
||||
ctx->curr_exp = lbm_cadr(ctx->curr_exp);
|
||||
} else {
|
||||
error_ctx(ENC_SYM_STACK_ERROR);
|
||||
return;
|
||||
}
|
||||
sptr[0] = else_branch;
|
||||
sptr[1] = then_branch;
|
||||
sptr[2] = ctx->curr_env;
|
||||
sptr[3] = IF;
|
||||
ctx->curr_exp = lbm_cadr(ctx->curr_exp);
|
||||
}
|
||||
|
||||
static void eval_let(eval_context_t *ctx) {
|
||||
|
|
16
src/heap.c
16
src/heap.c
|
@ -453,6 +453,10 @@ static int generate_freelist(size_t num_cells) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void lbm_nil_freelist(void) {
|
||||
lbm_heap_state.freelist = ENC_SYM_NIL;
|
||||
}
|
||||
|
||||
static void heap_init_state(lbm_cons_t *addr, lbm_uint num_cells,
|
||||
lbm_uint *gc_stack_storage, lbm_uint gc_stack_size) {
|
||||
lbm_heap_state.heap = addr;
|
||||
|
@ -657,8 +661,9 @@ int lbm_gc_sweep_phase(void) {
|
|||
lbm_cons_t *heap = (lbm_cons_t *)lbm_heap_state.heap;
|
||||
|
||||
for (i = 0; i < lbm_heap_state.heap_size; i ++) {
|
||||
if ( !get_gc_mark(&heap[i])){
|
||||
|
||||
if ( get_gc_mark(&heap[i])) {
|
||||
clr_gc_mark(&heap[i]);
|
||||
} else {
|
||||
// Check if this cell is a pointer to an array
|
||||
// and free it.
|
||||
if (lbm_type_of(heap[i].cdr) == LBM_TYPE_SYMBOL) {
|
||||
|
@ -689,12 +694,11 @@ int lbm_gc_sweep_phase(void) {
|
|||
lbm_uint *t = (lbm_uint*)heap[i].car;
|
||||
lbm_custom_type_destroy(t);
|
||||
lbm_memory_free(t);
|
||||
} break;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// create pointer to use as new freelist
|
||||
lbm_uint addr = lbm_enc_cons_ptr(i);
|
||||
|
||||
|
@ -705,7 +709,6 @@ int lbm_gc_sweep_phase(void) {
|
|||
lbm_heap_state.num_alloc --;
|
||||
lbm_heap_state.gc_recovered ++;
|
||||
}
|
||||
clr_gc_mark(&heap[i]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -774,6 +777,7 @@ lbm_value lbm_cdr(lbm_value c){
|
|||
return ENC_SYM_TERROR;
|
||||
}
|
||||
|
||||
|
||||
int lbm_set_car(lbm_value c, lbm_value v) {
|
||||
int r = 0;
|
||||
if (lbm_type_of(c) == LBM_TYPE_CONS) {
|
||||
|
|
70
src/stack.c
70
src/stack.c
|
@ -80,19 +80,81 @@ int lbm_push(lbm_stack_t *s, lbm_uint val) {
|
|||
if (s->sp == s->size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->data[s->sp] = val;
|
||||
s->sp++;
|
||||
|
||||
if (s->sp > s->max_sp) s->max_sp = s->sp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int lbm_pop(lbm_stack_t *s, lbm_uint *val) {
|
||||
int lbm_push_2(lbm_stack_t *s, lbm_uint v1, lbm_uint v2) {
|
||||
if (s->sp + 1 < s->size) {
|
||||
s->data[s->sp++] = v1;
|
||||
s->data[s->sp++] = v2;
|
||||
if (s->sp > s->max_sp) s->max_sp = s->sp;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lbm_push_3(lbm_stack_t *s, lbm_uint v1, lbm_uint v2, lbm_uint v3) {
|
||||
if (s->sp + 2 < s->size) {
|
||||
s->data[s->sp++] = v1;
|
||||
s->data[s->sp++] = v2;
|
||||
s->data[s->sp++] = v3;
|
||||
if (s->sp > s->max_sp) s->max_sp = s->sp;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lbm_push_4(lbm_stack_t *s, lbm_uint v1, lbm_uint v2, lbm_uint v3, lbm_uint v4) {
|
||||
if (s->sp + 3 < s->size) {
|
||||
s->data[s->sp++] = v1;
|
||||
s->data[s->sp++] = v2;
|
||||
s->data[s->sp++] = v3;
|
||||
s->data[s->sp++] = v4;
|
||||
if (s->sp > s->max_sp) s->max_sp = s->sp;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lbm_push_5(lbm_stack_t *s, lbm_uint v1, lbm_uint v2, lbm_uint v3, lbm_uint v4, lbm_uint v5) {
|
||||
if (s->sp + 4 < s->size) {
|
||||
s->data[s->sp++] = v1;
|
||||
s->data[s->sp++] = v2;
|
||||
s->data[s->sp++] = v3;
|
||||
s->data[s->sp++] = v4;
|
||||
s->data[s->sp++] = v5;
|
||||
if (s->sp > s->max_sp) s->max_sp = s->sp;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lbm_pop(lbm_stack_t *s, lbm_uint *val) {
|
||||
s->sp--;
|
||||
*val = s->data[s->sp];
|
||||
//s->data[s->sp] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lbm_pop_2(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1) {
|
||||
s->sp--;
|
||||
*r0 = s->data[s->sp--];
|
||||
*r1 = s->data[s->sp];
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lbm_pop_3(lbm_stack_t *s, lbm_uint *r0, lbm_uint *r1, lbm_uint *r2) {
|
||||
s->sp--;
|
||||
*r0 = s->data[s->sp--];
|
||||
*r1 = s->data[s->sp--];
|
||||
*r2 = s->data[s->sp];
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
(let ((b 101))
|
||||
(defun f (a)
|
||||
`(+ ,b ,a)))
|
||||
|
||||
|
||||
(and (= (eval (f 1)) 102)
|
||||
(= (eval (f 100)) 201))
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
(defun f (a)
|
||||
`(+ b ,a))
|
||||
|
||||
|
||||
(let ((b 101))
|
||||
(and (= (eval (f 1)) 102)
|
||||
(= (eval (f 100)) 201)))
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
(define a 10)
|
||||
|
||||
(= (eval (let ((b 1))
|
||||
`(+ ,b ,a)))
|
||||
11)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
(define a 10)
|
||||
|
||||
(= (let ((b 1))
|
||||
(eval `(+ b ,a)))
|
||||
11)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
(defun f (a)
|
||||
(let ((b 101))
|
||||
`(+ ,b ,a)))
|
||||
|
||||
|
||||
(and (= (eval (f 1)) 102)
|
||||
(= (eval (f 100)) 201))
|
Loading…
Reference in New Issue