diff --git a/src/equal.h b/src/equal.h index 502dd32..2c4a86d 100644 --- a/src/equal.h +++ b/src/equal.h @@ -10,6 +10,8 @@ #include #include +#include "consspaceobject.h" + #ifndef __equal_h #define __equal_h diff --git a/src/intern.c b/src/intern.c new file mode 100644 index 0000000..6770bdf --- /dev/null +++ b/src/intern.c @@ -0,0 +1,107 @@ +/** + * intern.c + * + * For now this implements an oblist and shallow binding; local environments can + * be consed onto the front of the oblist. Later, this won't do; bindings will happen + * in namespaces, which will probably be implemented as hash tables. + * + * Doctrine is that cons cells are immutable, and life is a lot more simple if they are; + * so when a symbol is rebound in the master oblist, what in fact we do is construct + * a new oblist without the previous binding but with the new binding. Anything which, + * prior to this action, held a pointer to the old oblist (as all current threads' + * environments must do) continues to hold a pointer to the old oblist, and consequently + * doesn't see the change. This is probably good but does mean you cannot use bindings + * on the oblist to signal between threads. + * + * (c) 2017 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + +#include + +#include "equal.h" +#include "conspage.h" +#include "consspaceobject.h" + +/** + * The object list. What is added to this during system setup is 'global', that is, + * visible to all sessions/threads. What is added during a session/thread is local to + * that session/thread (because shallow binding). There must be some way for a user to + * make the contents of their own environment persistent between threads but I don't + * know what it is yet. At some stage there must be a way to rebind deep values so + * they're visible to all users/threads, but again I don't yet have any idea how + * that will work. + */ +struct cons_pointer oblist = NIL; + +/** + * return the value associated with this key in this store. In the current + * implementation a store is just an assoc list, but in future it might be a + * namespace, a regularity or a homogeneity. + * TODO: This function ultimately belongs in lispops. + */ +struct cons_pointer assoc( struct cons_pointer key, struct cons_pointer store) { + struct cons_pointer result = NIL; + + if ( consp( store)) { + struct cons_space_object* cell_store = &pointer2cell( store); + + if ( consp( cell_store->payload.cons.car)) { + struct cons_space_object* binding = + &pointer2cell( cell_store->payload.cons.car); + + if ( eq( key, binding->payload.cons.car)) { + result = binding->payload.cons.cdr; + } + } + /* top-level objects on an assoc list ought to be conses (i.e. each + * successive car should be a cons), but there's no need to throw a + * wobbly if it isn't. */ + + if ( nilp( result)) { + result = assoc( key, cell_store->payload.cons.cdr); + } + } + + return result; +} + + +/** + * Return true if this key is present as a key in this enviroment, defaulting to + * the oblist if no environment is passed. + */ +bool internedp( struct cons_pointer key, struct cons_pointer environment) { + bool result = false; + + if ( nilp( environment)) { + if ( !nilp( oblist)) { + result = internedp( key, oblist); + } + } else { + result = !nilp( assoc( key, environment)); + } + + return result; +} + + +/** + * Return a new key/value store containing all the key/value pairs in this store + * with this key/value pair added to the front. + */ +struct cons_pointer bind( struct cons_pointer key, struct cons_pointer value, + struct cons_pointer store) { + return make_cons( make_cons( key, value), store); +} + + +/** + * Binds this key to this value in the global oblist, but doesn't affect the + * current environment. May not be useful except in bootstrapping (and even + * there it may not be especially useful). + */ +struct cons_pointer deep_bind( struct cons_pointer key, struct cons_pointer value) { + oblist = bind( key, value, oblist); + return oblist; +} diff --git a/src/intern.h b/src/intern.h new file mode 100644 index 0000000..656fe62 --- /dev/null +++ b/src/intern.h @@ -0,0 +1,48 @@ +/** + * intern.h + * + * For now this implements an oblist and shallow binding; local environments can + * be consed onto the front of the oblist. Later, this won't do; bindings will happen + * in namespaces, which will probably be implemented as hash tables. + * + * Doctrine is that cons cells are immutable, and life is a lot more simple if they are; + * so when a symbol is rebound in the master oblist, what in fact we do is construct + * a new oblist without the previous binding but with the new binding. Anything which, + * prior to this action, held a pointer to the old oblist (as all current threads' + * environments must do) continues to hold a pointer to the old oblist, and consequently + * doesn't see the change. This is probably good but does mean you cannot use bindings + * on the oblist to signal between threads. + * + * (c) 2017 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + +extern struct cons_pointer oblist; + +/** + * return the value associated with this key in this store. In the current + * implementation a store is just an assoc list, but in future it might be a + * namespace, a regularity or a homogeneity. + * TODO: This function ultimately belongs in lispops. + */ +struct cons_pointer assoc( struct cons_pointer key, struct cons_pointer store); + +/** + * Return true if this key is present as a key in this enviroment, defaulting to + * the oblist if no environment is passed. + */ +bool internedp( struct cons_pointer key, struct cons_pointer environment); + +/** + * Return a new key/value store containing all the key/value pairs in this store + * with this key/value pair added to the front. + */ +struct cons_pointer bind( struct cons_pointer key, struct cons_pointer value, + struct cons_pointer store); + +/** + * Binds this key to this value in the global oblist, but doesn't affect the + * current environment. May not be useful except in bootstrapping (and even + * there it may not be especially useful). + */ +struct cons_pointer deep_bind( struct cons_pointer key, struct cons_pointer value);