Post Scarcity 0.0.6
A prototype for a post scarcity programming environment
Loading...
Searching...
No Matches
intern.c
Go to the documentation of this file.
1/*
2 * intern.c
3 *
4 * For now this implements an oblist and shallow binding; local environments can
5 * be consed onto the front of the oblist. Later, this won't do; bindings will happen
6 * in namespaces, which will probably be implemented as hash tables.
7 *
8 * Doctrine is that cons cells are immutable, and life is a lot more simple if they are;
9 * so when a symbol is rebound in the master oblist, what in fact we do is construct
10 * a new oblist without the previous binding but with the new binding. Anything which,
11 * prior to this action, held a pointer to the old oblist (as all current threads'
12 * environments must do) continues to hold a pointer to the old oblist, and consequently
13 * doesn't see the change. This is probably good but does mean you cannot use bindings
14 * on the oblist to signal between threads.
15 *
16 * (c) 2017 Simon Brooke <simon@journeyman.cc>
17 * Licensed under GPL version 2.0, or, at your option, any later version.
18 */
19
20#include <stdbool.h>
21#include <string.h>
22/*
23 * wide characters
24 */
25#include <wchar.h>
26#include <wctype.h>
27
28#include "authorise.h"
29#include "debug.h"
30#include "io/io.h"
31#include "memory/conspage.h"
33#include "memory/hashmap.h"
34#include "ops/equal.h"
35#include "ops/intern.h"
36#include "ops/lispops.h"
37// #include "print.h"
38
39/**
40 * @brief The global object list/or, to put it differently, the root namespace.
41 * What is added to this during system setup is 'global', that is,
42 * visible to all sessions/threads. What is added during a session/thread is local to
43 * that session/thread (because shallow binding). There must be some way for a user to
44 * make the contents of their own environment persistent between threads but I don't
45 * know what it is yet. At some stage there must be a way to rebind deep values so
46 * they're visible to all users/threads, but again I don't yet have any idea how
47 * that will work.
48 */
50
51/**
52 * @brief the symbol `NIL`, which is special!
53 *
54 */
56
57/**
58 * Return a hash value for the structure indicated by `ptr` such that if
59 * `x`,`y` are two separate structures whose print representation is the same
60 * then `(sxhash x)` and `(sxhash y)` will always be equal.
61 */
62uint32_t sxhash( struct cons_pointer ptr ) {
63 // TODO: Not Yet Implemented
64 /* TODO: should look at the implementation of Common Lisp sxhash?
65 * My current implementation of `print` only addresses URL_FILE
66 * streams. It would be better if it also addressed strings but
67 * currently it doesn't. Creating a print string of the structure
68 * and taking the hash of that would be one simple (but not necessarily
69 * cheap) solution.
70 */
71 /* TODO: sbcl's implementation of `sxhash` is in src/compiler/sxhash.lisp
72 * and is EXTREMELY complex, and essentially has a different dispatch for
73 * every type of object. It's likely we need to do the same.
74 */
75 return 0;
76}
77
78/**
79 * Get the hash value for the cell indicated by this `ptr`; currently only
80 * implemented for string like things and integers.
81 */
82uint32_t get_hash( struct cons_pointer ptr ) {
83 struct cons_space_object *cell = &pointer2cell( ptr );
84 uint32_t result = 0;
85
86 switch ( cell->tag.value ) {
87 case INTEGERTV:
88 /* Note that we're only hashing on the least significant word of an
89 * integer. */
90 result = cell->payload.integer.value & 0xffffffff;
91 break;
92 case KEYTV:
93 case STRINGTV:
94 case SYMBOLTV:
95 result = cell->payload.string.hash;
96 break;
97 case TRUETV:
98 result = 1; // arbitrarily
99 break;
100 default:
101 result = sxhash( ptr );
102 break;
103 }
104
105 return result;
106}
107
108/**
109 * Free the hashmap indicated by this `pointer`.
110 */
111void free_hashmap( struct cons_pointer pointer ) {
112 struct cons_space_object *cell = &pointer2cell( pointer );
113
114 if ( hashmapp( pointer ) ) {
115 struct vector_space_object *vso = cell->payload.vectorp.address;
116
117 dec_ref( vso->payload.hashmap.hash_fn );
118 dec_ref( vso->payload.hashmap.write_acl );
119
120 for ( int i = 0; i < vso->payload.hashmap.n_buckets; i++ ) {
121 if ( !nilp( vso->payload.hashmap.buckets[i] ) ) {
123 L"Decrementing bucket [%d] of hashmap at 0x%lx\n",
124 i, cell->payload.vectorp.address );
125 dec_ref( vso->payload.hashmap.buckets[i] );
126 }
127 }
128 } else {
129 debug_printf( DEBUG_ALLOC, L"Non-hashmap passed to `free_hashmap`\n" );
130 }
131}
132
133
134/**
135 * Make a hashmap with this number of buckets, using this `hash_fn`. If
136 * `hash_fn` is `NIL`, use the standard hash funtion.
137 */
138struct cons_pointer make_hashmap( uint32_t n_buckets,
139 struct cons_pointer hash_fn,
140 struct cons_pointer write_acl ) {
141 struct cons_pointer result = make_vso( HASHTV,
142 ( sizeof( struct cons_pointer ) *
143 ( n_buckets + 2 ) ) +
144 ( sizeof( uint32_t ) * 2 ) );
145
146 struct hashmap_payload *payload =
147 ( struct hashmap_payload * ) &pointer_to_vso( result )->payload;
148
149 payload->hash_fn = inc_ref( hash_fn );
150 payload->write_acl = inc_ref( write_acl );
151
152 payload->n_buckets = n_buckets;
153 for ( int i = 0; i < n_buckets; i++ ) {
154 payload->buckets[i] = NIL;
155 }
156
157 return result;
158}
159
160/**
161 * return a flat list of all the keys in the hashmap indicated by `map`.
162 */
164 struct cons_pointer result = NIL;
165 if ( hashmapp( mapp ) && truep( authorised( mapp, NIL ) ) ) {
166 struct vector_space_object *map = pointer_to_vso( mapp );
167
168 for ( int i = 0; i < map->payload.hashmap.n_buckets; i++ ) {
169 for ( struct cons_pointer c = map->payload.hashmap.buckets[i];
170 !nilp( c ); c = c_cdr( c ) ) {
171 result = make_cons( c_car( c_car( c ) ), result );
172 }
173 }
174 }
175
176 return result;
177}
178
179/**
180 * Copy all key/value pairs in this association list `assoc` into this hashmap `mapp`. If
181 * current user is authorised to write to this hashmap, modifies the hashmap and
182 * returns it; if not, clones the hashmap, modifies the clone, and returns that.
183 */
185 struct cons_pointer assoc ) {
186 // TODO: if current user has write access to this hashmap
187 if ( hashmapp( mapp ) ) {
188 struct vector_space_object *map = pointer_to_vso( mapp );
189
190 if ( consp( assoc ) ) {
191 for ( struct cons_pointer pair = c_car( assoc ); !nilp( pair );
192 pair = c_car( assoc ) ) {
193 /* TODO: this is really hammering the memory management system, because
194 * it will make a new clone for every key/value pair added. Fix. */
195 if ( consp( pair ) ) {
196 mapp = hashmap_put( mapp, c_car( pair ), c_cdr( pair ) );
197 } else if ( hashmapp( pair ) ) {
198 hashmap_put_all( mapp, pair );
199 } else {
200 hashmap_put( mapp, pair, TRUE );
201 }
202 assoc = c_cdr( assoc );
203 }
204 } else if ( hashmapp( assoc ) ) {
205 for ( struct cons_pointer keys = hashmap_keys( assoc );
206 !nilp( keys ); keys = c_cdr( keys ) ) {
207 struct cons_pointer key = c_car( keys );
208 hashmap_put( mapp, key, hashmap_get( assoc, key, false ) );
209 }
210 }
211 }
212
213 return mapp;
214}
215
216/** Get a value from a hashmap.
217 *
218 * Note that this is here, rather than in memory/hashmap.c, because it is
219 * closely tied in with search_store, q.v.
220 */
222 struct cons_pointer key, bool return_key ) {
223#ifdef DEBUG
224 debug_print( L"\nhashmap_get: key is `", DEBUG_BIND );
226 debug_print( L"`; store of type `", DEBUG_BIND );
228 debug_printf( DEBUG_BIND, L"`; returning `%s`.\n",
229 return_key ? "key" : "value" );
230#endif
231
232 struct cons_pointer result = NIL;
233 if ( hashmapp( mapp ) && truep( authorised( mapp, NIL ) ) && !nilp( key ) ) {
234 struct vector_space_object *map = pointer_to_vso( mapp );
235 uint32_t bucket_no = get_hash( key ) % map->payload.hashmap.n_buckets;
236
237 result =
238 search_store( key, map->payload.hashmap.buckets[bucket_no],
239 return_key );
240 }
241#ifdef DEBUG
242 debug_print( L"\nhashmap_get returning: `", DEBUG_BIND );
244 debug_print( L"`\n", DEBUG_BIND );
245#endif
246
247 return result;
248}
249
250/**
251 * If this `ptr` is a pointer to a hashmap, return a new identical hashmap;
252 * else return an exception.
253 */
255 struct cons_pointer result = NIL;
256
257 if ( truep( authorised( ptr, NIL ) ) ) {
258 if ( hashmapp( ptr ) ) {
259 struct vector_space_object const *from = pointer_to_vso( ptr );
260
261 if ( from != NULL ) {
262 struct hashmap_payload from_pl = from->payload.hashmap;
263 result =
264 make_hashmap( from_pl.n_buckets, from_pl.hash_fn,
265 from_pl.write_acl );
266 struct vector_space_object const *to =
267 pointer_to_vso( result );
268 struct hashmap_payload to_pl = to->payload.hashmap;
269
270 for ( int i = 0; i < to_pl.n_buckets; i++ ) {
271 to_pl.buckets[i] = from_pl.buckets[i];
272 inc_ref( to_pl.buckets[i] );
273 }
274 }
275 }
276 } else {
277 result =
279 ( L"Arg to `clone_hashmap` must "
280 L"be a readable hashmap.`" ), NIL );
281 }
282
283 return result;
284}
285
286/**
287 * @brief `(search-store key store return-key?)` Search this `store` for this
288 * a key lexically identical to this `key`.
289 *
290 * If found, then, if `return-key?` is non-nil, return the copy found in the
291 * `store`, else return the value associated with it.
292 *
293 * At this stage the following structures are legal stores:
294 * 1. an association list comprising (key . value) dotted pairs;
295 * 2. a hashmap;
296 * 3. a namespace (which for these purposes is identical to a hashmap);
297 * 4. a hybrid list comprising both (key . value) pairs and hashmaps as first
298 * level items;
299 * 5. such a hybrid list, but where the last CDR pointer is to a hashmap
300 * rather than to a cons sell or to `nil`.
301 *
302 * This is over-complex and type 5 should be disallowed, but it will do for
303 * now.
304 */
306 struct cons_pointer store,
307 bool return_key ) {
308 struct cons_pointer result = NIL;
309
310#ifdef DEBUG
311 debug_print( L"\nsearch_store; key is `", DEBUG_BIND );
313 debug_print( L"`; store of type `", DEBUG_BIND );
315 debug_printf( DEBUG_BIND, L"`; returning `%s`.\n",
316 return_key ? "key" : "value" );
317#endif
318
319 switch ( get_tag_value( key ) ) {
320 case SYMBOLTV:
321 case KEYTV:
322 struct cons_space_object *store_cell = &pointer2cell( store );
323
324 switch ( get_tag_value( store ) ) {
325 case CONSTV:
326 for ( struct cons_pointer cursor = store;
327 nilp( result ) && ( consp( cursor )
328 || hashmapp( cursor ) );
329 cursor = pointer2cell( cursor ).payload.cons.cdr ) {
330 switch ( get_tag_value( cursor ) ) {
331 case CONSTV:
332 struct cons_pointer entry_ptr =
333 c_car( cursor );
334
335 switch ( get_tag_value( entry_ptr ) ) {
336 case CONSTV:
337 if ( equal( key, c_car( entry_ptr ) ) ) {
338 result =
339 return_key ? c_car( entry_ptr )
340 : c_cdr( entry_ptr );
341 goto found;
342 }
343 break;
344 case HASHTV:
345 case NAMESPACETV:
346 result =
347 hashmap_get( entry_ptr, key,
348 return_key );
349 break;
350 default:
351 result =
354 ( L"search-store (entry)" ),
357 ( L"Unexpected store type: " ),
358 c_type( c_car( entry_ptr ) ) ),
359 NIL );
360
361 }
362 break;
363 case HASHTV:
364 case NAMESPACETV:
366 ( L"\n\tHashmap as top-level value in list",
367 DEBUG_BIND );
368 result =
369 hashmap_get( cursor, key, return_key );
370 break;
371 default:
372 result =
374 ( L"search-store (cursor)" ),
377 ( L"Unexpected store type: " ),
378 c_type( cursor ) ),
379 NIL );
380 }
381 }
382 break;
383 case HASHTV:
384 case NAMESPACETV:
385 result = hashmap_get( store, key, return_key );
386 break;
387 default:
388 result =
390 ( L"search-store (store)" ),
392 ( L"Unexpected store type: " ),
393 c_type( store ) ), NIL );
394 break;
395 }
396 break;
397 case EXCEPTIONTV:
398 result =
400 ( L"search-store (exception)" ),
402 ( L"Unexpected key type: " ),
403 c_type( key ) ), NIL );
404
405 break;
406 default:
407 result =
409 ( L"search-store (key)" ),
411 ( L"Unexpected key type: " ),
412 c_type( key ) ), NIL );
413 }
414
415 found:
416
417 debug_print( L"search-store: returning `", DEBUG_BIND );
419 debug_print( L"`\n", DEBUG_BIND );
420
421 return result;
422}
423
425 struct cons_pointer store ) {
426 return search_store( key, store, true );
427}
428
429/**
430 * @brief Implementation of `interned?` in C.
431 *
432 * @param key the key to search for.
433 * @param store the store to search in.
434 * @return struct cons_pointer `t` if the key was found, else `nil`.
435 */
437 struct cons_pointer store ) {
438 struct cons_pointer result = NIL;
439
440 if ( consp( store ) ) {
441 for ( struct cons_pointer pair = c_car( store );
442 eq( result, NIL ) && !nilp( pair ); pair = c_car( store ) ) {
443 if ( consp( pair ) ) {
444 if ( equal( c_car( pair ), key ) ) {
445 // yes, this should be `eq`, but if symbols are correctly
446 // interned this will work efficiently, and if not it will
447 // still work.
448 result = TRUE;
449 }
450 } else if ( hashmapp( pair ) ) {
451 result = internedp( key, pair );
452 }
453
454 store = c_cdr( store );
455 }
456 } else if ( hashmapp( store ) ) {
457 struct vector_space_object *map = pointer_to_vso( store );
458
459 for ( int i = 0; i < map->payload.hashmap.n_buckets; i++ ) {
460 for ( struct cons_pointer c = map->payload.hashmap.buckets[i];
461 !nilp( c ); c = c_cdr( c ) ) {
462 result = internedp( key, c );
463 }
464 }
465 }
466
467 return result;
468}
469
470/**
471 * Implementation of assoc in C. Like interned?, the final implementation will
472 * deal with stores which can be association lists or hashtables or hybrids of
473 * the two, but that will almost certainly be implemented in lisp.
474 *
475 * If this key is lexically identical to a key in this store, return the value
476 * of that key from the store; otherwise return NIL.
477 */
479 struct cons_pointer store ) {
480 return search_store( key, store, false );
481}
482
483/**
484 * Store this `val` as the value of this `key` in this hashmap `mapp`. If
485 * current user is authorised to write to this hashmap, modifies the hashmap and
486 * returns it; if not, clones the hashmap, modifies the clone, and returns that.
487 */
489 struct cons_pointer key,
490 struct cons_pointer val ) {
491 if ( hashmapp( mapp ) && !nilp( key ) ) {
492 struct vector_space_object *map = pointer_to_vso( mapp );
493
494 if ( nilp( authorised( mapp, map->payload.hashmap.write_acl ) ) ) {
495 mapp = clone_hashmap( mapp );
496 map = pointer_to_vso( mapp );
497 }
498 uint32_t bucket_no = get_hash( key ) % map->payload.hashmap.n_buckets;
499
500 // TODO: if there are too many values in the bucket, rehash the whole
501 // hashmap to a bigger number of buckets, and return that.
502
503 map->payload.hashmap.buckets[bucket_no] =
504 make_cons( make_cons( key, val ),
505 map->payload.hashmap.buckets[bucket_no] );
506 }
507
508 debug_print( L"hashmap_put:\n", DEBUG_BIND );
510
511 return mapp;
512}
513
514/**
515 * If this store is modifiable, add this key value pair to it. Otherwise,
516 * return a new key/value store containing all the key/value pairs in this
517 * store with this key/value pair added to the front.
518 */
519struct cons_pointer set( struct cons_pointer key, struct cons_pointer value,
520 struct cons_pointer store ) {
521 struct cons_pointer result = NIL;
522
523#ifdef DEBUG
524 bool deep = eq( store, oblist );
525 debug_print_binding( key, value, deep, DEBUG_BIND );
526
527 if ( deep ) {
528 debug_printf( DEBUG_BIND, L"\t-> %4.4s\n",
529 pointer2cell( store ).payload.vectorp.tag.bytes );
530 }
531#endif
532 if ( nilp( store ) || consp( store ) ) {
533 result = make_cons( make_cons( key, value ), store );
534 } else if ( hashmapp( store ) ) {
535 result = hashmap_put( store, key, value );
536 }
537
538 return result;
539}
540
541/**
542 * @brief Binds this `key` to this `value` in the global oblist, and returns the `key`.
543 */
544struct cons_pointer
545deep_bind( struct cons_pointer key, struct cons_pointer value ) {
546 debug_print( L"Entering deep_bind\n", DEBUG_BIND );
547
548 oblist = set( key, value, oblist );
549
550 debug_print( L"deep_bind returning ", DEBUG_BIND );
553
554 return key;
555}
556
557/**
558 * Ensure that a canonical copy of this key is bound in this environment, and
559 * return that canonical copy. If there is currently no such binding, create one
560 * with the value TRUE.
561 */
562struct cons_pointer
563intern( struct cons_pointer key, struct cons_pointer environment ) {
564 struct cons_pointer result = environment;
565 struct cons_pointer canonical = internedp( key, environment );
566 if ( nilp( canonical ) ) {
567 /*
568 * not currently bound. TODO: this should bind to NIL?
569 */
570 result = set( key, TRUE, environment );
571 }
572
573 return result;
574}
struct cons_pointer authorised(struct cons_pointer target, struct cons_pointer acl)
TODO: does nothing, yet.
Definition authorise.c:18
struct cons_pointer dec_ref(struct cons_pointer pointer)
Decrement the reference count of the object at this cons pointer.
#define KEYTV
The string KEYW, considered as an unsigned int.
#define truep(conspoint)
true if conspoint points to something that is truthy, i.e.
#define SYMBOLTV
The string SYMB, considered as an unsigned int.
union cons_space_object::@2 tag
union cons_space_object::@3 payload
#define NIL
a cons pointer which points to the special NIL cell
struct cons_pointer make_exception(struct cons_pointer message, struct cons_pointer frame_pointer)
Construct an exception cell.
struct cons_pointer c_cdr(struct cons_pointer arg)
Implementation of cdr in C.
#define STRINGTV
The string STRG, considered as an unsigned int.
#define INTEGERTV
The string INTR, considered as an unsigned int.
#define consp(conspoint)
true if conspoint points to a cons cell, else false
#define CONSTV
The string CONS, considered as an unsigned int.
#define nilp(conspoint)
true if conspoint points to the special cell NIL, else false (there should only be one of these so it...
#define TRUETV
The string TRUE, considered as an unsigned int.
uint32_t get_tag_value(struct cons_pointer pointer)
given a cons_pointer as argument, return the tag.
struct cons_pointer c_string_to_lisp_string(wchar_t *string)
Return a lisp string representation of this wide character string.
struct cons_pointer inc_ref(struct cons_pointer pointer)
increment the reference count of the object at this cons pointer.
#define EXCEPTIONTV
The string EXEP, considered as an unsigned int.
#define TRUE
a cons pointer which points to the special T cell
struct cons_pointer c_string_to_lisp_symbol(wchar_t *symbol)
Return a lisp symbol representation of this wide character string.
struct cons_pointer c_car(struct cons_pointer arg)
Implementation of car in C.
struct cons_pointer c_type(struct cons_pointer pointer)
Get the Lisp type of the single argument.
#define pointer2cell(pointer)
given a cons_pointer as argument, return the cell.
struct cons_pointer make_cons(struct cons_pointer car, struct cons_pointer cdr)
Construct a cons cell from this pair of pointers.
An indirect pointer to a cons cell.
an object in cons space.
void debug_print_binding(struct cons_pointer key, struct cons_pointer val, bool deep, int level)
Standardise printing of binding trace messages.
Definition debug.c:169
void debug_println(int level)
print a line feed to stderr, if verbosity matches level.
Definition debug.c:104
void debug_dump_object(struct cons_pointer pointer, int level)
Like dump_object, q.v., but protected by the verbosity mechanism.
Definition debug.c:155
void debug_printf(int level, wchar_t *format,...)
wprintf adapted for the debug logging system.
Definition debug.c:120
void debug_print(wchar_t *message, int level)
print this debug message to stderr, if verbosity matches level.
Definition debug.c:60
void debug_print_object(struct cons_pointer pointer, int level)
print the object indicated by this pointer to stderr, if verbosity matches level.
Definition debug.c:138
#define DEBUG_BIND
Print messages debugging symbol binding.
Definition debug.h:38
#define DEBUG_ALLOC
Print messages debugging memory allocation.
Definition debug.h:24
bool equal(struct cons_pointer a, struct cons_pointer b)
Deep, and thus expensive, equality: true if these two objects have identical structure,...
Definition equal.c:334
bool eq(struct cons_pointer a, struct cons_pointer b)
Shallow, and thus cheap, equality: true if these two objects are the same object, else false.
Definition equal.c:28
struct cons_pointer search_store(struct cons_pointer key, struct cons_pointer store, bool return_key)
(search-store key store return-key?) Search this store for this a key lexically identical to this key...
Definition intern.c:305
struct cons_pointer hashmap_put(struct cons_pointer mapp, struct cons_pointer key, struct cons_pointer val)
Store this val as the value of this key in this hashmap mapp.
Definition intern.c:488
struct cons_pointer privileged_symbol_nil
the symbol NIL, which is special!
Definition intern.c:55
void free_hashmap(struct cons_pointer pointer)
Free the hashmap indicated by this pointer.
Definition intern.c:111
struct cons_pointer hashmap_put_all(struct cons_pointer mapp, struct cons_pointer assoc)
Copy all key/value pairs in this association list assoc into this hashmap mapp.
Definition intern.c:184
struct cons_pointer make_hashmap(uint32_t n_buckets, struct cons_pointer hash_fn, struct cons_pointer write_acl)
Make a hashmap with this number of buckets, using this hash_fn.
Definition intern.c:138
struct cons_pointer hashmap_keys(struct cons_pointer mapp)
return a flat list of all the keys in the hashmap indicated by map.
Definition intern.c:163
struct cons_pointer hashmap_get(struct cons_pointer mapp, struct cons_pointer key, bool return_key)
Get a value from a hashmap.
Definition intern.c:221
uint32_t get_hash(struct cons_pointer ptr)
Get the hash value for the cell indicated by this ptr; currently only implemented for string like thi...
Definition intern.c:82
struct cons_pointer internedp(struct cons_pointer key, struct cons_pointer store)
Implementation of interned? in C.
Definition intern.c:436
uint32_t sxhash(struct cons_pointer ptr)
Return a hash value for the structure indicated by ptr such that if x,y are two separate structures w...
Definition intern.c:62
struct cons_pointer c_assoc(struct cons_pointer key, struct cons_pointer store)
Implementation of assoc in C.
Definition intern.c:478
struct cons_pointer interned(struct cons_pointer key, struct cons_pointer store)
Definition intern.c:424
struct cons_pointer intern(struct cons_pointer key, struct cons_pointer environment)
Ensure that a canonical copy of this key is bound in this environment, and return that canonical copy...
Definition intern.c:563
struct cons_pointer oblist
The global object list/or, to put it differently, the root namespace.
Definition intern.c:49
struct cons_pointer clone_hashmap(struct cons_pointer ptr)
If this ptr is a pointer to a hashmap, return a new identical hashmap; else return an exception.
Definition intern.c:254
struct cons_pointer deep_bind(struct cons_pointer key, struct cons_pointer value)
Binds this key to this value in the global oblist, and returns the key.
Definition intern.c:545
struct cons_pointer set(struct cons_pointer key, struct cons_pointer value, struct cons_pointer store)
If this store is modifiable, add this key value pair to it.
Definition intern.c:519
struct cons_pointer throw_exception(struct cons_pointer location, struct cons_pointer payload, struct cons_pointer frame_pointer)
Throw an exception.
Definition lispops.c:1396
struct cons_pointer make_vso(uint32_t tag, uint64_t payload_size)
Allocate a vector space object with this payload_size and tag, and return a cons_pointer which points...
Definition vectorspace.c:78
struct cons_pointer hash_fn
Definition vectorspace.h:89
uint32_t n_buckets
Definition vectorspace.h:95
struct cons_pointer write_acl
Definition vectorspace.h:91
union vector_space_object::@5 payload
we'll malloc size bytes for payload, payload is just the first of these.
#define pointer_to_vso(pointer)
given a pointer to a vector space object, return the object.
Definition vectorspace.h:55
#define HASHTV
Definition vectorspace.h:30
#define hashmapp(conspoint)
Definition vectorspace.h:32
#define NAMESPACETV
Definition vectorspace.h:40
struct cons_pointer buckets[]
Definition vectorspace.h:97
The payload of a hashmap.
Definition vectorspace.h:88
a vector_space_object is just a vector_space_header followed by a lump of bytes; what we deem to be i...