ao_lisp_poly.c \
ao_lisp_prim.c \
ao_lisp_builtin.c \
- ao_lisp_read.c
+ ao_lisp_read.c \
+ ao_lisp_frame.c
OBJS=$(SRCS:.c=.o)
#ifndef _AO_LISP_H_
#define _AO_LISP_H_
+#include <stdlib.h>
+
#if !defined(AO_LISP_TEST) && !defined(AO_LISP_MAKE_CONST)
#include <ao.h>
#define AO_LISP_ALTOS 1
+#define abort() ao_panic(1)
#endif
#include <stdint.h>
#ifdef AO_LISP_MAKE_CONST
#define AO_LISP_POOL_CONST 16384
extern uint8_t ao_lisp_const[AO_LISP_POOL_CONST];
+#define ao_lisp_pool ao_lisp_const
+#define AO_LISP_POOL AO_LISP_POOL_CONST
#define _ao_lisp_atom_quote ao_lisp_atom_poly(ao_lisp_atom_intern("quote"))
+#define _ao_lisp_atom_set ao_lisp_atom_poly(ao_lisp_atom_intern("set"))
#else
#include "ao_lisp_const.h"
+#define AO_LISP_POOL 1024
+extern uint8_t ao_lisp_pool[AO_LISP_POOL];
#endif
/* Primitive types */
/* These have a type value at the start of the struct */
#define AO_LISP_ATOM 4
#define AO_LISP_BUILTIN 5
-#define AO_LISP_NUM_TYPE 6
+#define AO_LISP_FRAME 6
+#define AO_LISP_NUM_TYPE 7
#define AO_LISP_NIL 0
-#define AO_LISP_POOL 1024
-
-extern uint8_t ao_lisp_pool[AO_LISP_POOL];
extern uint16_t ao_lisp_top;
#define AO_LISP_OOM 0x01
return poly & AO_LISP_CONST;
}
+#define AO_LISP_POOL_BASE (ao_lisp_pool - 4)
+#define AO_LISP_CONST_BASE (ao_lisp_const - 4)
+
+#define AO_LISP_IS_CONST(a) (ao_lisp_const <= ((uint8_t *) (a)) && ((uint8_t *) (a)) < ao_lisp_const + AO_LISP_POOL_CONST)
+#define AO_LISP_IS_POOL(a) (ao_lisp_pool <= ((uint8_t *) (a)) && ((uint8_t *) (a)) < ao_lisp_pool + AO_LISP_POOL)
+
static inline void *
ao_lisp_ref(ao_poly poly) {
if (poly == AO_LISP_NIL)
return NULL;
if (poly & AO_LISP_CONST)
- return (void *) ((ao_lisp_const - 4) + (poly & AO_LISP_REF_MASK));
- else
- return (void *) ((ao_lisp_pool - 4) + (poly & AO_LISP_REF_MASK));
+ return (void *) (AO_LISP_CONST_BASE + (poly & AO_LISP_REF_MASK));
+ return (void *) (AO_LISP_POOL_BASE + (poly & AO_LISP_REF_MASK));
}
static inline ao_poly
ao_lisp_poly(const void *addr, ao_poly type) {
const uint8_t *a = addr;
- if (addr == NULL)
+ if (a == NULL)
return AO_LISP_NIL;
- if (ao_lisp_pool <= a && a < ao_lisp_pool + AO_LISP_POOL)
- return (a - (ao_lisp_pool - 4)) | type;
- else if (ao_lisp_const <= a && a <= ao_lisp_const + AO_LISP_POOL_CONST)
- return AO_LISP_CONST | (a - (ao_lisp_const - 4)) | type;
- else {
- ao_lisp_exception |= AO_LISP_INVALID;
- return AO_LISP_NIL;
- }
+ if (AO_LISP_IS_CONST(a))
+ return AO_LISP_CONST | (a - AO_LISP_CONST_BASE) | type;
+ return (a - AO_LISP_POOL_BASE) | type;
}
-#define AO_LISP_POLY(addr, type) (((ao_lisp_pool <= ((uint8_t *) (a)) && \
- ((uint8_t *) (a)) < ao_lisp_pool + AO_LISP_POOL) ? \
- ((uint8_t *) (a) - (ao_lisp_pool - 4)) : \
- (((uint8_t *) (a) - (ao_lisp_const - 4)) | AO_LISP_POOL_CONST)) | \
- (type))
-
struct ao_lisp_type {
void (*mark)(void *addr);
int (*size)(void *addr);
struct ao_lisp_atom {
uint8_t type;
uint8_t pad[1];
- ao_poly val;
ao_poly next;
char name[];
};
+struct ao_lisp_val {
+ ao_poly atom;
+ ao_poly val;
+};
+
+struct ao_lisp_frame {
+ uint8_t num;
+ uint8_t readonly;
+ ao_poly next;
+ struct ao_lisp_val vals[];
+};
+
+static inline struct ao_lisp_frame *
+ao_lisp_poly_frame(ao_poly poly) {
+ return ao_lisp_ref(poly);
+}
+
+static inline ao_poly
+ao_lisp_frame_poly(struct ao_lisp_frame *frame) {
+ return ao_lisp_poly(frame, AO_LISP_OTHER);
+}
+
#define AO_LISP_LAMBDA 0
#define AO_LISP_NLAMBDA 1
#define AO_LISP_MACRO 2
return ao_lisp_ref(poly);
}
+static inline uint8_t
+ao_lisp_other_type(void *other) {
+ return *((uint8_t *) other);
+}
+
static inline ao_poly
ao_lisp_other_poly(const void *other)
{
#define AO_LISP_OTHER_POLY(other) ((ao_poly)(other) + AO_LISP_OTHER)
static inline int ao_lisp_poly_type(ao_poly poly) {
- int type = poly & 3;
+ int type = poly & AO_LISP_TYPE_MASK;
if (type == AO_LISP_OTHER)
- return *((uint8_t *) ao_lisp_poly_other(poly));
+ return ao_lisp_other_type(ao_lisp_poly_other(poly));
return type;
}
int
ao_lisp_mark_memory(void *addr, int size);
+void *
+ao_lisp_move_map(void *addr);
+
void *
ao_lisp_move(const struct ao_lisp_type *type, void *addr);
void *
ao_lisp_alloc(int size);
+void
+ao_lisp_collect(void);
+
int
ao_lisp_root_add(const struct ao_lisp_type *type, void *addr);
struct ao_lisp_atom *
ao_lisp_atom_intern(char *name);
+ao_poly
+ao_lisp_atom_get(ao_poly atom);
+
+ao_poly
+ao_lisp_atom_set(ao_poly atom, ao_poly val);
+
/* int */
void
ao_lisp_int_print(ao_poly i);
void
ao_lisp_builtin_print(ao_poly b);
+extern const struct ao_lisp_type ao_lisp_builtin_type;
+
/* read */
ao_poly
ao_lisp_read(void);
ao_poly
ao_lisp_read_eval_print(void);
+/* frame */
+extern const struct ao_lisp_type ao_lisp_frame_type;
+
+int
+ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val);
+
+ao_poly
+ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom);
+
+struct ao_lisp_frame *
+ao_lisp_frame_new(int num, int readonly);
+
+struct ao_lisp_frame *
+ao_lisp_frame_add(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val);
+
#endif /* _AO_LISP_H_ */
#include "ao_lisp.h"
+#if 0
+#define DBG(...) printf(__VA_ARGS__)
+#else
+#define DBG(...)
+#endif
+
static int name_size(char *name)
{
return sizeof(struct ao_lisp_atom) + strlen(name) + 1;
{
struct ao_lisp_atom *atom = addr;
+ DBG ("\tatom start %s\n", atom->name);
for (;;) {
- ao_lisp_poly_mark(atom->val);
atom = ao_lisp_poly_atom(atom->next);
if (!atom)
break;
+ DBG("\t\tatom mark %s %d\n", atom->name, (uint8_t *) atom - ao_lisp_const);
if (ao_lisp_mark_memory(atom, atom_size(atom)))
break;
}
+ DBG ("\tatom done\n");
}
static void atom_move(void *addr)
{
struct ao_lisp_atom *atom = addr;
+ DBG("\tatom move start %s %d next %s %d\n",
+ atom->name, ((uint8_t *) atom - ao_lisp_const),
+ atom->next ? ao_lisp_poly_atom(atom->next)->name : "(none)",
+ atom->next ? ((uint8_t *) ao_lisp_poly_atom(atom->next) - ao_lisp_const) : 0);
for (;;) {
struct ao_lisp_atom *next;
- atom->val = ao_lisp_poly_move(atom->val);
next = ao_lisp_poly_atom(atom->next);
next = ao_lisp_move_memory(next, atom_size(next));
if (!next)
break;
+ DBG("\t\tatom move %s %d->%d\n", next->name, ((uint8_t *) ao_lisp_poly_atom(atom->next) - ao_lisp_const), ((uint8_t *) next - ao_lisp_const));
atom->next = ao_lisp_atom_poly(next);
atom = next;
}
+ DBG("\tatom move end\n");
}
const struct ao_lisp_type ao_lisp_atom_type = {
ao_lisp_atom_intern(char *name)
{
struct ao_lisp_atom *atom;
-// int b;
for (atom = ao_lisp_atoms; atom; atom = ao_lisp_poly_atom(atom->next)) {
if (!strcmp(atom->name, name))
return atom;
}
#endif
- if (!ao_lisp_atoms)
- ao_lisp_root_add(&ao_lisp_atom_type, (void **) &ao_lisp_atoms);
atom = ao_lisp_alloc(name_size(name));
if (atom) {
atom->type = AO_LISP_ATOM;
atom->next = ao_lisp_atom_poly(ao_lisp_atoms);
+ if (!ao_lisp_atoms)
+ ao_lisp_root_add(&ao_lisp_atom_type, &ao_lisp_atoms);
ao_lisp_atoms = atom;
strcpy(atom->name, name);
- atom->val = AO_LISP_NIL;
}
return atom;
}
+static struct ao_lisp_frame *globals;
+
+ao_poly
+ao_lisp_atom_get(ao_poly atom)
+{
+ struct ao_lisp_frame *frame = globals;
+#ifdef ao_builtin_frame
+ if (!frame)
+ frame = ao_lisp_poly_frame(ao_builtin_frame);
+#endif
+ return ao_lisp_frame_get(frame, atom);
+}
+
+ao_poly
+ao_lisp_atom_set(ao_poly atom, ao_poly val)
+{
+ if (!ao_lisp_frame_set(globals, atom, val)) {
+ globals = ao_lisp_frame_add(globals, atom, val);
+ if (!globals->next) {
+ ao_lisp_root_add(&ao_lisp_frame_type, &globals);
+#ifdef ao_builtin_frame
+ globals->next = ao_builtin_frame;
+#endif
+ }
+ }
+ return val;
+}
+
void
ao_lisp_atom_print(ao_poly a)
{
#include "ao_lisp.h"
+static int
+builtin_size(void *addr)
+{
+ (void) addr;
+ return sizeof (struct ao_lisp_builtin);
+}
+
+static void
+builtin_mark(void *addr)
+{
+ (void) addr;
+}
+
+static void
+builtin_move(void *addr)
+{
+ (void) addr;
+}
+
+const struct ao_lisp_type ao_lisp_builtin_type = {
+ .size = builtin_size,
+ .mark = builtin_mark,
+ .move = builtin_move
+};
+
void
ao_lisp_builtin_print(ao_poly b)
{
ao_poly
ao_lisp_set(struct ao_lisp_cons *cons)
{
- ao_poly atom, val;
if (!check_argc(cons, 2, 2))
return AO_LISP_NIL;
if (!check_argt(cons, 0, AO_LISP_ATOM, 0))
return AO_LISP_NIL;
- atom = cons->car;
- val = ao_lisp_poly_cons(cons->cdr)->car;
- if (ao_lisp_is_const(atom)) {
- ao_lisp_exception |= AO_LISP_INVALID;
- return AO_LISP_NIL;
- }
- ao_lisp_poly_atom(atom)->val = val;
- return val;
+ return ao_lisp_atom_set(cons->car, ao_lisp_poly_cons(cons->cdr)->car);
}
ao_poly
val = cons->car;
ao_lisp_poly_print(val);
cons = ao_lisp_poly_cons(cons->cdr);
+ if (cons)
+ printf(" ");
}
return val;
}
#include "ao_lisp.h"
+#define OFFSET(a) ((int) ((uint8_t *) (a) - ao_lisp_const))
+
+#if 0
+static int cons_depth;
+#define DBG(...) do { int d; for (d = 0; d < cons_depth; d++) printf (" "); printf(__VA_ARGS__); } while(0)
+#define DBG_IN() (cons_depth++)
+#define DBG_OUT() (cons_depth--)
+#define DBG_PR(c) ao_lisp_cons_print(ao_lisp_cons_poly(c))
+#define DBG_PRP(p) ao_lisp_poly_print(p)
+#else
+#define DBG(...)
+#define DBG_IN()
+#define DBG_OUT()
+#define DBG_PR(c)
+#define DBG_PRP(p)
+#endif
+
static void cons_mark(void *addr)
{
struct ao_lisp_cons *cons = addr;
{
struct ao_lisp_cons *cons = addr;
+ DBG_IN();
+ DBG("move cons start %d\n", OFFSET(cons));
for (;;) {
struct ao_lisp_cons *cdr;
+ ao_poly car;
- cons->car = ao_lisp_poly_move(cons->car);
+ car = ao_lisp_poly_move(cons->car);
+ DBG(" moved car %d -> %d\n", OFFSET(ao_lisp_ref(cons->car)), OFFSET(ao_lisp_ref(car)));
+ cons->car = car;
cdr = ao_lisp_poly_cons(cons->cdr);
cdr = ao_lisp_move_memory(cdr, sizeof (struct ao_lisp_cons));
if (!cdr)
break;
+ DBG(" moved cdr %d -> %d\n", OFFSET(ao_lisp_poly_cons(cons->cdr)), OFFSET(cdr));
cons->cdr = ao_lisp_cons_poly(cdr);
cons = cdr;
}
+ DBG("move cons end\n");
+ DBG_OUT();
}
const struct ao_lisp_type ao_lisp_cons_type = {
case AO_LISP_STRING:
break;
case AO_LISP_ATOM:
- v = ao_lisp_poly_atom(v)->val;
+ v = ao_lisp_atom_get(v);
break;
}
DBG("stack pop: actuals"); DBG_CONS(actuals); DBG("\n");
DBG("stack pop: formals"); DBG_CONS(formals); DBG("\n");
} else {
+ actuals = 0;
+ formals = 0;
+ formals_tail = 0;
DBG("done func\n");
break;
}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * 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 2 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.
+ */
+
+#include "ao_lisp.h"
+
+#if 0
+#define DBG(...) printf(__VA_ARGS__)
+#else
+#define DBG(...)
+#endif
+
+static inline int
+frame_num_size(int num)
+{
+ return sizeof (struct ao_lisp_frame) + num * sizeof (struct ao_lisp_val);
+}
+
+static int
+frame_size(void *addr)
+{
+ struct ao_lisp_frame *frame = addr;
+ return frame_num_size(frame->num);
+}
+
+#define OFFSET(a) ((uint8_t *) (ao_lisp_ref(a)) - ao_lisp_const)
+
+static void
+frame_mark(void *addr)
+{
+ struct ao_lisp_frame *frame = addr;
+ int f;
+
+ for (;;) {
+ if (frame->readonly)
+ break;
+ for (f = 0; f < frame->num; f++) {
+ struct ao_lisp_val *v = &frame->vals[f];
+
+ ao_lisp_poly_mark(v->atom);
+ ao_lisp_poly_mark(v->val);
+ DBG ("\tframe mark atom %s %d val %d at %d\n", ao_lisp_poly_atom(v->atom)->name, OFFSET(v->atom), OFFSET(v->val), f);
+ }
+ frame = ao_lisp_poly_frame(frame->next);
+ if (!frame)
+ break;
+ if (ao_lisp_mark_memory(frame, frame_size(frame)))
+ break;
+ }
+}
+
+static void
+frame_move(void *addr)
+{
+ struct ao_lisp_frame *frame = addr;
+ int f;
+
+ for (;;) {
+ struct ao_lisp_frame *next;
+ if (frame->readonly)
+ break;
+ for (f = 0; f < frame->num; f++) {
+ struct ao_lisp_val *v = &frame->vals[f];
+ ao_poly t;
+
+ t = ao_lisp_poly_move(v->atom);
+ DBG("\t\tatom %s %d -> %d\n", ao_lisp_poly_atom(t)->name, OFFSET(v->atom), OFFSET(t));
+ v->atom = t;
+ t = ao_lisp_poly_move(v->val);
+ DBG("\t\tval %d -> %d\n", OFFSET(v->val), OFFSET(t));
+ v->val = t;
+ }
+ next = ao_lisp_poly_frame(frame->next);
+ if (!next)
+ break;
+ next = ao_lisp_move_memory(next, frame_size(next));
+ frame->next = ao_lisp_frame_poly(next);
+ frame = next;
+ }
+}
+
+const struct ao_lisp_type ao_lisp_frame_type = {
+ .mark = frame_mark,
+ .size = frame_size,
+ .move = frame_move
+};
+
+static ao_poly *
+ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom)
+{
+ int f;
+ for (f = 0; f < frame->num; f++)
+ if (frame->vals[f].atom == atom)
+ return &frame->vals[f].val;
+ return NULL;
+}
+
+int
+ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
+{
+ while (frame) {
+ if (!frame->readonly) {
+ ao_poly *ref = ao_lisp_frame_ref(frame, atom);
+ if (ref) {
+ *ref = val;
+ return 1;
+ }
+ }
+ frame = ao_lisp_poly_frame(frame->next);
+ }
+ return 0;
+}
+
+ao_poly
+ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom)
+{
+ while (frame) {
+ ao_poly *ref = ao_lisp_frame_ref(frame, atom);
+ if (ref)
+ return *ref;
+ frame = ao_lisp_poly_frame(frame->next);
+ }
+ return AO_LISP_NIL;
+}
+
+struct ao_lisp_frame *
+ao_lisp_frame_new(int num, int readonly)
+{
+ struct ao_lisp_frame *frame = ao_lisp_alloc(frame_num_size(num));
+
+ if (!frame)
+ return NULL;
+ frame->num = num;
+ frame->readonly = readonly;
+ frame->next = AO_LISP_NIL;
+ memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val));
+ return frame;
+}
+
+static struct ao_lisp_frame *
+ao_lisp_frame_realloc(struct ao_lisp_frame *frame, int new_num, int readonly)
+{
+ struct ao_lisp_frame *new;
+ int copy;
+
+ if (new_num == frame->num)
+ return frame;
+ new = ao_lisp_frame_new(new_num, readonly);
+ if (!new)
+ return NULL;
+ copy = new_num;
+ if (copy > frame->num)
+ copy = frame->num;
+ memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val));
+ if (frame)
+ new->next = frame->next;
+ return new;
+}
+
+struct ao_lisp_frame *
+ao_lisp_frame_add(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val)
+{
+ ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL;
+ if (!ref) {
+ int f;
+ if (frame) {
+ f = frame->num;
+ frame = ao_lisp_frame_realloc(frame, f + 1, frame->readonly);
+ } else {
+ f = 0;
+ frame = ao_lisp_frame_new(1, 0);
+ }
+ if (!frame)
+ return NULL;
+ DBG ("add atom %s %d, val %d at %d\n", ao_lisp_poly_atom(atom)->name, OFFSET(atom), OFFSET(val), f);
+ frame->vals[f].atom = atom;
+ ref = &frame->vals[f].val;
+ }
+ *ref = val;
+ return frame;
+}
#define N_FUNC (sizeof funcs / sizeof funcs[0])
+struct ao_lisp_frame *globals;
+
+static int
+is_atom(int offset)
+{
+ struct ao_lisp_atom *a;
+
+ for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next))
+ if (((uint8_t *) a->name - ao_lisp_const) == offset)
+ return strlen(a->name);
+ return 0;
+}
+
int
main(int argc, char **argv)
{
int f, o;
ao_poly atom, val;
struct ao_lisp_atom *a;
+ int in_atom;
+ printf("/*\n");
+ printf(" * Generated file, do not edit\n");
+ ao_lisp_root_add(&ao_lisp_frame_type, &globals);
+ globals = ao_lisp_frame_new(0, 0);
for (f = 0; f < N_FUNC; f++) {
struct ao_lisp_builtin *b = ao_lisp_make_builtin(funcs[f].func, funcs[f].args);
struct ao_lisp_atom *a = ao_lisp_atom_intern(funcs[f].name);
- a->val = ao_lisp_builtin_poly(b);
+ globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), ao_lisp_builtin_poly(b));
}
+ /* boolean constants */
+ a = ao_lisp_atom_intern("nil");
+ globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), AO_LISP_NIL);
+ a = ao_lisp_atom_intern("t");
+ globals = ao_lisp_frame_add(globals, ao_lisp_atom_poly(a), ao_lisp_atom_poly(a));
+
for (;;) {
atom = ao_lisp_read();
if (!atom)
fprintf(stderr, "input must be atom val pairs\n");
exit(1);
}
- ao_lisp_poly_atom(atom)->val = val;
+ globals = ao_lisp_frame_add(globals, atom, val);
}
- printf("/* constant objects, all referenced from atoms */\n\n");
+ /* Reduce to referenced values */
+ ao_lisp_collect();
+ printf(" */\n");
+
+ globals->readonly = 1;
+
printf("#define AO_LISP_POOL_CONST %d\n", ao_lisp_top);
printf("extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n");
printf("#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms));
+ printf("#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(globals));
for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
char *n = a->name, c;
else
printf(" ");
c = ao_lisp_const[o];
- if (' ' < c && c <= '~' && c != '\'')
+ if (!in_atom)
+ in_atom = is_atom(o);
+ if (in_atom) {
printf (" '%c',", c);
- else
+ in_atom--;
+ } else {
printf("0x%02x,", c);
+ }
}
printf("\n};\n");
printf("#endif /* AO_LISP_CONST_BITS */\n");
#include "ao_lisp.h"
#include <stdio.h>
-uint8_t ao_lisp_pool[AO_LISP_POOL] __attribute__((aligned(4)));
-
#ifdef AO_LISP_MAKE_CONST
#include <stdlib.h>
uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));
+#define ao_lisp_pool ao_lisp_const
+#undef AO_LISP_POOL
+#define AO_LISP_POOL AO_LISP_POOL_CONST
+#else
+uint8_t ao_lisp_pool[AO_LISP_POOL] __attribute__((aligned(4)));
+#endif
+
+#if 0
+#define DBG_DUMP
+#define DBG_OFFSET(a) ((int) ((uint8_t *) (a) - ao_lisp_pool))
+#define DBG(...) printf(__VA_ARGS__)
+static int move_dump;
+static int move_depth;
+#define DBG_RESET() (move_depth = 0)
+#define DBG_MOVE(...) do { if(move_dump) { int d; for (d = 0; d < move_depth; d++) printf (" "); printf(__VA_ARGS__); } } while (0)
+#define DBG_MOVE_IN() (move_depth++)
+#define DBG_MOVE_OUT() (move_depth--)
+#else
+#define DBG(...)
+#define DBG_RESET()
+#define DBG_MOVE(...)
+#define DBG_MOVE_IN()
+#define DBG_MOVE_OUT()
#endif
uint8_t ao_lisp_exception;
return 0;
}
+static int
+busy_object(uint8_t *tag, void *addr) {
+ int base;
+
+ if (!addr)
+ return 1;
+
+ if ((uint8_t *) addr < ao_lisp_pool || ao_lisp_pool + AO_LISP_POOL <= (uint8_t*) addr)
+ return 1;
+
+ base = (uint8_t *) addr - ao_lisp_pool;
+ base = limit(base);
+ if (busy(tag, base))
+ return 1;
+ return 0;
+}
+
static void *move_old, *move_new;
static int move_size;
{
int i;
+ DBG_RESET();
+ DBG_MOVE("move %d -> %d\n", DBG_OFFSET(move_old), DBG_OFFSET(move_new));
+ DBG_MOVE_IN();
memset(ao_lisp_moving, '\0', sizeof (ao_lisp_moving));
for (i = 0; i < AO_LISP_ROOT; i++)
- if (ao_lisp_root[i].addr) {
+ if (ao_lisp_root[i].addr && *ao_lisp_root[i].addr) {
void *new;
+ DBG_MOVE("root %d\n", DBG_OFFSET(*ao_lisp_root[i].addr));
new = ao_lisp_move(ao_lisp_root[i].type, *ao_lisp_root[i].addr);
if (new)
*ao_lisp_root[i].addr = new;
}
+ DBG_MOVE_OUT();
+ DBG_MOVE("move done\n");
}
+#ifdef DBG_DUMP
static void
-collect(void)
+dump_busy(void)
+{
+ int i;
+ printf("busy:");
+ for (i = 0; i < ao_lisp_top; i += 4) {
+ if ((i & 0xff) == 0)
+ printf("\n");
+ else if ((i & 0x1f) == 0)
+ printf(" ");
+ if (busy(ao_lisp_busy, i))
+ putchar('*');
+ else
+ putchar('-');
+ }
+ printf ("\n");
+}
+#define DUMP_BUSY() dump_busy()
+#else
+#define DUMP_BUSY()
+#endif
+
+void
+ao_lisp_collect(void)
{
int i;
+ int top;
/* Mark */
memset(ao_lisp_busy, '\0', sizeof (ao_lisp_busy));
+ DBG("mark\n");
for (i = 0; i < AO_LISP_ROOT; i++)
- if (ao_lisp_root[i].addr)
+ if (ao_lisp_root[i].addr && *ao_lisp_root[i].addr) {
+ DBG("root %p\n", *ao_lisp_root[i].addr);
ao_lisp_mark(ao_lisp_root[i].type, *ao_lisp_root[i].addr);
+ }
+ DUMP_BUSY();
/* Compact */
- ao_lisp_top = 0;
- for (i = 0; i < AO_LISP_POOL; i += 4) {
+ DBG("find first busy\n");
+ for (i = 0; i < ao_lisp_top; i += 4) {
if (!busy(ao_lisp_busy, i))
break;
}
- ao_lisp_top = i;
- while(i < AO_LISP_POOL) {
+ top = i;
+ while(i < ao_lisp_top) {
if (busy(ao_lisp_busy, i)) {
+ DBG("busy %d -> %d\n", i, top);
move_old = &ao_lisp_pool[i];
- move_new = &ao_lisp_pool[ao_lisp_top];
+ move_new = &ao_lisp_pool[top];
move_size = 0;
move_object();
+ DBG("\tbusy size %d\n", move_size);
+ if (move_size == 0)
+ abort();
clear_object(ao_lisp_busy, move_old, move_size);
+ mark_object(ao_lisp_busy, move_new, move_size);
i += move_size;
- ao_lisp_top += move_size;
+ top += move_size;
+ DUMP_BUSY();
} else {
i += 4;
}
}
+ ao_lisp_top = top;
}
void
ao_lisp_mark(const struct ao_lisp_type *type, void *addr)
{
+ if (!addr)
+ return;
if (mark_object(ao_lisp_busy, addr, type->size(addr)))
return;
type->mark(addr);
return mark_object(ao_lisp_busy, addr, size);
}
+/*
+ * After the object has been moved, we have to reference it
+ * in the new location. This is only relevant for ao_lisp_poly_move
+ * as it needs to fetch the type byte from the object, which
+ * may have been overwritten by the copy
+ */
+void *
+ao_lisp_move_map(void *addr)
+{
+ if (addr == move_old) {
+ if (busy_object(ao_lisp_moving, addr))
+ return move_new;
+ }
+ return addr;
+}
+
static void *
check_move(void *addr, int size)
{
if (addr == move_old) {
- memmove(move_new, move_old, size);
- move_size = (size + 3) & ~3;
+ DBG_MOVE("mapping %d -> %d\n", DBG_OFFSET(addr), DBG_OFFSET(move_new));
+ if (!busy_object(ao_lisp_moving, addr)) {
+ DBG_MOVE(" copy %d\n", size);
+ memmove(move_new, move_old, size);
+ move_size = (size + 3) & ~3;
+ }
addr = move_new;
}
return addr;
void *
ao_lisp_move(const struct ao_lisp_type *type, void *addr)
{
+ uint8_t *a = addr;
int size = type->size(addr);
if (!addr)
return NULL;
+#ifndef AO_LISP_MAKE_CONST
+ if (AO_LISP_IS_CONST(addr))
+ return addr;
+#endif
+ DBG_MOVE("object %d\n", DBG_OFFSET(addr));
+ if (a < ao_lisp_pool || ao_lisp_pool + AO_LISP_POOL <= a)
+ abort();
+ DBG_MOVE_IN();
addr = check_move(addr, size);
- if (mark_object(ao_lisp_moving, addr, size))
+ if (mark_object(ao_lisp_moving, addr, size)) {
+ DBG_MOVE("already moved\n");
+ DBG_MOVE_OUT();
return addr;
+ }
+ DBG_MOVE_OUT();
+ DBG_MOVE("recursing...\n");
+ DBG_MOVE_IN();
type->move(addr);
+ DBG_MOVE_OUT();
+ DBG_MOVE("done %d\n", DBG_OFFSET(addr));
return addr;
}
if (!addr)
return NULL;
+ DBG_MOVE("memory %d\n", DBG_OFFSET(addr));
+ DBG_MOVE_IN();
addr = check_move(addr, size);
- if (mark_object(ao_lisp_moving, addr, size))
- return NULL;
+ if (mark_object(ao_lisp_moving, addr, size)) {
+ DBG_MOVE("already moved\n");
+ DBG_MOVE_OUT();
+ return addr;
+ }
+ DBG_MOVE_OUT();
return addr;
}
void *addr;
size = ao_lisp_mem_round(size);
-#ifdef AO_LISP_MAKE_CONST
- if (ao_lisp_top + size > AO_LISP_POOL_CONST) {
- fprintf(stderr, "Too much constant data, increase AO_LISP_POOL_CONST\n");
- exit(1);
- }
- addr = ao_lisp_const + ao_lisp_top;
-#else
if (ao_lisp_top + size > AO_LISP_POOL) {
- collect();
+ ao_lisp_collect();
if (ao_lisp_top + size > AO_LISP_POOL) {
ao_lisp_exception |= AO_LISP_OOM;
return NULL;
}
}
addr = ao_lisp_pool + ao_lisp_top;
-#endif
ao_lisp_top += size;
return addr;
}
ao_lisp_root_add(const struct ao_lisp_type *type, void *addr)
{
int i;
+ DBG("add root type %p addr %p\n", type, addr);
for (i = 0; i < AO_LISP_ROOT; i++) {
if (!ao_lisp_root[i].addr) {
ao_lisp_root[i].addr = addr;
return 1;
}
}
+ abort();
return 0;
}
return p;
}
+static const struct ao_lisp_type const *ao_lisp_types[AO_LISP_NUM_TYPE] = {
+ [AO_LISP_CONS] = &ao_lisp_cons_type,
+ [AO_LISP_STRING] = &ao_lisp_string_type,
+ [AO_LISP_ATOM] = &ao_lisp_atom_type,
+ [AO_LISP_BUILTIN] = &ao_lisp_builtin_type,
+};
+
void
ao_lisp_poly_mark(ao_poly p)
{
- switch (ao_lisp_poly_type(p)) {
- case AO_LISP_CONS:
- ao_lisp_mark(&ao_lisp_cons_type, ao_lisp_poly_cons(p));
- break;
- case AO_LISP_STRING:
- ao_lisp_mark(&ao_lisp_string_type, ao_lisp_poly_string(p));
- break;
- case AO_LISP_ATOM:
- ao_lisp_mark(&ao_lisp_atom_type, ao_lisp_poly_atom(p));
- break;
- }
+ const struct ao_lisp_type *lisp_type = ao_lisp_types[ao_lisp_poly_type(p)];
+ if (lisp_type)
+ ao_lisp_mark(lisp_type, ao_lisp_ref(p));
}
ao_poly
ao_lisp_poly_move(ao_poly p)
{
- switch (ao_lisp_poly_type(p)) {
- case AO_LISP_CONS:
- p = ao_lisp_cons_poly(ao_lisp_move(&ao_lisp_cons_type, ao_lisp_poly_cons(p)));
- break;
- case AO_LISP_STRING:
- p = ao_lisp_string_poly(ao_lisp_move(&ao_lisp_string_type, ao_lisp_poly_string(p)));
- break;
- case AO_LISP_ATOM:
- p = ao_lisp_atom_poly(ao_lisp_move(&ao_lisp_atom_type, ao_lisp_poly_atom(p)));
- break;
- }
+ uint8_t type = p & AO_LISP_TYPE_MASK;
+ const struct ao_lisp_type *lisp_type;
+
+ if (type == AO_LISP_OTHER)
+ type = ao_lisp_other_type(ao_lisp_move_map(ao_lisp_poly_other(p)));
+
+ lisp_type = ao_lisp_types[type];
+ if (lisp_type)
+ p = ao_lisp_poly(ao_lisp_move(lisp_type, ao_lisp_ref(p)), p & AO_LISP_TYPE_MASK);
return p;
}
int count;
c = lex_get();
-// if (jumping)
-// return nil;
if (c == EOF)
return EOF;
c &= 0x7f;
count = 1;
while (count <= 3) {
c = lex_get();
-// if (jumping)
-// return nil;
if (c == EOF)
return EOF;
c &= 0x7f;
if (lex_class & ENDOFFILE)
return AO_LISP_NIL;
-// if (jumping)
-// return nil;
if (lex_class & WHITE)
continue;
+ if (lex_class & COMMENT) {
+ while ((c = lexc()) != '\n') {
+ if (lex_class & ENDOFFILE)
+ return AO_LISP_NIL;
+ }
+ continue;
+ }
+
if (lex_class & (BRA|KET|QUOTEC)) {
add_token(c);
end_token();
if (lex_class & STRINGC) {
for (;;) {
c = lexc();
-// if (jumping)
-// return nil;
if (lex_class & (STRINGC|ENDOFFILE)) {
end_token();
return STRING;
}
add_token (c);
c = lexc ();
-// if (jumping)
-// return nil;
if (lex_class & (NOTNAME)) {
// if (lex_class & ENDOFFILE)
// clearerr (f);
read_cons_tail && read_cons_tail->cdr;
read_cons_tail = ao_lisp_poly_cons(read_cons_tail->cdr))
;
+ } else {
+ read_cons = 0;
+ read_cons_tail = 0;
+ read_stack = 0;
}
return in_quote;
}
ao_lisp_root_add(&ao_lisp_cons_type, &read_cons);
ao_lisp_root_add(&ao_lisp_cons_type, &read_cons_tail);
ao_lisp_root_add(&ao_lisp_cons_type, &read_stack);
+ been_here = 1;
}
parse_token = lex();
ao_pins.h \
ao_product.h \
ao_task.h \
+ ao_lisp.h \
+ ao_lisp_const.h \
stm32f0.h \
Makefile
ao_lisp_builtin.c \
ao_lisp_read.c \
ao_lisp_rep.c \
+ ao_lisp_frame.c \
ao_exti_stm.c
PRODUCT=Nucleo-32
#AO_LISP_OBJS = ao_lisp_test.o ao_lisp_mem.o ao_lisp_lex.o ao_lisp_cons.o ao_lisp_string.o ao_lisp_atom.o ao_lisp_int.o ao_lisp_prim.o ao_lisp_eval.o ao_lisp_poly.o ao_lisp_builtin.o ao_lisp_read.o
-AO_LISP_OBJS = ao_lisp_test.o ao_lisp_mem.o ao_lisp_cons.o ao_lisp_string.o ao_lisp_atom.o ao_lisp_int.o ao_lisp_prim.o ao_lisp_eval.o ao_lisp_poly.o ao_lisp_builtin.o ao_lisp_read.o ao_lisp_rep.o
+AO_LISP_OBJS = ao_lisp_test.o ao_lisp_mem.o ao_lisp_cons.o ao_lisp_string.o \
+ ao_lisp_atom.o ao_lisp_int.o ao_lisp_prim.o ao_lisp_eval.o ao_lisp_poly.o \
+ ao_lisp_builtin.o ao_lisp_read.o ao_lisp_rep.o ao_lisp_frame.o
ao_lisp_test: $(AO_LISP_OBJS)
cc $(CFLAGS) -o $@ $(AO_LISP_OBJS)
list = ao_lisp_cons_cons(ao_lisp_string_poly(string), list);
list = ao_lisp_cons_cons(ao_lisp_int_poly(i), list);
atom = ao_lisp_atom_intern("ant");
- atom->val = ao_lisp_cons_poly(list);
list = ao_lisp_cons_cons(ao_lisp_atom_poly(atom), list);
}
ao_lisp_poly_print(ao_lisp_cons_poly(list));
for (atom = ao_lisp_poly_atom(ao_builtin_atoms); atom; atom = ao_lisp_poly_atom(atom->next)) {
printf("%s = ", atom->name);
- ao_lisp_poly_print(atom->val);
+ ao_lisp_poly_print(ao_lisp_atom_get(ao_lisp_atom_poly(atom)));
printf("\n");
}
#if 1