diff --git a/lispBM/lispBM/doc/lbmref.md b/lispBM/lispBM/doc/lbmref.md
index f8d9f43d..6c7468aa 100644
--- a/lispBM/lispBM/doc/lbmref.md
+++ b/lispBM/lispBM/doc/lbmref.md
@@ -2,9 +2,9 @@
## About Symbols
-Symbols are very important and fundamental to LispBM and also perhaps
+Symbols are very important and central to LispBM and also perhaps
a bit different from identifiers/names used in languages such as C, so
-a short intro could be good here.
+a short intro on symbols could be good here.
A symbol can be thought of as a name and can be used to give names
to functions or values (variables). A symbol can also be treated and
@@ -37,20 +37,20 @@ should not be able to redefine and trying to redefine them leads to an error.
Symbols that start with `ext-` are special and reserved for use together
with extensions that are loaded and bound at runtime.
-Examples of symbols used as data are `nil` and `t`. `nil` is used the
-represent nothing, the empty list or other similar things and `t`
+Examples of symbols used as data are `nil` and `t`. `nil` representds
+"nothing", the empty list or other similar things and `t`
represents true. But any symbol can be used as data by quoting it
`'`, see Quotes and
Quasiquotation .
### Valid symbol names
-A symbol is string of characters following the rules:
+A symbol is a string of characters following the rules:
1. The first character is a one of 'a' - 'z' or 'A' - 'Z' or '+-*/=<>#!'.
2. The rest of the characters are in 'a' - 'z' or 'A' - 'Z' or '0' - '9' or '+-*/=<>!?_'.
3. At most 256 characters long.
-Note that lower-case and upper-case alphabetical letters are considers identical
+Note that lower-case and upper-case alphabetical letters are considered identical
so the symbol `apa` is the same symbol as `APA`.
examples of valid symbols
@@ -386,7 +386,7 @@ the argument.
### nil
Represents the empty list. The nil value is also considered to be false by
-conditionals
+conditionals.
The example below creates a one element list by allocating a cons cell and putting a value (1) in the car field
and nil in the cdr field.
@@ -874,7 +874,6 @@ These two programs are thus equivalent:
(define a 10)
(define b 20)
(+ a b))
-
```
And
@@ -951,7 +950,7 @@ The code above evaluates to 11.
read-program
-Parses a string containing multiple sequenced expressed. The resulting list of
+Parses a string containing multiple sequenced expressions. The resulting list of
expressions can be evaluated as a program using eval-program.
The form of a read-program expression is `(read-program string)`.
@@ -1170,7 +1169,7 @@ Example that combines to lists.
### ix
-Index into a list using the `ix`. the form of an `ix` expression
+Index into a list using the `ix` function. The form of an `ix` expression
is `(ix list-expr index-expr)`. Indexing starts from 0 and if you index out of bounds the result is nil.
Example that evaluates to 2.
@@ -1365,9 +1364,9 @@ alist. The form of a `setassoc` expression is `(setassoc alist-expr key-expr val
### bufcreate
Create an array of bytes. The
-form of an `bufcreate` expression is `(bufcreate size-expr)`
+form of a `bufcreate` expression is `(bufcreate size-expr)`
-Example that creates a 10 element buffer caled data:
+Example that creates a 10 element buffer called data:
```clj
(define data (bufcreate 10))
@@ -1672,19 +1671,21 @@ An example that atomically perfoms operations a,b and c.
### exit-ok
-The `exit-ok` function terminates the thread in a "successful" way and returnes a result
-specified by the programmer. The form of an `exit-ok` expression is `(exit-ok value)`.
-If the process that calls `exit-ok` was created using `spawn-trap` a message of the form
+The `exit-ok` function terminates the thread in a "successful" way and
+returnes a result specified by the programmer. The form of an
+`exit-ok` expression is `(exit-ok value)`. If the process that calls
+`exit-ok` was created using `spawn-trap` a message of the form
`(exit-ok tid value)` is be sent to the parent of this process.
---
### exit-error
-The `exit-error` function terminates the thread with an error specified by the programmer.
-The form of an `exit-error` expression is `(exit-error err_val)`. If the process that
-calls `exit-error` was created using `spawn-trap` a message of the form
-`(exit-error tid err_val)` is sent to the parent of this process.
+The `exit-error` function terminates the thread with an error
+specified by the programmer. The form of an `exit-error` expression
+is `(exit-error err_val)`. If the process that calls `exit-error` was
+created using `spawn-trap` a message of the form `(exit-error tid
+err_val)` is sent to the parent of this process.
---
diff --git a/lispBM/lispBM/include/lbm_defines.h b/lispBM/lispBM/include/lbm_defines.h
index 46cd5526..308988dc 100644
--- a/lispBM/lispBM/include/lbm_defines.h
+++ b/lispBM/lispBM/include/lbm_defines.h
@@ -199,102 +199,117 @@
#define SYM_LOOP 0x115
#define SPECIAL_FORMS_END 0x115
+// Fundamental built in operations that take their
+// arguments on stack. Fundamentals do not handle
+// their own GC and they are not allowed to create
+// continuations.
+#define SYM_ADD 0x20000
+#define SYM_SUB 0x20001
+#define SYM_MUL 0x20002
+#define SYM_DIV 0x20003
+#define SYM_MOD 0x20004
+#define SYM_EQ 0x20005
+#define SYM_NOT_EQ 0x20006
+#define SYM_NUMEQ 0x20007
+#define SYM_NUM_NOT_EQ 0x20008
+#define SYM_LT 0x20009
+#define SYM_GT 0x2000A
+#define SYM_LEQ 0x2000B
+#define SYM_GEQ 0x2000C
+#define SYM_NOT 0x2000D
+#define SYM_PERFORM_GC 0x2000E
+#define SYM_SELF 0x2000F
+#define SYM_SET_MAILBOX_SIZE 0x20010
+#define SYM_CONS 0x20011
+#define SYM_CAR 0x20012
+#define SYM_CDR 0x20013
+#define SYM_LIST 0x20014
+#define SYM_APPEND 0x20015
+#define SYM_UNDEFINE 0x20016
+#define SYM_ARRAY_CREATE 0x20017
+#define SYM_SYMBOL_TO_STRING 0x20018
+#define SYM_STRING_TO_SYMBOL 0x20019
+#define SYM_SYMBOL_TO_UINT 0x2001A
+#define SYM_UINT_TO_SYMBOL 0x2001B
+#define SYM_SET_CAR 0x2001C
+#define SYM_SET_CDR 0x2001D
+#define SYM_SET_IX 0x2001E
+#define SYM_ASSOC 0x2001F
+#define SYM_ACONS 0x20020
+#define SYM_SET_ASSOC 0x20021
+#define SYM_COSSA 0x20022
+#define SYM_IX 0x20023
+#define SYM_TO_I 0x20024
+#define SYM_TO_I32 0x20025
+#define SYM_TO_U 0x20026
+#define SYM_TO_U32 0x20027
+#define SYM_TO_FLOAT 0x20028
+#define SYM_TO_I64 0x20029
+#define SYM_TO_U64 0x2002A
+#define SYM_TO_DOUBLE 0x2002B
+#define SYM_TO_BYTE 0x2002C
+#define SYM_SHL 0x2002D
+#define SYM_SHR 0x2002E
+#define SYM_BITWISE_AND 0x2002F
+#define SYM_BITWISE_OR 0x20030
+#define SYM_BITWISE_XOR 0x20031
+#define SYM_BITWISE_NOT 0x20032
+#define SYM_CUSTOM_DESTRUCT 0x20033
+#define SYM_TYPE_OF 0x20034
+#define SYM_LIST_LENGTH 0x20035
+#define SYM_RANGE 0x20036
+#define SYM_REG_EVENT_HANDLER 0x20037
+#define SYM_TAKE 0x20038
+#define SYM_DROP 0x20039
+
// Apply funs:
-// Get their arguments in evaluated form.
+// Get their arguments in evaluated form on the stack.
// Consecutive value symbols for lookup-application
-#define APPLY_FUNS_START 0x150
-#define SYM_SETVAR 0x150
-#define SYM_READ 0x151
-#define SYM_READ_PROGRAM 0x152
-#define SYM_READ_AND_EVAL_PROGRAM 0x153
-#define SYM_SPAWN 0x154
-#define SYM_SPAWN_TRAP 0x155
-#define SYM_YIELD 0x156
-#define SYM_WAIT 0x157
-#define SYM_EVAL 0x158
-#define SYM_EVAL_PROGRAM 0x159
-#define SYM_SEND 0x15A
-#define SYM_EXIT_OK 0x15B
-#define SYM_EXIT_ERROR 0x15C
-#define SYM_MAP 0x15D
-#define SYM_REVERSE 0x15E
-#define SYM_FLATTEN 0x15F
-#define SYM_UNFLATTEN 0x160
-#define SYM_KILL 0x161
-#define SYM_SLEEP 0x162
-#define SYM_MERGE 0x163
-#define SYM_SORT 0x164
-#define APPLY_FUNS_END 0x164
+// apply funs handle their own GC needs and can
+// create continuations.
+#define SYM_SETVAR 0x30000
+#define SYM_READ 0x30001
+#define SYM_READ_PROGRAM 0x30002
+#define SYM_READ_AND_EVAL_PROGRAM 0x30003
+#define SYM_SPAWN 0x30004
+#define SYM_SPAWN_TRAP 0x30005
+#define SYM_YIELD 0x30006
+#define SYM_WAIT 0x30007
+#define SYM_EVAL 0x30008
+#define SYM_EVAL_PROGRAM 0x30009
+#define SYM_SEND 0x3000A
+#define SYM_EXIT_OK 0x3000B
+#define SYM_EXIT_ERROR 0x3000C
+#define SYM_MAP 0x3000D
+#define SYM_REVERSE 0x3000E
+#define SYM_FLATTEN 0x3000F
+#define SYM_UNFLATTEN 0x30010
+#define SYM_KILL 0x30011
+#define SYM_SLEEP 0x30012
+#define SYM_MERGE 0x30013
+#define SYM_SORT 0x30014
-#define FUNDAMENTALS_START 0x20E
-#define SYM_ADD 0x20E
-#define SYM_SUB 0x20F
-#define SYM_MUL 0x210
-#define SYM_DIV 0x211
-#define SYM_MOD 0x212
-#define SYM_EQ 0x213
-#define SYM_NOT_EQ 0x214
-#define SYM_NUMEQ 0x215
-#define SYM_NUM_NOT_EQ 0x216
-#define SYM_LT 0x217
-#define SYM_GT 0x218
-#define SYM_LEQ 0x219
-#define SYM_GEQ 0x21A
-#define SYM_NOT 0x21B
-#define SYM_PERFORM_GC 0x21C
-#define SYM_SELF 0x21D
-#define SYM_SET_MAILBOX_SIZE 0x21E
-#define SYM_CONS 0x21F
-#define SYM_CAR 0x220
-#define SYM_CDR 0x221
-#define SYM_LIST 0x222
-#define SYM_APPEND 0x223
-#define SYM_UNDEFINE 0x224
-#define SYM_ARRAY_CREATE 0x225
-#define SYM_SYMBOL_TO_STRING 0x226
-#define SYM_STRING_TO_SYMBOL 0x227
-#define SYM_SYMBOL_TO_UINT 0x228
-#define SYM_UINT_TO_SYMBOL 0x229
-#define SYM_SET_CAR 0x22A
-#define SYM_SET_CDR 0x22B
-#define SYM_SET_IX 0x22C
-#define SYM_ASSOC 0x22D
-#define SYM_ACONS 0x22E
-#define SYM_SET_ASSOC 0x22F
-#define SYM_COSSA 0x230
-#define SYM_IX 0x231
-#define SYM_TO_I 0x232
-#define SYM_TO_I32 0x233
-#define SYM_TO_U 0x234
-#define SYM_TO_U32 0x235
-#define SYM_TO_FLOAT 0x236
-#define SYM_TO_I64 0x237
-#define SYM_TO_U64 0x238
-#define SYM_TO_DOUBLE 0x239
-#define SYM_TO_BYTE 0x23A
-#define SYM_SHL 0x23B
-#define SYM_SHR 0x23C
-#define SYM_BITWISE_AND 0x23D
-#define SYM_BITWISE_OR 0x23E
-#define SYM_BITWISE_XOR 0x23F
-#define SYM_BITWISE_NOT 0x240
-#define SYM_CUSTOM_DESTRUCT 0x241 /* run the destructor of a custom type */
-#define SYM_TYPE_OF 0x242
-#define SYM_LIST_LENGTH 0x243
-#define SYM_RANGE 0x244
-#define SYM_REG_EVENT_HANDLER 0x245
-#define SYM_TAKE 0x246
-#define SYM_DROP 0x247
-#define FUNDAMENTALS_END 0x249
-#define SPECIAL_SYMBOLS_START 0
-#define SPECIAL_SYMBOLS_END 0xFFFF
-#define EXTENSION_SYMBOLS_START 0x10000
-#define EXTENSION_SYMBOLS_END 0x1FFFF
-#define VARIABLE_SYMBOLS_START 0x20000
-#define VARIABLE_SYMBOLS_END 0x2FFFF
-#define RUNTIME_SYMBOLS_START 0x30000
-#define MAX_SYMBOL_VALUE 0x0FFFFFFF
+#define SYMBOL_KIND(X) ((X) >> 16)
+#define SYMBOL_KIND_SPECIAL 0
+#define SYMBOL_KIND_EXTENSION 1
+#define SYMBOL_KIND_FUNDAMENTAL 2
+#define SYMBOL_KIND_APPFUN 3
+
+#define SYMBOL_IX(X) ((X) & 0xFFFF)
+
+#define SPECIAL_SYMBOLS_START 0
+#define SPECIAL_SYMBOLS_END 0xFFFF
+#define EXTENSION_SYMBOLS_START 0x10000
+#define EXTENSION_SYMBOLS_END 0x1FFFF
+#define FUNDAMENTAL_SYMBOLS_START 0x20000
+#define FUNDAMENTAL_SYMBOLS_END 0x2FFFF
+#define APPFUN_SYMBOLS_START 0x30000
+#define APPFUN_SYMBOLS_END 0x3FFFF
+#define RUNTIME_SYMBOLS_START 0x40000
+#define MAX_SYMBOL_VALUE 0x0FFFFFFF
+
+// This leaves 268173312 runtime symbols available.
/* ------------------------------------------------------------
Encoded Symbols
diff --git a/lispBM/lispBM/include/symrepr.h b/lispBM/lispBM/include/symrepr.h
index 9f7c4a43..de7a1220 100644
--- a/lispBM/lispBM/include/symrepr.h
+++ b/lispBM/lispBM/include/symrepr.h
@@ -72,20 +72,6 @@ int lbm_add_symbol_flash(char *name, lbm_uint* id);
\return 1 for success and 0 for failure.
*/
int lbm_str_to_symbol(char *name, lbm_uint *sym_id);
-/** Add a variable-symbol to the symbol table. The symbol name string is copied to arrays and symbols memory.
- *
- * \param name String representation of the symbol.
- * \param id Resulting id is returned through this argument.
- * \return 1 for success and 0 for failure.
- */
-int lbm_add_variable_symbol(char *name, lbm_uint* id);
-/** Add a variable-symbol to the symbol table. The symbol name is
- * considered to be a statically allocated constant.
- * \param name String representation of the symbol.
- * \param id Resulting id is returned through this argument.
- * \return 1 for success and 0 for failure.
- */
-int lbm_add_variable_symbol_const(char *name, lbm_uint* id);
/** Add a symbol to the symbol table. The name is assumed to be a statically allocated string.
*
* \param name Statically allocated name string.
@@ -113,8 +99,6 @@ int lbm_get_symbol_by_name(char *name, lbm_uint *id);
*/
const char* lbm_get_name_by_symbol(lbm_uint id);
-lbm_uint lbm_get_num_variables(void);
-
/**
*
* \return The total amount of lbm_memory space occupied by the symbol table in bytes.
diff --git a/lispBM/lispBM/src/eval_cps.c b/lispBM/lispBM/src/eval_cps.c
index 10a6760a..844417e9 100644
--- a/lispBM/lispBM/src/eval_cps.c
+++ b/lispBM/lispBM/src/eval_cps.c
@@ -1,4 +1,4 @@
-/*
+ /*
Copyright 2018, 2020 - 2024 Joel Svensson svenssonjoel@yahoo.se
This program is free software: you can redistribute it and/or modify
@@ -122,6 +122,24 @@ const char* lbm_error_str_variable_not_bound = "Variable not bound.";
static lbm_value lbm_error_suspect;
static bool lbm_error_has_suspect = false;
+#ifdef LBM_ALWAYS_GC
+
+#define WITH_GC(y, x) \
+ gc(); \
+ (y) = (x); \
+ if (lbm_is_symbol_merror((y))) { \
+ error_ctx(ENC_SYM_MERROR); \
+ }
+
+#define WITH_GC_RMBR_1(y, x, r) \
+ lbm_gc_mark_phase(r); \
+ gc(); \
+ (y) = (x); \
+ if (lbm_is_symbol_merror((y))) { \
+ error_ctx(ENC_SYM_MERROR); \
+ }
+
+#else
#define WITH_GC(y, x) \
(y) = (x); \
@@ -145,6 +163,8 @@ static bool lbm_error_has_suspect = false;
/* continue executing statements below */ \
}
+#endif
+
typedef struct {
eval_context_t *first;
eval_context_t *last;
@@ -377,6 +397,17 @@ eval_context_t *lbm_get_current_context(void) {
/* Utilities used locally in this file */
static lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember) {
+#ifdef LBM_ALWAYS_GC
+ lbm_value roots[3] = {head, tail, remember};
+ lbm_gc_mark_roots(roots, 3);
+ gc();
+ lbm_value res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail);
+ res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail);
+ if (lbm_is_symbol_merror(res)) {
+ error_ctx(ENC_SYM_MERROR);
+ }
+ return res;
+#else
lbm_value res = lbm_heap_allocate_cell(LBM_TYPE_CONS, head, tail);
if (lbm_is_symbol_merror(res)) {
lbm_value roots[3] = {head, tail, remember};
@@ -388,6 +419,7 @@ static lbm_value cons_with_gc(lbm_value head, lbm_value tail, lbm_value remember
}
}
return res;
+#endif
}
static lbm_uint *get_stack_ptr(eval_context_t *ctx, unsigned int n) {
@@ -455,8 +487,10 @@ static void stack_push(lbm_stack_t *s, lbm_uint val) {
static void stack_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;
+ lbm_uint *t = &s->data[s->sp];
+ t[0] = v1;
+ t[1] = v2;
+ s->sp += 2;
if (s->sp > s->max_sp) s->max_sp = s->sp;
return;
}
@@ -465,9 +499,11 @@ static void stack_push_2(lbm_stack_t *s, lbm_uint v1, lbm_uint v2) {
static void stack_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;
+ lbm_uint *t = &s->data[s->sp];
+ t[0] = v1;
+ t[1] = v2;
+ t[2] = v3;
+ s->sp += 3;
if (s->sp > s->max_sp) s->max_sp = s->sp;
return;
}
@@ -476,10 +512,12 @@ static void stack_push_3(lbm_stack_t *s, lbm_uint v1, lbm_uint v2, lbm_uint v3)
static void stack_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;
+ lbm_uint *t = &s->data[s->sp];
+ t[0] = v1;
+ t[1] = v2;
+ t[2] = v3;
+ t[3] = v4;
+ s->sp += 4;
if (s->sp > s->max_sp) s->max_sp = s->sp;
return;
}
@@ -571,24 +609,34 @@ static lbm_value get_cddr(lbm_value a) {
static lbm_value allocate_closure(lbm_value params, lbm_value body, lbm_value env) {
+#ifdef LBM_ALWAYS_GC
+ gc();
+ if (lbm_heap_num_free() < 4) {
+ error_ctx(ENC_SYM_MERROR);
+ }
+#else
if (lbm_heap_num_free() < 4) {
gc();
if (lbm_heap_num_free() < 4) {
error_ctx(ENC_SYM_MERROR);
}
}
+#endif
+ // The freelist will always contain just plain heap-cells.
+ // So dec_ptr is sufficient.
lbm_value res = lbm_heap_state.freelist;
if (lbm_type_of(res) == LBM_TYPE_CONS) {
- lbm_cons_t *cell = lbm_ref_cell(res);
- cell->car = ENC_SYM_CLOSURE;
- cell = lbm_ref_cell(cell->cdr);
- cell->car = params;
- cell = lbm_ref_cell(cell->cdr);
- cell->car = body;
- cell = lbm_ref_cell(cell->cdr);
- cell->car = env;
- lbm_heap_state.freelist = cell->cdr;
- cell->cdr = ENC_SYM_NIL;
+ lbm_cons_t *heap = lbm_heap_state.heap;
+ lbm_uint ix = lbm_dec_ptr(res);
+ heap[ix].car = ENC_SYM_CLOSURE;
+ ix = lbm_dec_ptr(heap[ix].cdr);
+ heap[ix].car = params;
+ ix = lbm_dec_ptr(heap[ix].cdr);
+ heap[ix].car = body;
+ ix = lbm_dec_ptr(heap[ix].cdr);
+ heap[ix].car = env;
+ lbm_heap_state.freelist = heap[ix].cdr;
+ heap[ix].cdr = ENC_SYM_NIL;
lbm_heap_state.num_alloc+=4;
} else {
error_ctx(ENC_SYM_FATAL_ERROR);
@@ -625,7 +673,7 @@ static void call_fundamental(lbm_uint fundamental, lbm_value *args, lbm_uint arg
res = fundamental_table[fundamental](args, arg_count, ctx);
}
if (lbm_is_error(res)) {
- error_at_ctx(res, lbm_enc_sym(fundamental+FUNDAMENTALS_START));
+ error_at_ctx(res, lbm_enc_sym(EXTENSION_SYMBOLS_START | fundamental));
}
}
lbm_stack_drop(&ctx->K, arg_count+1);
@@ -1536,25 +1584,20 @@ int lbm_perform_gc(void) {
static void eval_symbol(eval_context_t *ctx) {
lbm_uint s = lbm_dec_sym(ctx->curr_exp);
if (s >= RUNTIME_SYMBOLS_START) {
- lbm_value res;
+ lbm_value res = ENC_SYM_NIL;
if (lbm_env_lookup_b(&res, ctx->curr_exp, ctx->curr_env) ||
lbm_global_env_lookup(&res, ctx->curr_exp)) {
ctx->r = res;
ctx->app_cont = true;
return;
}
- } else if (s <= EXTENSION_SYMBOLS_END) {
- //special symbols and extensions can be handled the same way.
- ctx->r = ctx->curr_exp;
- ctx->app_cont = true;
- return;
- }
- // Dynamic load attempt
- const char *sym_str = lbm_get_name_by_symbol(s);
- const char *code_str = NULL;
- if (!dynamic_load_callback(sym_str, &code_str)) {
- error_at_ctx(ENC_SYM_NOT_FOUND, ctx->curr_exp);
- } else {
+ // Dynamic load attempt
+ // Only symbols of kind RUNTIME can be dynamically loaded.
+ const char *sym_str = lbm_get_name_by_symbol(s);
+ const char *code_str = NULL;
+ if (!dynamic_load_callback(sym_str, &code_str)) {
+ error_at_ctx(ENC_SYM_NOT_FOUND, ctx->curr_exp);
+ }
stack_push_3(&ctx->K, ctx->curr_exp, ctx->curr_env, RESUME);
lbm_value chan;
@@ -1575,6 +1618,10 @@ static void eval_symbol(eval_context_t *ctx) {
loader), loader);
ctx->curr_exp = evaluator;
ctx->curr_env = ENC_SYM_NIL; // dynamics should be evaluable in empty local env
+ } else {
+ //special symbols and extensions can be handled the same way.
+ ctx->r = ctx->curr_exp;
+ ctx->app_cont = true;
}
}
@@ -2701,19 +2748,11 @@ static void application(eval_context_t *ctx, lbm_value *fun_args, lbm_uint arg_c
lbm_value fun = fun_args[0];
lbm_uint fun_val = lbm_dec_sym(fun);
- lbm_uint apply_val = fun_val - APPLY_FUNS_START;
- lbm_uint fund_val = fun_val - FUNDAMENTALS_START;
+ lbm_uint fun_kind = SYMBOL_KIND(fun_val);
- if (apply_val <= (APPLY_FUNS_END - APPLY_FUNS_START)) {
- fun_table[apply_val](&fun_args[1], arg_count, ctx);
- } else if (fund_val <= (FUNDAMENTALS_END - FUNDAMENTALS_START)) {
- call_fundamental(fund_val, &fun_args[1], arg_count, ctx);
- } else {
- // It may be an extension
- extension_fptr f = lbm_get_extension(fun_val);
- if (f == NULL) {
- error_at_ctx(ENC_SYM_EERROR,fun);
- }
+ switch (fun_kind) {
+ case SYMBOL_KIND_EXTENSION: {
+ extension_fptr f = extension_table[SYMBOL_IX(fun_val)].fptr;
lbm_value ext_res;
WITH_GC(ext_res, f(&fun_args[1], arg_count));
@@ -2735,6 +2774,16 @@ static void application(eval_context_t *ctx, lbm_value *fun_args, lbm_uint arg_c
ctx->app_cont = true;
ctx->r = ext_res;
}
+ } break;
+ case SYMBOL_KIND_FUNDAMENTAL:
+ call_fundamental(SYMBOL_IX(fun_val), &fun_args[1], arg_count, ctx);
+ break;
+ case SYMBOL_KIND_APPFUN:
+ fun_table[SYMBOL_IX(fun_val)](&fun_args[1], arg_count, ctx);
+ break;
+ default:
+ error_ctx(ENC_SYM_FATAL_ERROR);
+ break;
}
}
@@ -2756,20 +2805,20 @@ static void cont_closure_application_args(eval_context_t *ctx) {
error_ctx(ENC_SYM_MERROR);
}
}
+ lbm_cons_t* heap = lbm_heap_state.heap;
lbm_value cell0 = lbm_heap_state.freelist;
- lbm_cons_t *cell0_r = lbm_ref_cell(cell0);
- lbm_value cell1 = cell0_r->cdr;
- lbm_cons_t *cell1_r = lbm_ref_cell(cell1);
- lbm_heap_state.freelist = cell1_r->cdr;
+ lbm_uint cell0_ix = lbm_dec_ptr(cell0);
+ lbm_value cell1 = heap[cell0_ix].cdr;
+ lbm_uint cell1_ix = lbm_dec_ptr(cell1);
+ lbm_heap_state.freelist = heap[cell1_ix].cdr;
lbm_heap_state.num_alloc += 2;
- cell0_r->car = car_params;
- cell0_r->cdr = ctx->r;
- cell1_r->car = cell0;
- cell1_r->cdr = clo_env;
+ heap[cell0_ix].car = car_params;
+ heap[cell0_ix].cdr = ctx->r;
+ heap[cell1_ix].car = cell0;
+ heap[cell1_ix].cdr = clo_env;
clo_env = cell1;
- // TODO: We are NOT going to implement a lazy sweep.
bool a_nil = args == ENC_SYM_NIL;
bool p_nil = cdr_params == ENC_SYM_NIL;
@@ -2910,12 +2959,12 @@ static void cont_if(eval_context_t *ctx) {
static void cont_match(eval_context_t *ctx) {
lbm_value e = ctx->r;
- lbm_value patterns;
- lbm_value new_env;
- lbm_value orig_env;
bool do_gc = false;
- lbm_pop_2(&ctx->K, &orig_env, &patterns); // restore enclosing environment
- new_env = orig_env;
+
+ lbm_uint *sptr = get_stack_ptr(ctx, 2);
+ lbm_value patterns = (lbm_value)sptr[0];
+ lbm_value orig_env = (lbm_value)sptr[1]; // restore enclosing environment.
+ lbm_value new_env = orig_env;
if (lbm_is_symbol_nil(patterns)) {
// no more patterns
@@ -2937,8 +2986,6 @@ static void cont_match(eval_context_t *ctx) {
bool is_match = match(pattern, e, &new_env, &do_gc);
if (do_gc) {
- lbm_uint roots[3] = {orig_env, patterns, e};
- lbm_gc_mark_roots(roots, 3);
gc();
do_gc = false;
new_env = orig_env;
@@ -2949,23 +2996,26 @@ static void cont_match(eval_context_t *ctx) {
}
if (is_match) {
if (check_guard) {
- lbm_value *sptr = stack_reserve(ctx,7);
+ lbm_value *rptr = stack_reserve(ctx,5);
sptr[0] = get_cdr(patterns);
sptr[1] = ctx->curr_env;
- sptr[2] = MATCH;
- sptr[3] = new_env;
- sptr[4] = body;
- sptr[5] = e;
- sptr[6] = MATCH_GUARD;
+ rptr[0] = MATCH;
+ rptr[1] = new_env;
+ rptr[2] = body;
+ rptr[3] = e;
+ rptr[4] = MATCH_GUARD;
ctx->curr_env = new_env;
ctx->curr_exp = n1; // The guard
} else {
+ lbm_stack_drop(&ctx->K, 2);
ctx->curr_env = new_env;
ctx->curr_exp = body;
}
} else {
// set up for checking of next pattern
- stack_push_3(&ctx->K, get_cdr(patterns),orig_env, MATCH);
+ sptr[0] = get_cdr(patterns);
+ sptr[1] = orig_env;
+ stack_push(&ctx->K, MATCH);
// leave r unaltered
ctx->app_cont = true;
}
@@ -3116,12 +3166,11 @@ static void cont_merge_rest(eval_context_t *ctx) {
lbm_value cmp_env = sptr[6];
// Environment should be preallocated already at this point
// and the operations below should never need GC.
- // maybe rewrite this as a more efficient update and
- // a fatal error if that is not possible.
- lbm_value new_env0;
- lbm_value new_env;
- WITH_GC(new_env0, lbm_env_set(cmp_env, par1, lbm_car(a)));
- WITH_GC_RMBR_1(new_env, lbm_env_set(new_env0, par2, lbm_car(b)), new_env0);
+ lbm_value new_env0 = lbm_env_set(cmp_env, par1, lbm_car(a));
+ lbm_value new_env = lbm_env_set(new_env0, par2, lbm_car(b));
+ if (lbm_is_symbol(new_env0) || lbm_is_symbol(new_env)) {
+ error_ctx(ENC_SYM_FATAL_ERROR);
+ }
cmp_env = new_env;
stack_push(&ctx->K, MERGE_REST);
@@ -3233,12 +3282,11 @@ static void cont_merge_layer(eval_context_t *ctx) {
lbm_value par2 = sptr[3];
// Environment should be preallocated already at this point
// and the operations below should never need GC.
- // maybe rewrite this as a more efficient update and
- // a fatal error if that is not possible.
- lbm_value new_env0;
- lbm_value new_env;
- WITH_GC(new_env0, lbm_env_set(cmp_env, par1, lbm_car(a)));
- WITH_GC_RMBR_1(new_env, lbm_env_set(new_env0, par2, lbm_car(b)), new_env0);
+ lbm_value new_env0 = lbm_env_set(cmp_env, par1, lbm_car(a));
+ lbm_value new_env = lbm_env_set(cmp_env, par2, lbm_car(b));
+ if (lbm_is_symbol(new_env0) || lbm_is_symbol(new_env)) {
+ error_ctx(ENC_SYM_FATAL_ERROR);
+ }
cmp_env = new_env;
lbm_uint *merge_cont = stack_reserve(ctx, 11);
@@ -3576,7 +3624,7 @@ static void cont_read_next_token(eval_context_t *ctx) {
if (!lbm_lookup_extension_id(ext_name, &ext_id)) {
error_ctx(ENC_SYM_FATAL_ERROR);
}
- symbol_id = ext_id + EXTENSION_SYMBOLS_START;
+ symbol_id = ext_id;
} else {
error_ctx(ENC_SYM_MERROR);
}
@@ -4289,7 +4337,7 @@ lbm_value append(lbm_value front, lbm_value back) {
lbm_value t0, t1;
- t0 = cons_with_gc(back, ENC_SYM_NIL, ENC_SYM_NIL);
+ t0 = cons_with_gc(back, ENC_SYM_NIL, front);
t1 = cons_with_gc(front, t0, ENC_SYM_NIL);
return cons_with_gc(ENC_SYM_APPEND, t1, ENC_SYM_NIL);
}
@@ -4376,9 +4424,7 @@ static void cont_qq_expand_list(eval_context_t* ctx) {
if (lbm_type_of(car_val) == LBM_TYPE_SYMBOL &&
lbm_dec_sym(car_val) == SYM_COMMA) {
lbm_value tl = cons_with_gc(get_car(cdr_val), ENC_SYM_NIL, ENC_SYM_NIL);
- //WITH_GC(tl, lbm_cons(get_car(cdr_val), ENC_SYM_NIL));
lbm_value tmp = cons_with_gc(ENC_SYM_LIST, tl, ENC_SYM_NIL);
- //WITH_GC_RMBR_1(tmp, lbm_cons(ENC_SYM_LIST, tl), tl);
ctx->r = append(ctx->r, tmp);
ctx->app_cont = true;
return;
diff --git a/lispBM/lispBM/src/extensions.c b/lispBM/lispBM/src/extensions.c
index 869e9345..25035c72 100644
--- a/lispBM/lispBM/src/extensions.c
+++ b/lispBM/lispBM/src/extensions.c
@@ -25,7 +25,6 @@
#include "extensions.h"
-static lbm_uint ext_offset = EXTENSION_SYMBOLS_START;
static lbm_uint ext_max = 0;
static lbm_uint ext_num = 0;
static lbm_uint next_extension_ix = 0;
@@ -64,7 +63,7 @@ lbm_uint lbm_get_num_extensions(void) {
}
extension_fptr lbm_get_extension(lbm_uint sym) {
- lbm_uint ext_next = sym - ext_offset;
+ lbm_uint ext_next = sym - EXTENSION_SYMBOLS_START;
if (ext_next >= ext_max) {
return NULL;
}
@@ -72,7 +71,7 @@ extension_fptr lbm_get_extension(lbm_uint sym) {
}
bool lbm_clr_extension(lbm_uint sym_id) {
- lbm_uint ext_id = sym_id - ext_offset;
+ lbm_uint ext_id = sym_id - EXTENSION_SYMBOLS_START;
if (ext_id >= ext_max) {
return false;
}
@@ -85,7 +84,7 @@ bool lbm_lookup_extension_id(char *sym_str, lbm_uint *ix) {
for (lbm_uint i = 0; i < ext_max; i ++) {
if(extension_table[i].name) {
if (strcmp(extension_table[i].name, sym_str) == 0) {
- *ix = i;
+ *ix = i + EXTENSION_SYMBOLS_START;
return true;
}
}
@@ -100,9 +99,9 @@ bool lbm_add_extension(char *sym_str, extension_fptr ext) {
if (lbm_get_symbol_by_name(sym_str, &symbol)) {
if (lbm_is_extension(lbm_enc_sym(symbol))) {
// update the extension entry.
- if (strcmp(extension_table[symbol - ext_offset].name, sym_str) == 0) {
+ if (strcmp(extension_table[symbol - EXTENSION_SYMBOLS_START].name, sym_str) == 0) {
// Do not replace name ptr.
- extension_table[symbol - ext_offset].fptr = ext;
+ extension_table[symbol - EXTENSION_SYMBOLS_START].fptr = ext;
return true;
}
}
diff --git a/lispBM/lispBM/src/heap.c b/lispBM/lispBM/src/heap.c
index b35eb279..d6fb1b40 100644
--- a/lispBM/lispBM/src/heap.c
+++ b/lispBM/lispBM/src/heap.c
@@ -528,19 +528,19 @@ lbm_value lbm_heap_allocate_cell(lbm_type ptr_type, lbm_value car, lbm_value cdr
res = lbm_heap_state.freelist;
if (lbm_type_of(res) == LBM_TYPE_CONS) {
- lbm_cons_t *rc = lbm_ref_cell(res);
- lbm_heap_state.freelist = rc->cdr;
+ lbm_uint heap_ix = lbm_dec_ptr(res);
+ //lbm_cons_t *rc = lbm_ref_cell(res);
+ lbm_heap_state.freelist = lbm_heap_state.heap[heap_ix].cdr;
lbm_heap_state.num_alloc++;
- rc->car = car;
- rc->cdr = cdr;
-
+ lbm_heap_state.heap[heap_ix].car = car;
+ lbm_heap_state.heap[heap_ix].cdr = cdr;
res = lbm_set_ptr_type(res, ptr_type);
return res;
}
- else if ((lbm_type_of(lbm_heap_state.freelist) == LBM_TYPE_SYMBOL) &&
- (lbm_dec_sym(lbm_heap_state.freelist) == SYM_NIL)) {
+ else if ((lbm_type_of(res) == LBM_TYPE_SYMBOL) &&
+ (lbm_dec_sym(res) == SYM_NIL)) {
// all is as it should be (but no free cells)
return ENC_SYM_MERROR;
}
@@ -691,6 +691,7 @@ void lbm_gc_mark_phase(lbm_value root) {
}
#else
+extern eval_context_t *ctx_running;
void lbm_gc_mark_phase(lbm_value root) {
lbm_stack_t *s = &lbm_heap_state.gc_stack;
@@ -867,7 +868,6 @@ int lbm_gc_sweep_phase(void) {
lbm_heap_state.gc_recovered ++;
}
}
-
return 1;
}
@@ -1152,7 +1152,6 @@ int lbm_heap_allocate_array(lbm_value *res, lbm_uint size){
// Convert a C array into an lbm_array.
// if the array is in LBM_MEMORY, the lifetime will be managed by the GC.
-// TODO: Use lbm_malloc for header data
int lbm_lift_array(lbm_value *value, char *data, lbm_uint num_elt) {
lbm_array_header_t *array = NULL;
@@ -1165,13 +1164,15 @@ int lbm_lift_array(lbm_value *value, char *data, lbm_uint num_elt) {
array = (lbm_array_header_t*)lbm_malloc(sizeof(lbm_array_header_t));
- if (array == NULL) return 0;
+ if (array == NULL) {
+ *value = ENC_SYM_MERROR;
+ return 0;
+ }
array->data = (lbm_uint*)data;
array->size = num_elt;
lbm_set_car(cell, (lbm_uint)array);
- //lbm_set_cdr(cell, lbm_enc_sym(SYM_ARRAY_TYPE));
cell = lbm_set_ptr_type(cell, LBM_TYPE_ARRAY);
*value = cell;
diff --git a/lispBM/lispBM/src/symrepr.c b/lispBM/lispBM/src/symrepr.c
index af3876ac..054c86fa 100644
--- a/lispBM/lispBM/src/symrepr.c
+++ b/lispBM/lispBM/src/symrepr.c
@@ -1,5 +1,5 @@
/*
- Copyright 2018, 2021 2022 Joel Svensson svenssonjoel@yahoo.se
+ Copyright 2018, 2021, 2022, 2024 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
@@ -227,7 +227,6 @@ special_sym const special_symbols[] = {
static lbm_uint *symlist = NULL;
static lbm_uint next_symbol_id = RUNTIME_SYMBOLS_START;
-static lbm_uint next_variable_symbol_id = VARIABLE_SYMBOLS_START;
static lbm_uint symbol_table_size_list = 0;
static lbm_uint symbol_table_size_list_flash = 0;
static lbm_uint symbol_table_size_strings = 0;
@@ -239,7 +238,6 @@ lbm_value symbol_y = ENC_SYM_NIL;
int lbm_symrepr_init(void) {
symlist = NULL;
next_symbol_id = RUNTIME_SYMBOLS_START;
- next_variable_symbol_id = VARIABLE_SYMBOLS_START;
symbol_table_size_list = 0;
symbol_table_size_list_flash = 0;
symbol_table_size_strings = 0;
@@ -277,21 +275,28 @@ const char *lookup_symrepr_name_memory(lbm_uint id) {
// Lookup symbol name given a symbol id
const char *lbm_get_name_by_symbol(lbm_uint id) {
- if (id < SPECIAL_SYMBOLS_END) {
+ lbm_uint sym_kind = SYMBOL_KIND(id);
+ switch (sym_kind) {
+ case SYMBOL_KIND_SPECIAL: /* fall through */
+ case SYMBOL_KIND_FUNDAMENTAL:
+ case SYMBOL_KIND_APPFUN:
for (unsigned int i = 0; i < NUM_SPECIAL_SYMBOLS; i ++) {
if (id == special_symbols[i].id) {
return (special_symbols[i].name);
}
}
return NULL;
- } else if (id - EXTENSION_SYMBOLS_START < EXTENSION_SYMBOLS_END) {
+ break;
+ case SYMBOL_KIND_EXTENSION: {
unsigned int ext_id = id - EXTENSION_SYMBOLS_START;
if (ext_id < lbm_get_max_extensions()) {
- return extension_table[ext_id].name;
+ return extension_table[ext_id].name;
}
return NULL;
+ } break;
+ default:
+ return lookup_symrepr_name_memory(id);
}
- return lookup_symrepr_name_memory(id);
}
lbm_uint *lbm_get_symbol_list_entry_by_name(char *name) {
@@ -465,10 +470,6 @@ lbm_uint lbm_get_symbol_table_size_names_flash(void) {
return symbol_table_size_strings_flash * sizeof(lbm_uint);
}
-lbm_uint lbm_get_num_variables(void) {
- return next_variable_symbol_id - VARIABLE_SYMBOLS_START;
-}
-
bool lbm_symbol_in_flash(char *str) {
return !lbm_memory_ptr_inside((lbm_uint*)str);
}
diff --git a/lispBM/lispBM/tests/Makefile b/lispBM/lispBM/tests/Makefile
index 17143b27..50e88028 100644
--- a/lispBM/lispBM/tests/Makefile
+++ b/lispBM/lispBM/tests/Makefile
@@ -17,6 +17,11 @@ OBJ = obj
SOURCES = $(wildcard *.c)
EXECS = $(patsubst %.c, %.exe, $(SOURCES))
+gc: CCFLAGS += -m32 -DLBM_ALWAYS_GC
+gc: $(EXECS)
+ mv test_lisp_code_cps.exe test_lisp_code_cps
+
+
all: CCFLAGS += -m32
all: $(EXECS)
mv test_lisp_code_cps.exe test_lisp_code_cps
diff --git a/lispBM/lispBM/tests/run_tests_gc.sh b/lispBM/lispBM/tests/run_tests_gc.sh
new file mode 100755
index 00000000..2f08327a
--- /dev/null
+++ b/lispBM/lispBM/tests/run_tests_gc.sh
@@ -0,0 +1,147 @@
+#!/bin/bash
+
+echo "BUILDING"
+
+make clean
+make gc
+
+echo "PERFORMING TESTS:"
+
+expected_fails=("test_lisp_code_cps -t 360 -h 1024 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -s -h 1024 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -h 512 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -s -h 512 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -i -h 1024 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -i -s -h 1024 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -i -h 512 test_take_iota_0.lisp"
+ "test_lisp_code_cps -t 360 -i -s -h 512 test_take_iota_0.lisp"
+ )
+
+
+success_count=0
+fail_count=0
+failing_tests=()
+result=0
+
+for exe in *.exe; do
+
+ if [ "$exe" = "test_gensym.exe" ]; then
+ continue
+ fi
+
+ ./$exe
+
+ result=$?
+
+ echo "------------------------------------------------------------"
+ if [ $result -eq 1 ]
+ then
+ success_count=$((success_count+1))
+ echo $exe SUCCESS
+ else
+
+ fail_count=$((fail_count+1))
+ echo $exe FAILED
+ fi
+ echo "------------------------------------------------------------"
+done
+
+test_config=("-t 360 -h 32768"
+ "-t 360 -i -h 32768"
+ "-t 360 -s -h 32768"
+ "-t 360 -i -s -h 32768"
+ "-t 360 -h 16384"
+ "-t 360 -i -h 16384"
+ "-t 360 -s -h 16384"
+ "-t 360 -i -s -h 16384"
+ "-t 360 -h 8192"
+ "-t 360 -i -h 8192"
+ "-t 360 -s -h 8192"
+ "-t 360 -i -s -h 8192"
+ "-t 360 -h 4096"
+ "-t 360 -i -h 4096"
+ "-t 360 -s -h 4096"
+ "-t 360 -i -s -h 4096"
+ "-t 360 -h 2048"
+ "-t 360 -i -h 2048"
+ "-t 360 -s -h 2048"
+ "-t 360 -i -s -h 2048"
+ "-t 360 -h 1024"
+ "-t 360 -i -h 1024"
+ "-t 360 -s -h 1024"
+ "-t 360 -i -s -h 1024"
+ "-t 360 -h 512"
+ "-t 360 -i -h 512"
+ "-t 360 -s -h 512"
+ "-t 360 -i -s -h 512")
+
+#"test_lisp_code_cps_nc"
+for prg in "test_lisp_code_cps" ; do
+ for arg in "${test_config[@]}"; do
+ for lisp in *.lisp; do
+
+ ./$prg $arg $lisp
+
+ result=$?
+
+ echo "------------------------------------------------------------"
+ #echo $arg
+ if [ $result -eq 1 ]
+ then
+ success_count=$((success_count+1))
+ echo $lisp SUCCESS
+ else
+
+ #!/bin/bash
+ # foo=('foo bar' 'foo baz' 'bar baz')
+ # bar=$(printf ",%s" "${foo[@]}")
+ # bar=${bar:1}
+
+ # echo $bar
+ str=$(printf "%s " "$prg $arg $lisp")
+ #echo $str
+
+ failing_tests+=("$prg $arg $lisp")
+ fail_count=$((fail_count+1))
+ #echo $failing_tests
+
+ echo $lisp FAILED
+ fi
+ echo "------------------------------------------------------------"
+ done
+ done
+done
+
+# echo -e $failing_tests
+
+expected_count=0
+
+for (( i = 0; i < ${#failing_tests[@]}; i++ ))
+do
+ expected=false
+ for (( j = 0; j < ${#expected_fails[@]}; j++))
+ do
+
+ if [[ "${failing_tests[$i]}" == "${expected_fails[$j]}" ]] ;
+ then
+ expected=true
+ fi
+ done
+ if $expected ; then
+ expected_count=$((expected_count+1))
+ echo "(OK - expected to fail)" ${failing_tests[$i]}
+ else
+ echo "(FAILURE)" ${failing_tests[$i]}
+ fi
+done
+
+
+echo Tests passed: $success_count
+echo Tests failed: $fail_count
+echo Expected fails: $expected_count
+echo Actual fails: $((fail_count - expected_count))
+
+if [ $((fail_count - expected_count)) -gt 0 ]
+then
+ exit 1
+fi
diff --git a/lispBM/lispBM/tests/test_lisp_code_cps.c b/lispBM/lispBM/tests/test_lisp_code_cps.c
index 40647c06..8b401332 100644
--- a/lispBM/lispBM/tests/test_lisp_code_cps.c
+++ b/lispBM/lispBM/tests/test_lisp_code_cps.c
@@ -49,6 +49,7 @@
lbm_extension_t extensions[EXTENSION_STORAGE_SIZE];
lbm_uint constants_memory[CONSTANT_MEMORY_SIZE];
+static uint32_t timeout = 10;
void const_heap_init(void) {
for (int i = 0; i < CONSTANT_MEMORY_SIZE; i ++) {
@@ -338,6 +339,7 @@ LBM_EXTENSION(ext_check, args, argn) {
}
int res = lbm_print_value(output, 128, t);
+ printf("Checking result value: %s\n", output);
if (checks == 2) {
experiment_done = true;
@@ -401,8 +403,11 @@ int main(int argc, char **argv) {
int c;
opterr = 1;
- while (( c = getopt(argc, argv, "igsch:")) != -1) {
+ while (( c = getopt(argc, argv, "igsch:t:")) != -1) {
switch (c) {
+ case 't':
+ timeout = (uint32_t)atoi((char *)optarg);
+ break;
case 'h':
heap_size = (unsigned int)atoi((char *)optarg);
break;
@@ -752,15 +757,19 @@ int main(int argc, char **argv) {
}
}
printf("Program loaded\n");
- int i = 0;
+ uint32_t i = 0;
+ bool timed_out = false;
while (!experiment_done) {
- if (i == 10000) break;
+ if (i >= timeout * 1000) {
+ timed_out = true;
+ break;
+ }
sleep_callback(1000);
i ++;
}
- if (i == 10000) {
- printf ("experiment failed due to taking longer than 10 seconds\n");
+ if (timed_out) {
+ printf ("experiment failed due to taking longer than %u seconds\n", timeout);
experiment_success = false;
return FAIL;
}
@@ -778,6 +787,7 @@ int main(int argc, char **argv) {
free(heap_storage);
printf("Experiment done: ");
+ printf("Check was executed %u times\n", checks);
if (experiment_success) {
printf("SUCCESS\n");
return 1;
diff --git a/lispBM/lispBM/tests/test_match_guard_10.lisp b/lispBM/lispBM/tests/test_match_guard_10.lisp
new file mode 100644
index 00000000..fb87e7dd
--- /dev/null
+++ b/lispBM/lispBM/tests/test_match_guard_10.lisp
@@ -0,0 +1,19 @@
+
+(defun larger ( x ) {
+ (gc)
+ (> x 10)
+ })
+
+(defun smaller ( x ) {
+ (gc)
+ (< x 10)
+ })
+
+(defun f (x)
+ (match x
+ ( ((? x) . ((? y) . _)) (smaller x) (list y 'smaller))
+ ( ((? x) . ((? y) . _)) (larger x) (list y 'larger))
+ ( _ 'whatever)))
+
+(check (and (eq (f '(0 1 2 3)) '(1 smaller))
+ (eq (f '(11 9 8 7)) '(9 larger))))
diff --git a/lispBM/lispBM/tests/test_match_guard_11.lisp b/lispBM/lispBM/tests/test_match_guard_11.lisp
new file mode 100644
index 00000000..6006460c
--- /dev/null
+++ b/lispBM/lispBM/tests/test_match_guard_11.lisp
@@ -0,0 +1,21 @@
+
+(defun larger ( x ) {
+ (gc)
+ (> x 10)
+ })
+
+(defun smaller ( x ) {
+ (gc)
+ (< x 10)
+ })
+
+(defun f (x)
+ (atomic
+ (var z "apa")
+ (match x
+ ( ((? x) . ((? y) . _)) (smaller z) (list y 'smaller))
+ ( ((? x) . ((? y) . _)) (larger z) (list y 'larger))
+ ( _ 'whatever))))
+
+(check (and (eq (f '(0 1 2 3)) 'whatever)
+ (eq (f '(11 9 8 7)) 'whatever)))