altos/lisp: add length, pack, unpack and flush
authorKeith Packard <keithp@keithp.com>
Fri, 11 Nov 2016 08:28:31 +0000 (00:28 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 20 Feb 2017 19:16:50 +0000 (11:16 -0800)
lots more builtins

Signed-off-by: Keith Packard <keithp@keithp.com>
src/lambdakey-v1.0/ao_lisp_os.h
src/lisp/ao_lisp.h
src/lisp/ao_lisp_builtin.c
src/lisp/ao_lisp_cons.c
src/lisp/ao_lisp_lambda.c
src/lisp/ao_lisp_make_const.c
src/lisp/ao_lisp_os.h
src/lisp/ao_lisp_string.c
src/test/ao_lisp_os.h

index df158f6a06671f0f83b3acebe7893b80f5571230..1993ac442d86532a79a80dc4839cf7d2b0806f18 100644 (file)
@@ -35,6 +35,12 @@ ao_lisp_getc() {
        return c;
 }
 
+static inline void
+ao_lisp_os_flush(void)
+{
+       flush();
+}
+
 static inline void
 ao_lisp_abort(void)
 {
index 60a97f2c9d98ca96a83fd3b62e7dc7cc16fa237c..86a5ddcff018f4a2feb0e33c42a5f9de8d400432 100644 (file)
@@ -36,10 +36,14 @@ extern uint8_t ao_lisp_const[AO_LISP_POOL_CONST];
 #define _ao_lisp_atom_cdr      _atom("cdr")
 #define _ao_lisp_atom_cons     _atom("cons")
 #define _ao_lisp_atom_last     _atom("last")
+#define _ao_lisp_atom_length   _atom("length")
 #define _ao_lisp_atom_cond     _atom("cond")
 #define _ao_lisp_atom_lambda   _atom("lambda")
 #define _ao_lisp_atom_led      _atom("led")
 #define _ao_lisp_atom_delay    _atom("delay")
+#define _ao_lisp_atom_pack     _atom("pack")
+#define _ao_lisp_atom_unpack   _atom("unpack")
+#define _ao_lisp_atom_flush    _atom("flush")
 #define _ao_lisp_atom_eval     _atom("eval")
 #define _ao_lisp_atom_read     _atom("read")
 #define _ao_lisp_atom_eof      _atom("eof")
@@ -215,6 +219,7 @@ enum ao_lisp_builtin_id {
        builtin_cdr,
        builtin_cons,
        builtin_last,
+       builtin_length,
        builtin_quote,
        builtin_set,
        builtin_setq,
@@ -233,6 +238,9 @@ enum ao_lisp_builtin_id {
        builtin_greater,
        builtin_less_equal,
        builtin_greater_equal,
+       builtin_pack,
+       builtin_unpack,
+       builtin_flush,
        builtin_delay,
        builtin_led,
        _builtin_last
@@ -409,6 +417,9 @@ ao_lisp_cons_print(ao_poly);
 void
 ao_lisp_cons_patom(ao_poly);
 
+int
+ao_lisp_cons_length(struct ao_lisp_cons *cons);
+
 /* string */
 extern const struct ao_lisp_type ao_lisp_string_type;
 
@@ -421,6 +432,12 @@ ao_lisp_string_copy(char *a);
 char *
 ao_lisp_string_cat(char *a, char *b);
 
+ao_poly
+ao_lisp_string_pack(struct ao_lisp_cons *cons);
+
+ao_poly
+ao_lisp_string_unpack(char *a);
+
 void
 ao_lisp_string_print(ao_poly s);
 
index 57d9ee10edd1ecca5869ba066280a35bcf684267..30631980500df974f6a6a9cb4a58f469c5f3a072 100644 (file)
@@ -58,6 +58,7 @@ static const ao_poly builtin_names[] = {
        [builtin_cdr] = _ao_lisp_atom_cdr,
        [builtin_cons] = _ao_lisp_atom_cons,
        [builtin_last] = _ao_lisp_atom_last,
+       [builtin_length] = _ao_lisp_atom_length,
        [builtin_quote] = _ao_lisp_atom_quote,
        [builtin_set] = _ao_lisp_atom_set,
        [builtin_setq] = _ao_lisp_atom_setq,
@@ -76,6 +77,9 @@ static const ao_poly builtin_names[] = {
        [builtin_greater] = _ao_lisp_atom_3e,
        [builtin_less_equal] = _ao_lisp_atom_3c3d,
        [builtin_greater_equal] = _ao_lisp_atom_3e3d,
+       [builtin_pack] = _ao_lisp_atom_pack,
+       [builtin_unpack] = _ao_lisp_atom_unpack,
+       [builtin_flush] = _ao_lisp_atom_flush,
        [builtin_delay] = _ao_lisp_atom_delay,
        [builtin_led] = _ao_lisp_atom_led,
 };
@@ -200,6 +204,16 @@ ao_lisp_last(struct ao_lisp_cons *cons)
        return AO_LISP_NIL;
 }
 
+ao_poly
+ao_lisp_length(struct ao_lisp_cons *cons)
+{
+       if (!ao_lisp_check_argc(_ao_lisp_atom_last, cons, 1, 1))
+               return AO_LISP_NIL;
+       if (!ao_lisp_check_argt(_ao_lisp_atom_last, cons, 0, AO_LISP_CONS, 1))
+               return AO_LISP_NIL;
+       return ao_lisp_int_poly(ao_lisp_cons_length(ao_lisp_poly_cons(ao_lisp_arg(cons, 0))));
+}
+
 ao_poly
 ao_lisp_quote(struct ao_lisp_cons *cons)
 {
@@ -470,6 +484,35 @@ ao_lisp_greater_equal(struct ao_lisp_cons *cons)
        return ao_lisp_compare(cons, builtin_greater_equal);
 }
 
+ao_poly
+ao_lisp_pack(struct ao_lisp_cons *cons)
+{
+       if (!ao_lisp_check_argc(_ao_lisp_atom_pack, cons, 1, 1))
+               return AO_LISP_NIL;
+       if (!ao_lisp_check_argt(_ao_lisp_atom_pack, cons, 0, AO_LISP_CONS, 1))
+               return AO_LISP_NIL;
+       return ao_lisp_string_pack(ao_lisp_poly_cons(ao_lisp_arg(cons, 0)));
+}
+
+ao_poly
+ao_lisp_unpack(struct ao_lisp_cons *cons)
+{
+       if (!ao_lisp_check_argc(_ao_lisp_atom_unpack, cons, 1, 1))
+               return AO_LISP_NIL;
+       if (!ao_lisp_check_argt(_ao_lisp_atom_unpack, cons, 0, AO_LISP_STRING, 0))
+               return AO_LISP_NIL;
+       return ao_lisp_string_unpack(ao_lisp_poly_string(ao_lisp_arg(cons, 0)));
+}
+
+ao_poly
+ao_lisp_flush(struct ao_lisp_cons *cons)
+{
+       if (!ao_lisp_check_argc(_ao_lisp_atom_flush, cons, 0, 0))
+               return AO_LISP_NIL;
+       ao_lisp_os_flush();
+       return _ao_lisp_atom_t;
+}
+
 ao_poly
 ao_lisp_led(struct ao_lisp_cons *cons)
 {
@@ -524,6 +567,7 @@ const ao_lisp_func_t ao_lisp_builtins[] = {
        [builtin_cdr] = ao_lisp_cdr,
        [builtin_cons] = ao_lisp_cons,
        [builtin_last] = ao_lisp_last,
+       [builtin_length] = ao_lisp_length,
        [builtin_quote] = ao_lisp_quote,
        [builtin_set] = ao_lisp_set,
        [builtin_setq] = ao_lisp_setq,
@@ -542,6 +586,9 @@ const ao_lisp_func_t ao_lisp_builtins[] = {
        [builtin_greater] = ao_lisp_greater,
        [builtin_less_equal] = ao_lisp_less_equal,
        [builtin_greater_equal] = ao_lisp_greater_equal,
+       [builtin_pack] = ao_lisp_pack,
+       [builtin_unpack] = ao_lisp_unpack,
+       [builtin_flush] = ao_lisp_flush,
        [builtin_led] = ao_lisp_led,
        [builtin_delay] = ao_lisp_delay,
 };
index cd8a8d1d03b9920716fece9c834e101f3d70b55f..b75ffaa0d611ffa5427e7b191d4d68d996e74534 100644 (file)
@@ -107,3 +107,14 @@ ao_lisp_cons_patom(ao_poly c)
                cons = ao_lisp_poly_cons(cons->cdr);
        }
 }
+
+int
+ao_lisp_cons_length(struct ao_lisp_cons *cons)
+{
+       int     len = 0;
+       while (cons) {
+               len++;
+               cons = ao_lisp_poly_cons(cons->cdr);
+       }
+       return len;
+}
index 8eafb18794baf48cbf5e2f20a3cf7f9f981d9ac0..c53a38fd687f99533d4e7075082967ce99e87bde 100644 (file)
@@ -49,17 +49,6 @@ const struct ao_lisp_type ao_lisp_lambda_type = {
        .move = lambda_move,
 };
 
-static int
-ao_lisp_cons_length(struct ao_lisp_cons *cons)
-{
-       int     len = 0;
-       while (cons) {
-               len++;
-               cons = ao_lisp_poly_cons(cons->cdr);
-       }
-       return len;
-}
-
 void
 ao_lisp_lambda_print(ao_poly poly)
 {
index 4fc43e583b6ca50f16d3f48cf264d2a23af9d650..0b3e25a6df079787182787abecf0dc120d1b07ae 100644 (file)
@@ -43,6 +43,7 @@ struct builtin_func funcs[] = {
        "cdr",          AO_LISP_FUNC_LAMBDA,    builtin_cdr,
        "cons",         AO_LISP_FUNC_LAMBDA,    builtin_cons,
        "last",         AO_LISP_FUNC_LAMBDA,    builtin_last,
+       "length",       AO_LISP_FUNC_LAMBDA,    builtin_length,
        "quote",        AO_LISP_FUNC_NLAMBDA,   builtin_quote,
        "set",          AO_LISP_FUNC_LAMBDA,    builtin_set,
        "setq",         AO_LISP_FUNC_MACRO,     builtin_setq,
@@ -61,6 +62,9 @@ struct builtin_func funcs[] = {
        ">",            AO_LISP_FUNC_LEXPR,     builtin_greater,
        "<=",           AO_LISP_FUNC_LEXPR,     builtin_less_equal,
        ">=",           AO_LISP_FUNC_LEXPR,     builtin_greater_equal,
+       "pack",         AO_LISP_FUNC_LAMBDA,    builtin_pack,
+       "unpack",       AO_LISP_FUNC_LAMBDA,    builtin_unpack,
+       "flush",        AO_LISP_FUNC_LAMBDA,    builtin_flush,
        "delay",        AO_LISP_FUNC_LAMBDA,    builtin_delay,
        "led",          AO_LISP_FUNC_LEXPR,     builtin_led,
 };
index 55ffed50361cf6a31cd33e9712f43e1bd301f62b..b7bf7a2cd825385abdfb9478a5bed5e1293cd3c7 100644 (file)
@@ -27,6 +27,11 @@ ao_lisp_getc() {
        return getchar();
 }
 
+static inline void
+ao_lisp_os_flush() {
+       fflush(stdout);
+}
+
 static inline void
 ao_lisp_abort(void)
 {
index 0064064cfe07cfc22730b7ac1f369b5240a23633..9ee1a7dd0b0e595a2b5a431fe7bc3ca361b2b671 100644 (file)
@@ -34,6 +34,12 @@ static void string_move(void *addr)
        (void) addr;
 }
 
+const struct ao_lisp_type ao_lisp_string_type = {
+       .mark = string_mark,
+       .size = string_size,
+       .move = string_move,
+};
+
 char *
 ao_lisp_string_new(int len) {
        char    *a = ao_lisp_alloc(len + 1);
@@ -68,11 +74,47 @@ ao_lisp_string_cat(char *a, char *b)
        return r;
 }
 
-const struct ao_lisp_type ao_lisp_string_type = {
-       .mark = string_mark,
-       .size = string_size,
-       .move = string_move,
-};
+ao_poly
+ao_lisp_string_pack(struct ao_lisp_cons *cons)
+{
+       int     len = ao_lisp_cons_length(cons);
+       char    *r = ao_lisp_alloc(len + 1);
+       char    *s = r;
+
+       while (cons) {
+               if (ao_lisp_poly_type(cons->car) != AO_LISP_INT)
+                       return ao_lisp_error(AO_LISP_INVALID, "non-int passed to pack");
+               *s++ = ao_lisp_poly_int(cons->car);
+               cons = ao_lisp_poly_cons(cons->cdr);
+       }
+       *s++ = 0;
+       return ao_lisp_string_poly(r);
+}
+
+ao_poly
+ao_lisp_string_unpack(char *a)
+{
+       struct ao_lisp_cons     *cons = NULL, *tail = NULL;
+       int                     c;
+
+       ao_lisp_root_add(&ao_lisp_cons_type, &cons);
+       ao_lisp_root_add(&ao_lisp_cons_type, &tail);
+       while ((c = *a++)) {
+               struct ao_lisp_cons     *n = ao_lisp_cons_cons(ao_lisp_int_poly(c), NULL);
+               if (!n) {
+                       cons = NULL;
+                       break;
+               }
+               if (tail)
+                       tail->cdr = ao_lisp_cons_poly(n);
+               else
+                       cons = n;
+               tail = n;
+       }
+       ao_lisp_root_clear(&cons);
+       ao_lisp_root_clear(&tail);
+       return ao_lisp_cons_poly(cons);
+}
 
 void
 ao_lisp_string_print(ao_poly p)
index 19bd4f64df3237b9a593ec1e470d2c037b4e4fe4..c979697eba5bae34f5a8363a6c6b68ed8a805b9f 100644 (file)
 
 extern int ao_lisp_getc(void);
 
+static inline void
+ao_lisp_os_flush() {
+       fflush(stdout);
+}
+
 static inline void
 ao_lisp_abort(void)
 {