Merge commit '78ca6b2cb3358e39e729507b50c7eaefbbaaf978'

This commit is contained in:
Benjamin Vedder 2022-02-21 20:02:27 +01:00
commit 84daf396e0
13 changed files with 181 additions and 86 deletions

View File

@ -3,6 +3,8 @@
\section sec_intro Introduction
WORK IN PROGRESS
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

View File

@ -1066,6 +1066,92 @@ Example where a process waits for an i28
\endcode
---
\section sec_macros Macros
lispBM macros are created using the <code>macro</code> keyword. A macro
is quite similar to <a href="lambda">lambda</a> in lispBM except that
arguments are passed in unevaluated. Together with the code-splicing
capabilities given by <a href="sec_quote">quasiquotation</a>, this
provides a powerful code-generation tool.
A macro application is run through the interpreted two times. Once to
evaluate the body of the macro on the unevaluated arguments. The result of
this first application should be a program. The resulting program then goes
through the interpreter again to compute final values.
Given this repeated evaluation, macros is not a performance boost in lispbm.
It is really a feature to invent new programming abstractions in cases where
it is ok to pay a little for the overhead for benefits in expressivity.
<a name="macro"> <h3>macro</h3> </a>
The form of a <code>macro</code> expression is: <code>(macro args body)</code>
\note
Some lisps provide a <code>defun</code> operation for defining functions
with a bit less typing. The example below defines a <code>defun</code> macro.
\code
(define defun (macro (name args body)
`(define ,name (lambda ,args ,body))))
\endcode
With this macro the function <code>inc</code> that adds 1 to its argument
can be defined as:
\code
(defun inc (x) (+ x 1))
\endcode
---
\section sec_cc Call With Current Continuation
"Call with current continuation" is called <code>call-cc</code> in LBM.
Call with current continuation saves the "current continuation", which encodes what
the evaluator will do next, into an object in the language. This encoded
continuation object behaves as a function taking one argument.
The <code>call-cc</code> should be given a function, <code>f</code>, as the single argument. This
function, <code>f</code>, should also take a single argument, the continuation.
At any point in the body of <code>f</code> the continuation can be applied to
a value, in essense replacing the entire <code>call-cc</code> with that value.
\note
The example below creates a macro for a <code>progn</code> facility that
allows returning at an arbitrary point.
\code
(define do (macro (body)
`(call-cc (lambda (return) (progn ,@body)))))
\endcode
The example using <code>do</code> below makes use of <code>print</code> which is not a
built-in feature of lispBM. There are just to many different ways a programmer may
want to implement <code>print</code> on an microcontroller. Use the lispBM extensions
framework to implement your own version of <code>print</code>
\code
(do ((print 10)
(return 't)
(print 20)))
\endcode
In the example above only "10" will be printed.
Below is an example that conditionally returns.
\code
(define f (lambda (x)
(do ((print "hello world" \#newline)
(if (= x 1)
(return 't)
nil)
(print "Gizmo!" \#newline)))))
\endcode
---
\section sec_unparse Unparsable symbols

View File

@ -25,10 +25,13 @@
/** LBM minor version */
#define LBM_MINOR_VERSION 4
/** LBM patch revision */
#define LBM_PATCH_VERSION 0
#define LBM_PATCH_VERSION 1
/* Change log */
/* Feb 21 2022: Version (0.4.1)
- Bug fixes in gc related to arrays
*/
/* Feb 20 2022: Version (0.4.0)
- Adds support for macros.

View File

@ -57,8 +57,9 @@
#define SYM_SEND 0x14
#define SYM_RECEIVE 0x15
#define SYM_MACRO 0x16
#define SYM_CALLCC 0x17
#define SYM_CONT 0x18
#define SYM_MACRO_EXPAND 0x17
#define SYM_CALLCC 0x18
#define SYM_CONT 0x19
#define SYM_ARRAY_TYPE 0x20
#define SYM_BOXED_I_TYPE 0x21

View File

@ -951,6 +951,7 @@ static inline void eval_progn(eval_context_t *ctx) {
lbm_value env = ctx->curr_env;
if (lbm_type_of(exps) == LBM_VAL_TYPE_SYMBOL && exps == NIL) {
printf("the nil case\n");
ctx->r = NIL;
ctx->app_cont = true;
return;
@ -1173,6 +1174,7 @@ static inline void cont_progn_rest(eval_context_t *ctx) {
lbm_value env;
lbm_pop_u32_2(&ctx->K, &rest, &env);
if (lbm_type_of(rest) == LBM_VAL_TYPE_SYMBOL && rest == NIL) {
printf("cont: rest is nil\n");
ctx->app_cont = true;
return;
}

View File

@ -57,22 +57,22 @@ bool lbm_array_extensions_init(void) {
}
}
bool res = true;
res = res && lbm_add_extension("unsafe-free", array_extension_unsafe_free_array);
res = res && lbm_add_extension("buffer-append-i8", array_extension_buffer_append_i8);
res = res && lbm_add_extension("buffer-append-i16", array_extension_buffer_append_i16);
res = res && lbm_add_extension("buffer-append-i32", array_extension_buffer_append_i32);
res = res && lbm_add_extension("buffer-append-u8", array_extension_buffer_append_u8);
res = res && lbm_add_extension("buffer-append-u16", array_extension_buffer_append_u16);
res = res && lbm_add_extension("buffer-append-u32", array_extension_buffer_append_u32);
res = res && lbm_add_extension("buffer-append-f32", array_extension_buffer_append_f32);
res = res && lbm_add_extension("free", array_extension_unsafe_free_array);
res = res && lbm_add_extension("bufset-i8", array_extension_buffer_append_i8);
res = res && lbm_add_extension("bufset-i16", array_extension_buffer_append_i16);
res = res && lbm_add_extension("bufset-i32", array_extension_buffer_append_i32);
res = res && lbm_add_extension("bufset-u8", array_extension_buffer_append_u8);
res = res && lbm_add_extension("bufset-u16", array_extension_buffer_append_u16);
res = res && lbm_add_extension("bufset-u32", array_extension_buffer_append_u32);
res = res && lbm_add_extension("bufset-f32", array_extension_buffer_append_f32);
res = res && lbm_add_extension("buffer-get-i8", array_extension_buffer_get_i8);
res = res && lbm_add_extension("buffer-get-i16", array_extension_buffer_get_i16);
res = res && lbm_add_extension("buffer-get-i32", array_extension_buffer_get_i32);
res = res && lbm_add_extension("buffer-get-u8", array_extension_buffer_get_u8);
res = res && lbm_add_extension("buffer-get-u16", array_extension_buffer_get_u16);
res = res && lbm_add_extension("buffer-get-u32", array_extension_buffer_get_u32);
res = res && lbm_add_extension("buffer-get-f32", array_extension_buffer_get_f32);
res = res && lbm_add_extension("bufget-i8", array_extension_buffer_get_i8);
res = res && lbm_add_extension("bufget-i16", array_extension_buffer_get_i16);
res = res && lbm_add_extension("bufget-i32", array_extension_buffer_get_i32);
res = res && lbm_add_extension("bufget-u8", array_extension_buffer_get_u8);
res = res && lbm_add_extension("bufget-u16", array_extension_buffer_get_u16);
res = res && lbm_add_extension("bufget-u32", array_extension_buffer_get_u32);
res = res && lbm_add_extension("bufget-f32", array_extension_buffer_get_f32);
return res;
}

View File

@ -24,7 +24,7 @@
#include "symrepr.h"
#define NUM_SPECIAL_SYMBOLS 109
#define NUM_SPECIAL_SYMBOLS 110
#define NAME 0
#define ID 1
#define NEXT 2
@ -53,6 +53,7 @@ special_sym const special_symbols[NUM_SPECIAL_SYMBOLS] = {
{"send" , SYM_SEND},
{"recv" , SYM_RECEIVE},
{"macro" , SYM_MACRO},
{"macro-expand" , SYM_MACRO_EXPAND},
{"call-cc" , SYM_CALLCC},
{"continuation" , SYM_CONT},
@ -198,7 +199,7 @@ 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 < NUM_SPECIAL_SYMBOLS) {
if (id < SPECIAL_SYMBOLS_END) {
for (int i = 0; i < NUM_SPECIAL_SYMBOLS; i ++) {
if (id == special_symbols[i].id) {
return (special_symbols[i].name);

View File

@ -1,23 +1,23 @@
(define arr (array-create type-byte 10))
(buffer-append-i8 arr 70 0)
(buffer-append-i8 arr 69 1)
(buffer-append-i8 arr 68 2)
(buffer-append-i8 arr 67 3)
(buffer-append-i8 arr 66 4)
(buffer-append-i8 arr 65 5)
(buffer-append-i8 arr 64 6)
(buffer-append-i8 arr 63 7)
(buffer-append-i8 arr 62 8)
(buffer-append-i8 arr 61 9)
(bufset-i8 arr 70 0)
(bufset-i8 arr 69 1)
(bufset-i8 arr 68 2)
(bufset-i8 arr 67 3)
(bufset-i8 arr 66 4)
(bufset-i8 arr 65 5)
(bufset-i8 arr 64 6)
(bufset-i8 arr 63 7)
(bufset-i8 arr 62 8)
(bufset-i8 arr 61 9)
(and (= (buffer-get-i8 arr 0) 70)
(= (buffer-get-i8 arr 1) 69)
(= (buffer-get-i8 arr 2) 68)
(= (buffer-get-i8 arr 3) 67)
(= (buffer-get-i8 arr 4) 66)
(= (buffer-get-i8 arr 5) 65)
(= (buffer-get-i8 arr 6) 64)
(= (buffer-get-i8 arr 7) 63)
(= (buffer-get-i8 arr 8) 62)
(= (buffer-get-i8 arr 9) 61))
(and (= (bufget-i8 arr 0) 70)
(= (bufget-i8 arr 1) 69)
(= (bufget-i8 arr 2) 68)
(= (bufget-i8 arr 3) 67)
(= (bufget-i8 arr 4) 66)
(= (bufget-i8 arr 5) 65)
(= (bufget-i8 arr 6) 64)
(= (bufget-i8 arr 7) 63)
(= (bufget-i8 arr 8) 62)
(= (bufget-i8 arr 9) 61))

View File

@ -1,24 +1,24 @@
(define arr (array-create type-byte 10))
(buffer-append-u8 arr 70 0)
(buffer-append-u8 arr 69 1)
(buffer-append-u8 arr 68 2)
(buffer-append-u8 arr 67 3)
(buffer-append-u8 arr 66 4)
(buffer-append-u8 arr 65 5)
(buffer-append-u8 arr 64 6)
(buffer-append-u8 arr 63 7)
(buffer-append-u8 arr 62 8)
(buffer-append-u8 arr 61 9)
(bufset-u8 arr 70 0)
(bufset-u8 arr 69 1)
(bufset-u8 arr 68 2)
(bufset-u8 arr 67 3)
(bufset-u8 arr 66 4)
(bufset-u8 arr 65 5)
(bufset-u8 arr 64 6)
(bufset-u8 arr 63 7)
(bufset-u8 arr 62 8)
(bufset-u8 arr 61 9)
(= (buffer-get-u8 arr 0) 70u28)
(and (num-eq (buffer-get-u8 arr 0) 70)
(num-eq (buffer-get-u8 arr 1) 69)
(num-eq (buffer-get-u8 arr 2) 68)
(num-eq (buffer-get-u8 arr 3) 67)
(num-eq (buffer-get-u8 arr 4) 66)
(num-eq (buffer-get-u8 arr 5) 65)
(num-eq (buffer-get-u8 arr 6) 64)
(num-eq (buffer-get-u8 arr 7) 63)
(num-eq (buffer-get-u8 arr 8) 62)
(num-eq (buffer-get-u8 arr 9) 61))
(= (bufget-u8 arr 0) 70u28)
(and (num-eq (bufget-u8 arr 0) 70)
(num-eq (bufget-u8 arr 1) 69)
(num-eq (bufget-u8 arr 2) 68)
(num-eq (bufget-u8 arr 3) 67)
(num-eq (bufget-u8 arr 4) 66)
(num-eq (bufget-u8 arr 5) 65)
(num-eq (bufget-u8 arr 6) 64)
(num-eq (bufget-u8 arr 7) 63)
(num-eq (bufget-u8 arr 8) 62)
(num-eq (bufget-u8 arr 9) 61))

View File

@ -1,14 +1,14 @@
(define arr (array-create type-byte 16))
(buffer-append-u32 arr 16777215 0)
(buffer-append-u32 arr 0xFFFFFFFF 4)
(buffer-append-u32 arr 10 8)
(buffer-append-u32 arr 0xDEADBEEF 12)
(bufset-u32 arr 16777215 0)
(bufset-u32 arr 0xFFFFFFFF 4)
(bufset-u32 arr 10 8)
(bufset-u32 arr 0xDEADBEEF 12)
(and (num-eq (buffer-get-u32 arr 0) 16777215)
(num-eq (buffer-get-u32 arr 4) 0xFFFFFFFF)
(num-eq (buffer-get-u32 arr 8) 10)
(num-eq (buffer-get-u32 arr 12) 0xDEADBEEF))
(and (num-eq (bufget-u32 arr 0) 16777215)
(num-eq (bufget-u32 arr 4) 0xFFFFFFFF)
(num-eq (bufget-u32 arr 8) 10)
(num-eq (bufget-u32 arr 12) 0xDEADBEEF))

View File

@ -1,11 +1,11 @@
(define arr (array-create type-byte 16))
(buffer-append-i32 arr 16777215 0)
(buffer-append-i32 arr 0xFFFFFFFF 4)
(buffer-append-i32 arr 10 8)
(buffer-append-i32 arr 0xDEADBEEF 12)
(bufset-i32 arr 16777215 0)
(bufset-i32 arr 0xFFFFFFFF 4)
(bufset-i32 arr 10 8)
(bufset-i32 arr 0xDEADBEEF 12)
(and (num-eq (buffer-get-i32 arr 0) 16777215)
(num-eq (buffer-get-i32 arr 4) 0xFFFFFFFF)
(num-eq (buffer-get-i32 arr 8) 10)
(num-eq (buffer-get-i32 arr 12) 0xDEADBEEF))
(and (num-eq (bufget-i32 arr 0) 16777215)
(num-eq (bufget-i32 arr 4) 0xFFFFFFFF)
(num-eq (bufget-i32 arr 8) 10)
(num-eq (bufget-i32 arr 12) 0xDEADBEEF))

View File

@ -1,11 +1,11 @@
(define arr (array-create type-byte 16))
(buffer-append-f32 arr 3.14 0)
(buffer-append-f32 arr 666.666 4)
(buffer-append-f32 arr 100 8)
(buffer-append-f32 arr 42 12)
(bufset-f32 arr 3.14 0)
(bufset-f32 arr 666.666 4)
(bufset-f32 arr 100 8)
(bufset-f32 arr 42 12)
(and (num-eq (buffer-get-f32 arr 0) 3.14)
(num-eq (buffer-get-f32 arr 4) 666.666)
(num-eq (buffer-get-f32 arr 8) 100)
(num-eq (buffer-get-f32 arr 12) 42))
(and (num-eq (bufget-f32 arr 0) 3.14)
(num-eq (bufget-f32 arr 4) 666.666)
(num-eq (bufget-f32 arr 8) 100)
(num-eq (bufget-f32 arr 12) 42))

View File

@ -1,7 +1,7 @@
(define arr (array-create type-byte 16))
(unsafe-free arr)
(free arr)
(and (= (car arr) nil)
(= (cdr arr) nil))