Huge amount of work. Does not even nearly compile, but it's nearer.
This commit is contained in:
parent
1afb1b9fad
commit
cae27731b7
31 changed files with 407 additions and 96 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* debug.h
|
* debug.c
|
||||||
*
|
*
|
||||||
* Post Scarcity Software Environment: entry point.
|
* Post Scarcity Software Environment: debugging messages.
|
||||||
*
|
*
|
||||||
* Print debugging output.
|
* Print debugging output.
|
||||||
*
|
*
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
int verbosity = 0;
|
int verbosity = 0;
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,10 @@
|
||||||
#define __psse_debug_h
|
#define __psse_debug_h
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Print messages debugging memory allocation.
|
* @brief Print messages debugging memory allocation.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <bits/stdint-uintn.h>
|
#include <bits/stdint-uintn.h>
|
||||||
|
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
#define TAGLENGTH 3
|
#define TAGLENGTH 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
struct pso_header {
|
struct pso_header {
|
||||||
union {
|
union {
|
||||||
/** the tag (type) of this cell,
|
/** the tag (type) of this object,
|
||||||
* considered as bytes */
|
* considered as bytes */
|
||||||
struct {
|
struct {
|
||||||
/** mnemonic for this type; */
|
/** mnemonic for this type; */
|
||||||
|
|
@ -31,10 +33,10 @@ struct pso_header {
|
||||||
/** the tag considered as a number */
|
/** the tag considered as a number */
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
} tag;
|
} tag;
|
||||||
/** the count of the number of references to this cell */
|
/** the count of the number of references to this object */
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
/** cons pointer to the access control list of this cell */
|
/** pointer to the access control list of this object */
|
||||||
struct cons_pointer access;
|
struct pso_pointer access;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ struct pso_pointer freelists[MAX_SIZE_CLASS + 1];
|
||||||
|
|
||||||
|
|
||||||
int initialise_memory( int node ) {
|
int initialise_memory( int node ) {
|
||||||
fprintf( stderr, "TODO: Implement initialise_memory()" );
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i <= MAX_SIZE_CLASS; i++) {
|
for (uint8_t i = 0; i <= MAX_SIZE_CLASS; i++) {
|
||||||
freelists[i] = nil;S
|
freelists[i] = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
#ifndef __psse_memory_memory_h
|
#ifndef __psse_memory_memory_h
|
||||||
#define __psse_memory_memory_h
|
#define __psse_memory_memory_h
|
||||||
|
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum size class
|
* @brief Maximum size class
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@
|
||||||
#ifndef __psse_memory_node_h
|
#ifndef __psse_memory_node_h
|
||||||
#define __psse_memory_node_h
|
#define __psse_memory_node_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The index of this node in the hypercube.
|
* @brief The index of this node in the hypercube.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
extern int node_index;
|
extern uint32_t node_index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The canonical `nil` pointer
|
* @brief The canonical `nil` pointer
|
||||||
|
|
@ -30,4 +31,6 @@ extern struct pso_pointer nil;
|
||||||
*/
|
*/
|
||||||
extern struct pso_pointer t;
|
extern struct pso_pointer t;
|
||||||
|
|
||||||
|
struct pso_pointer initialise_node( uint32_t index );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,27 @@ struct page * pages[NPAGES];
|
||||||
*/
|
*/
|
||||||
uint32_t npages_allocated = 0
|
uint32_t npages_allocated = 0
|
||||||
|
|
||||||
struct cons_pointer initialise_page( struct page * result, uint16_t page_index, uint8_t size_class, pso_pointer freelist) {
|
/**
|
||||||
|
* @brief private to allocate_page; do not use.
|
||||||
|
*
|
||||||
|
* @param page_addr address of the newly allocated page to be initialised;
|
||||||
|
* @param page_index its location in the pages[] array;
|
||||||
|
* @param size_class the size class of objects in this page;
|
||||||
|
* @param freelist the freelist for objects of this size class.
|
||||||
|
* @return struct cons_pointer the new head for the freelist for this size_class,
|
||||||
|
*/
|
||||||
|
struct cons_pointer initialise_page( struct page * page_addr, uint16_t page_index, uint8_t size_class, pso_pointer freelist) {
|
||||||
struct cons_pointer result = freelist;
|
struct cons_pointer result = freelist;
|
||||||
int obj_size = pow(2, size_class);
|
int obj_size = pow(2, size_class);
|
||||||
int obj_bytes = obj_size * sizeof(uint64_t);
|
int obj_bytes = obj_size * sizeof(uint64_t);
|
||||||
int objs_in_page = PAGE_BYTES/obj_bytes;
|
int objs_in_page = PAGE_BYTES/obj_bytes;
|
||||||
|
|
||||||
|
// we do this backwards (i--) so that object {0, 0, 0} will be first on the
|
||||||
|
// freelist when the first page is initiated, so we can grab that one for
|
||||||
|
// `nil` and the next on for `t`.
|
||||||
for (int i = objs_in_page - 1; i >= 0; i--) {
|
for (int i = objs_in_page - 1; i >= 0; i--) {
|
||||||
// it should be safe to cast any pso object to a pso2
|
// it should be safe to cast any pso object to a pso2
|
||||||
struct pso2* object = (pso2 *)(result + (i * obj_bytes));
|
struct pso2* object = (pso2 *)(page_addr + (i * obj_bytes));
|
||||||
|
|
||||||
object->header.tag.size_class = size_class;
|
object->header.tag.size_class = size_class;
|
||||||
strncpy( (char *)(object->header.tag.mnemonic), FREETAG, TAGLENGTH);
|
strncpy( (char *)(object->header.tag.mnemonic), FREETAG, TAGLENGTH);
|
||||||
|
|
@ -75,10 +87,10 @@ struct cons_pointer initialise_page( struct page * result, uint16_t page_index,
|
||||||
* cast it back.
|
* cast it back.
|
||||||
*
|
*
|
||||||
* @param size_class an integer in the range 0...MAX_SIZE_CLASS.
|
* @param size_class an integer in the range 0...MAX_SIZE_CLASS.
|
||||||
* @return a pointer to the page, or NULL if an error occurred.
|
* @return t on success, an exception if an error occurred.
|
||||||
*/
|
*/
|
||||||
void *allocate_page( uint8_t size_class ) {
|
struct cons_pointer allocate_page( uint8_t size_class ) {
|
||||||
void *result = NULL;
|
struct cons_pointer result = t;
|
||||||
|
|
||||||
if ( npages_allocated == 0) {
|
if ( npages_allocated == 0) {
|
||||||
for (int i = 0; i < NPAGES; i++) {
|
for (int i = 0; i < NPAGES; i++) {
|
||||||
|
|
@ -108,22 +120,28 @@ void *allocate_page( uint8_t size_class ) {
|
||||||
|
|
||||||
npages_allocated ++;
|
npages_allocated ++;
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: exception when we have one.
|
||||||
|
result = nil;
|
||||||
fwide( stderr, 1 );
|
fwide( stderr, 1 );
|
||||||
fwprintf( stderr,
|
fwprintf( stderr,
|
||||||
L"\nCannot allocate page: heap exhausted,\n",
|
L"\nCannot allocate page: heap exhausted,\n",
|
||||||
size_class, MAX_SIZE_CLASS );
|
size_class, MAX_SIZE_CLASS );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: exception when we have one.
|
||||||
|
result = nil;
|
||||||
fwide( stderr, 1 );
|
fwide( stderr, 1 );
|
||||||
fwprintf( stderr,
|
fwprintf( stderr,
|
||||||
L"\nCannot allocate page for size class %x, min is 2 max is %x.\n",
|
L"\nCannot allocate page for size class %x, min is 2 max is %x.\n",
|
||||||
size_class, MAX_SIZE_CLASS );
|
size_class, MAX_SIZE_CLASS );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fwide( stderr, 1 );
|
// TODO: exception when we have one.
|
||||||
fwprintf( stderr,
|
result = nil;
|
||||||
L"\nCannot allocate page: page space exhausted.\n",
|
fwide( stderr, 1 );
|
||||||
size_class, MAX_SIZE_CLASS );
|
fwprintf( stderr,
|
||||||
|
L"\nCannot allocate page: page space exhausted.\n",
|
||||||
|
size_class, MAX_SIZE_CLASS );
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ struct pso_pointer {
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct pso_pointer make_pointer( uint32_t node, uint16_t page, uint16_t offset);
|
struct pso_pointer make_pointer( uint32_t node, uint16_t page, uint16_t offset);
|
||||||
|
|
||||||
|
struct pso2* pointer_to_object( struct pso_pointer pointer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,26 @@
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct cons_pointer allocate( char* tag, uint8_t size_class) {
|
#include "memory/page.h"
|
||||||
struct cons_pointer result = nil;
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate an object of this size_class with this tag.
|
||||||
|
*
|
||||||
|
* @param tag The tag. Only the first three bytes will be used;
|
||||||
|
* @param size_class The size class for the object to be allocated;
|
||||||
|
* @return struct pso_pointer a pointer to the newly allocated object
|
||||||
|
*/
|
||||||
|
struct pso_pointer allocate( char* tag, uint8_t size_class) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
if (size_class <= MAX_SIZE_CLASS) {
|
if (size_class <= MAX_SIZE_CLASS) {
|
||||||
if ( not( freelists[size_class] ) ) {
|
if (freelists[size_class] == nil) {
|
||||||
|
result = allocate_page(size_class)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !exceptionp( result) && not( freelists[size_class] ) ) {
|
||||||
result = freelists[size_class];
|
result = freelists[size_class];
|
||||||
struct pso2* object = pointer_to_object( result);
|
struct pso2* object = pointer_to_object( result);
|
||||||
freelists[size_class] = object->payload.free.next;
|
freelists[size_class] = object->payload.free.next;
|
||||||
|
|
@ -32,7 +47,7 @@ struct cons_pointer allocate( char* tag, uint8_t size_class) {
|
||||||
}
|
}
|
||||||
/* the objext ought to have a reference count ot zero, because it's
|
/* the objext ought to have a reference count ot zero, because it's
|
||||||
* on the freelist, but again we should sanity check. */
|
* on the freelist, but again we should sanity check. */
|
||||||
if ( object->header.count != 0) {
|
if ( object->header.header.count != 0) {
|
||||||
// TODO: return an exception instead? Or warn, set it, and continue?
|
// TODO: return an exception instead? Or warn, set it, and continue?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,6 +57,97 @@ struct cons_pointer allocate( char* tag, uint8_t size_class) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cons_pointer get_tag_value( struct cons_pointer pointer) {
|
/**
|
||||||
result =
|
* increment the reference count of the object at this cons pointer.
|
||||||
|
*
|
||||||
|
* You can't roll over the reference count. Once it hits the maximum
|
||||||
|
* value you cannot increment further.
|
||||||
|
*
|
||||||
|
* Returns the `pointer`.
|
||||||
|
*/
|
||||||
|
struct pso_pointer inc_ref( struct pso_pointer pointer ) {
|
||||||
|
struct pso2 *object = pointer_to_object( pointer );
|
||||||
|
|
||||||
|
if ( object->header.count < MAXREFERENCE ) {
|
||||||
|
object->header.count++;
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug_printf( DEBUG_ALLOC,
|
||||||
|
L"\nIncremented object of type %4.4s at page %u, offset %u to count %u",
|
||||||
|
( ( char * ) object->header.tag.bytes ), pointer.page,
|
||||||
|
pointer.offset, object->header.count );
|
||||||
|
if ( strncmp( object->header.tag.bytes, VECTORPOINTTAG, TAGLENGTH ) == 0 ) {
|
||||||
|
debug_printf( DEBUG_ALLOC,
|
||||||
|
L"; pointer to vector object of type %4.4s.\n",
|
||||||
|
( ( char * ) ( object->header.payload.vectorp.tag.bytes ) ) );
|
||||||
|
} else {
|
||||||
|
debug_println( DEBUG_ALLOC );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement the reference count of the object at this cons pointer.
|
||||||
|
*
|
||||||
|
* If a count has reached MAXREFERENCE it cannot be decremented.
|
||||||
|
* If a count is decremented to zero the object should be freed.
|
||||||
|
*
|
||||||
|
* Returns the `pointer`, or, if the object has been freed, a pointer to `nil`.
|
||||||
|
*/
|
||||||
|
struct pso_pointer dec_ref( struct pso_pointer pointer ) {
|
||||||
|
struct pso2 *object = pointer_to_object( pointer );
|
||||||
|
|
||||||
|
if ( object->count > 0 && object->count != MAXREFERENCE ) {
|
||||||
|
object->count--;
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug_printf( DEBUG_ALLOC,
|
||||||
|
L"\nDecremented object of type %4.4s at page %d, offset %d to count %d",
|
||||||
|
( ( char * ) object->tag.bytes ), pointer.page,
|
||||||
|
pointer.offset, object->count );
|
||||||
|
if ( strncmp( ( char * ) object->tag.bytes, VECTORPOINTTAG, TAGLENGTH )
|
||||||
|
== 0 ) {
|
||||||
|
debug_printf( DEBUG_ALLOC,
|
||||||
|
L"; pointer to vector object of type %4.4s.\n",
|
||||||
|
( ( char * ) ( object->payload.vectorp.tag.bytes ) ) );
|
||||||
|
} else {
|
||||||
|
debug_println( DEBUG_ALLOC );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( object->header.count == 0 ) {
|
||||||
|
free_cell( pointer );
|
||||||
|
pointer = NIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prevent an object ever being dereferenced.
|
||||||
|
*
|
||||||
|
* @param pointer pointer to an object to lock.
|
||||||
|
*/
|
||||||
|
void lock_object( struct pso_pointer pointer) {
|
||||||
|
struct pso2* object = pointer_to_object( pointer );
|
||||||
|
|
||||||
|
object->header.header.count = MAXREFERENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the numeric value of the tag bytes of the object indicated
|
||||||
|
* by this pointer
|
||||||
|
*
|
||||||
|
* @param pointer a pointer to an object.
|
||||||
|
* @return the tag value of the object indicated.
|
||||||
|
*/
|
||||||
|
uint32_t get_tag_value( struct pso_pointer pointer) {
|
||||||
|
result = (pointer_to_object( pointer)->tag.value & 0xffffff;
|
||||||
|
|
||||||
|
// TODO: deal with the vector pointer issue
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -13,13 +13,17 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "memory/header.h"
|
#include "memory/header.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
#include "payloads/cons.h"
|
#include "payloads/cons.h"
|
||||||
|
#include "payloads/exception.h"
|
||||||
#include "payloads/free.h"
|
#include "payloads/free.h"
|
||||||
#include "payloads/function.h"
|
#include "payloads/function.h"
|
||||||
|
#include "payloads/hashtable.h"
|
||||||
#include "payloads/integer.h"
|
#include "payloads/integer.h"
|
||||||
#include "payloads/ketwod.h"
|
#include "payloads/keyword.h"
|
||||||
#include "payloads/lambda.h"
|
#include "payloads/lambda.h"
|
||||||
#include "payloads/mutex.h"
|
#include "payloads/mutex.h"
|
||||||
|
#include "payloads/namespace.h"
|
||||||
#include "payloads/nlambda.h"
|
#include "payloads/nlambda.h"
|
||||||
#include "payloads/read_stream.h"
|
#include "payloads/read_stream.h"
|
||||||
#include "payloads/special.h"
|
#include "payloads/special.h"
|
||||||
|
|
@ -38,8 +42,8 @@
|
||||||
struct pso2 {
|
struct pso2 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[16] bytes;
|
char bytes[16];
|
||||||
uint64_t[2] words;
|
uint64_t words[2];
|
||||||
struct cons_payload cons;
|
struct cons_payload cons;
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
struct function_payload function;
|
struct function_payload function;
|
||||||
|
|
@ -60,8 +64,8 @@ struct pso2 {
|
||||||
struct pso3 {
|
struct pso3 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[48] bytes;
|
char bytes[48];
|
||||||
uint64_t[6] words;
|
uint64_t words[6];
|
||||||
struct exception_payload exception;
|
struct exception_payload exception;
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
struct mutex_payload mutex;
|
struct mutex_payload mutex;
|
||||||
|
|
@ -76,8 +80,8 @@ struct pso3 {
|
||||||
struct pso4 {
|
struct pso4 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[112] bytes;
|
char bytes[112];
|
||||||
uint64_t[14] words;
|
uint64_t words[14];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
struct stack_frame_payload stack_frame;
|
struct stack_frame_payload stack_frame;
|
||||||
} payload;
|
} payload;
|
||||||
|
|
@ -91,8 +95,8 @@ struct pso4 {
|
||||||
struct pso5 {
|
struct pso5 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[240] bytes;
|
char bytes[240];
|
||||||
uint64_t[30] words;
|
uint64_t words[30];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -105,8 +109,8 @@ struct pso5 {
|
||||||
struct pso6 {
|
struct pso6 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[496] bytes;
|
char bytes[496];
|
||||||
uint64_t[62] words;
|
uint64_t words[62];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
struct hashtable_payload hashtable;
|
struct hashtable_payload hashtable;
|
||||||
struct namespace_payload namespace;
|
struct namespace_payload namespace;
|
||||||
|
|
@ -121,8 +125,8 @@ struct pso6 {
|
||||||
struct pso7 {
|
struct pso7 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[1008] bytes;
|
char bytes[1008];
|
||||||
uint64_t[126] words;
|
uint64_t words[126];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -135,8 +139,8 @@ struct pso7 {
|
||||||
struct pso8 {
|
struct pso8 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[2032] bytes;
|
char bytes[2032];
|
||||||
uint64_t[254] words;
|
uint64_t words[254];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -149,8 +153,8 @@ struct pso8 {
|
||||||
struct pso9 {
|
struct pso9 {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[4080] bytes;
|
char bytes[4080];
|
||||||
uint64_t[510] words;
|
uint64_t words[510];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -163,8 +167,8 @@ struct pso9 {
|
||||||
struct psoa {
|
struct psoa {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[8176] bytes;
|
char bytes[8176];
|
||||||
uint64_t[1022] words;
|
uint64_t words[1022];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -177,8 +181,8 @@ struct psoa {
|
||||||
struct psob {
|
struct psob {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[16368] bytes;
|
char bytes[16368];
|
||||||
uint64_t[2046] words;
|
uint64_t words[2046];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -191,8 +195,8 @@ struct psob {
|
||||||
struct psoc {
|
struct psoc {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[32752] bytes;
|
char bytes[32752];
|
||||||
uint64_t[4094] words;
|
uint64_t words[4094];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -205,8 +209,8 @@ struct psoc {
|
||||||
struct psod {
|
struct psod {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[65520] bytes;
|
char bytes[65520];
|
||||||
uint64_t[8190] words;
|
uint64_t words[8190];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -219,8 +223,8 @@ struct psod {
|
||||||
struct psoe {
|
struct psoe {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[131056] bytes;
|
char bytes[131056];
|
||||||
uint64_t[16382] words;
|
uint64_t words[16382];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
@ -233,8 +237,18 @@ struct psoe {
|
||||||
struct psof {
|
struct psof {
|
||||||
struct pso_header header;
|
struct pso_header header;
|
||||||
union {
|
union {
|
||||||
char[262128] bytes;
|
char bytes[262128];
|
||||||
uint64_t[32766] words;
|
uint64_t words[32766];
|
||||||
struct free_payload free;
|
struct free_payload free;
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso_pointer allocate( char* tag, uint8_t size_class);
|
||||||
|
|
||||||
|
struct pso_pointer dec_ref( struct pso_pointer pointer );
|
||||||
|
|
||||||
|
struct pso_pointer inc_ref( struct pso_pointer pointer );
|
||||||
|
|
||||||
|
void lock_object( struct pso_pointer pointer);
|
||||||
|
|
||||||
|
#endif
|
||||||
86
src/c/payloads/cons.c
Normal file
86
src/c/payloads/cons.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
* payloads/cons.h
|
||||||
|
*
|
||||||
|
* A cons cell.
|
||||||
|
*
|
||||||
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "memory/node.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
#include "payloads/cons.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief allocate a cons cell with this car and this cdr, and return a pointer
|
||||||
|
* to it.
|
||||||
|
*
|
||||||
|
* @param car the pointer which should form the car of this cons cell;
|
||||||
|
* @param cdr the pointer which should form the cdr of this cons cell.
|
||||||
|
* @return struct pso_pointer a pointer to the newly allocated cons cell.
|
||||||
|
*/
|
||||||
|
struct pso_pointer cons( struct pso_pointer car, struct pso_pointer cdr) {
|
||||||
|
struct pso_pointer result = allocate( CONSTAG, 2);
|
||||||
|
|
||||||
|
struct pso2 *object = pointer_to_object( result );
|
||||||
|
object->payload.cons.car = car;
|
||||||
|
object->payload.cons.cdr = cdr;
|
||||||
|
|
||||||
|
inc_ref( car);
|
||||||
|
inc_ref( cdr);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return true if `ptr` indicates a cons cell, else false.
|
||||||
|
*
|
||||||
|
* @param ptr a pointer.
|
||||||
|
* @return true if `ptr` indicates a cons cell.
|
||||||
|
* @return false otherwise
|
||||||
|
*/
|
||||||
|
bool consp( struct pso_pointer ptr) {
|
||||||
|
// TODO: make it actually work!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the car of this cons cell.
|
||||||
|
*
|
||||||
|
* @param cons a pointer to the cell.
|
||||||
|
* @return the car of the indicated cell.
|
||||||
|
* @exception if the pointer does not indicate a cons cell.
|
||||||
|
*/
|
||||||
|
struct pso_pointer car( struct pso_pointer cons) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
struct pso2 *object = pointer_to_object( result );
|
||||||
|
|
||||||
|
if ( consp( cons)) {
|
||||||
|
result = object->payload.cons.car;
|
||||||
|
}
|
||||||
|
// TODO: else throw an exception
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return the cdr of this cons cell.
|
||||||
|
*
|
||||||
|
* @param cons a pointer to the cell.
|
||||||
|
* @return the cdr of the indicated cell.
|
||||||
|
* @exception if the pointer does not indicate a cons cell.
|
||||||
|
*/
|
||||||
|
struct pso_pointer cdr( struct pso_pointer cons) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
struct pso2 *object = pointer_to_object( result );
|
||||||
|
|
||||||
|
if ( consp( cons)) {
|
||||||
|
result = object->payload.cons.cdr;
|
||||||
|
}
|
||||||
|
// TODO: else throw an exception
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#ifndef __psse_payloads_cons_h
|
#ifndef __psse_payloads_cons_h
|
||||||
#define __psse_payloads_cons_h
|
#define __psse_payloads_cons_h
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
|
@ -16,6 +17,7 @@
|
||||||
* An ordinary cons cell:
|
* An ordinary cons cell:
|
||||||
*/
|
*/
|
||||||
#define CONSTAG "CNS"
|
#define CONSTAG "CNS"
|
||||||
|
#define CONSTV 5459523
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A cons cell.
|
* @brief A cons cell.
|
||||||
|
|
@ -28,5 +30,12 @@ struct cons_payload {
|
||||||
struct pso_pointer cdr;
|
struct pso_pointer cdr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso_pointer car( struct pso_pointer cons);
|
||||||
|
|
||||||
|
struct pso_pointer cdr( struct pso_pointer cons);
|
||||||
|
|
||||||
|
struct pso_pointer cons( struct pso_pointer car, struct pso_pointer cdr);
|
||||||
|
|
||||||
|
bool consp( struct pso_pointer ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
#define EXCEPTIONTAG "EXP"
|
||||||
|
#define EXCEPTIONTV 5265477
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An exception; required three pointers, so use object of size class 3.
|
* @brief An exception; required three pointers, so use object of size class 3.
|
||||||
*/
|
*/
|
||||||
|
|
@ -21,7 +24,7 @@ struct exception_payload {
|
||||||
/** @brief the stack frame at which the exception was thrown. */
|
/** @brief the stack frame at which the exception was thrown. */
|
||||||
struct pso_pointer stack;
|
struct pso_pointer stack;
|
||||||
/** @brief the cause; expected to be another exception, or (usually) `nil`. */
|
/** @brief the cause; expected to be another exception, or (usually) `nil`. */
|
||||||
struct cons_pointer cause;
|
struct pso_pointer cause;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
* @brief Tag for an unassigned object; may be of any size class.
|
* @brief Tag for an unassigned object; may be of any size class.
|
||||||
*/
|
*/
|
||||||
#define FREETAG "FRE"
|
#define FREETAG "FRE"
|
||||||
|
#define FREETV 4543046
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An unassigned object, on a freelist; may be of any size class.
|
* @brief An unassigned object, on a freelist; may be of any size class.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#define __psse_payloads_function_h
|
#define __psse_payloads_function_h
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Tag for an ordinary Lisp function - one whose arguments are pre-evaluated.
|
* @brief Tag for an ordinary Lisp function - one whose arguments are pre-evaluated.
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
* \see SPECIALTAG for functions whose arguments are not pre-evaluated.
|
* \see SPECIALTAG for functions whose arguments are not pre-evaluated.
|
||||||
*/
|
*/
|
||||||
#define FUNCTIONTAG "FUN"
|
#define FUNCTIONTAG "FUN"
|
||||||
|
#define FUNCTIONTV 5133638
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Payload of a function cell.
|
* @brief Payload of a function cell.
|
||||||
|
|
@ -32,16 +34,16 @@ struct function_payload {
|
||||||
/**
|
/**
|
||||||
* pointer to metadata (e.g. the source from which the function was compiled).
|
* pointer to metadata (e.g. the source from which the function was compiled).
|
||||||
*/
|
*/
|
||||||
struct cons_pointer meta;
|
struct pso_pointer meta;
|
||||||
/** pointer to a function which takes a cons pointer (representing
|
/** pointer to a function which takes a cons pointer (representing
|
||||||
* its argument list) and a cons pointer (representing its environment) and a
|
* its argument list) and a cons pointer (representing its environment) and a
|
||||||
* stack frame (representing the previous stack frame) as arguments and returns
|
* stack frame (representing the previous stack frame) as arguments and returns
|
||||||
* a cons pointer (representing its result).
|
* a cons pointer (representing its result).
|
||||||
* \todo check this documentation is current!
|
* \todo check this documentation is current!
|
||||||
*/
|
*/
|
||||||
struct cons_pointer ( *executable ) ( struct stack_frame *,
|
struct pso_pointer ( *executable ) ( struct pso4 *,
|
||||||
struct cons_pointer,
|
struct pso_pointer,
|
||||||
struct cons_pointer );
|
struct pso_pointer );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,25 @@
|
||||||
*
|
*
|
||||||
* an ordinary Lisp hashtable - one whose contents are immutable.
|
* an ordinary Lisp hashtable - one whose contents are immutable.
|
||||||
*
|
*
|
||||||
* Can sensibly sit in any pso from size class 6 upwards.
|
* Can sensibly sit in any pso from size class 6 upwards. However, it's often
|
||||||
|
* considered a good thing to have a prime number of buckets in a hash table.
|
||||||
|
* Our total overhead on the full object size is two words header, and, for
|
||||||
|
* hashtables, one word for the pointer to the (optional) hash function, and
|
||||||
|
* one for the number of buckets, total four.
|
||||||
|
*
|
||||||
|
* | size class | words | less overhead | nearest prime | wasted |
|
||||||
|
* | ---------- | ----- | ------------- | ------------- | ------ |
|
||||||
|
* | 5 | 32 | 28 | 23 | 5 |
|
||||||
|
* | 6 | 64 | 60 | 59 | 1 |
|
||||||
|
* | 7 | 128 | 124 | 113 | 11 |
|
||||||
|
* | 8 | 256 | 252 | 251 | 1 |
|
||||||
|
* | 9 | 512 | 508 | 503 | 5 |
|
||||||
|
* | 10 | 1024 | 1020 | 1019 | 1 |
|
||||||
|
*
|
||||||
|
* So we can fit 59 buckets into a 64 word class 6 pso, wasting one word;
|
||||||
|
* 251 buckets in a 256 word class 8 again wasting one word; 1019 in a size
|
||||||
|
* class 10, also wasting only one word. In a 32 word class 5, the best prime
|
||||||
|
* we can do is 23 buckets, wasting five words.
|
||||||
*
|
*
|
||||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
|
@ -19,6 +37,8 @@
|
||||||
* \see NAMESPACETAG for mutable hashtables.
|
* \see NAMESPACETAG for mutable hashtables.
|
||||||
*/
|
*/
|
||||||
#define HASHTABLETAG "HTB"
|
#define HASHTABLETAG "HTB"
|
||||||
|
#define HASHTABLETV 4346952
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload of a hashtable. The number of buckets is assigned at run-time,
|
* The payload of a hashtable. The number of buckets is assigned at run-time,
|
||||||
* and is stored in n_buckets. Each bucket is something ASSOC can consume:
|
* and is stored in n_buckets. Each bucket is something ASSOC can consume:
|
||||||
|
|
@ -27,12 +47,7 @@
|
||||||
struct hashtable_payload {
|
struct hashtable_payload {
|
||||||
struct cons_pointer hash_fn; /* function for hashing values in this hashtable, or `NIL` to use
|
struct cons_pointer hash_fn; /* function for hashing values in this hashtable, or `NIL` to use
|
||||||
the default hashing function */
|
the default hashing function */
|
||||||
struct cons_pointer write_acl; /* it seems to me that it is likely that the
|
|
||||||
* principal difference between a hashtable and a
|
|
||||||
* namespace is that a hashtable has a write ACL
|
|
||||||
* of `NIL`, meaning not writeable by anyone */
|
|
||||||
uint32_t n_buckets; /* number of hash buckets */
|
uint32_t n_buckets; /* number of hash buckets */
|
||||||
uint32_t unused; /* for word alignment and possible later expansion */
|
|
||||||
struct cons_pointer buckets[]; /* actual hash buckets, which should be `NIL`
|
struct cons_pointer buckets[]; /* actual hash buckets, which should be `NIL`
|
||||||
* or assoc lists or (possibly) further hashtables. */
|
* or assoc lists or (possibly) further hashtables. */
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define INTEGERTAG "INT"
|
||||||
|
#define INTEGERTV 5525065
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An integer .
|
* @brief An integer .
|
||||||
*
|
*
|
||||||
|
|
@ -20,7 +23,7 @@
|
||||||
* in the Lisp layer, not the substrate.
|
* in the Lisp layer, not the substrate.
|
||||||
*/
|
*/
|
||||||
struct integer_payload {
|
struct integer_payload {
|
||||||
int128_t value;
|
__int128_t value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
* Tag for a keyword - an interned, self-evaluating string.
|
* Tag for a keyword - an interned, self-evaluating string.
|
||||||
*/
|
*/
|
||||||
#define KEYTAG "KEY"
|
#define KEYTAG "KEY"
|
||||||
|
#define KEYTV 5850443
|
||||||
|
|
||||||
/* TODO: for now, Keyword shares a payload with String, but this may change.
|
/* TODO: for now, Keyword shares a payload with String, but this may change.
|
||||||
* Strings are of indefinite length, but keywords are really not, and might
|
* Strings are of indefinite length, but keywords are really not, and might
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
* \see FUNCTIONTAG.
|
* \see FUNCTIONTAG.
|
||||||
*/
|
*/
|
||||||
#define LAMBDATAG "LMD"
|
#define LAMBDATAG "LMD"
|
||||||
|
#define LAMBDATV 4345164
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief payload for lambda and nlambda cells.
|
* @brief payload for lambda and nlambda cells.
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
* \see FUNCTIONTAG.
|
* \see FUNCTIONTAG.
|
||||||
*/
|
*/
|
||||||
#define MUTEXTAG "MTX"
|
#define MUTEXTAG "MTX"
|
||||||
|
#define MUTEXTV 5788749
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief payload for mutex objects.
|
* @brief payload for mutex objects.
|
||||||
|
|
@ -29,7 +30,7 @@
|
||||||
*/
|
*/
|
||||||
struct mutex_payload {
|
struct mutex_payload {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
}
|
};
|
||||||
|
|
||||||
struct pso_pointer make_mutex();
|
struct pso_pointer make_mutex();
|
||||||
|
|
||||||
|
|
@ -64,3 +65,5 @@ struct pso_pointer with_lock( struct pso_pointer lock, struct pso_pointer forms)
|
||||||
* @return struct pso_pointer the result.
|
* @return struct pso_pointer the result.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer attempt_with_lock( struct pso_pointer lock, struct pso_pointer forms);
|
struct pso_pointer attempt_with_lock( struct pso_pointer lock, struct pso_pointer forms);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,28 @@
|
||||||
*
|
*
|
||||||
* a Lisp namespace - a hashtable whose contents are mutable.
|
* a Lisp namespace - a hashtable whose contents are mutable.
|
||||||
*
|
*
|
||||||
* Can sensibly sit in any pso from size class 6 upwards.
|
* Can sensibly sit in any pso from size class 6 upwards. However, it's often
|
||||||
|
* considered a good thing to have a prime number of buckets in a hash table.
|
||||||
|
* Our total overhead on the full object size is two words header, and, for
|
||||||
|
* namespaces, one word for the pointer to the (optional) hash function,
|
||||||
|
* one for the number of buckets, one for the pointer to the write ACL, one
|
||||||
|
* for the pointer to the mutex, total six.
|
||||||
|
*
|
||||||
|
* There are no really good fits until you get up to class 9, which might
|
||||||
|
* make sense for some namespaces, but it's quite large!
|
||||||
|
*
|
||||||
|
* | size class | words | less overhead | nearest prime | wasted |
|
||||||
|
* | ---------- | ----- | ------------- | ------------- | ------ |
|
||||||
|
* | 5 | 32 | 26 | 23 | 3 |
|
||||||
|
* | 6 | 64 | 58 | 53 | 5 |
|
||||||
|
* | 7 | 128 | 122 | 113 | 9 |
|
||||||
|
* | 8 | 256 | 250 | 241 | 9 |
|
||||||
|
* | 9 | 512 | 506 | 503 | 3 |
|
||||||
|
* | 10 | 1024 | 1018 | 1013 | 5 |
|
||||||
|
*
|
||||||
|
* Although it may be *better* to have prime numbers of buckets, how much
|
||||||
|
* better is it? Is a bucket with 23 slots sufficiently better than one
|
||||||
|
* with 26 slots to make up for its inevitably-longer hash buckets?
|
||||||
*
|
*
|
||||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
|
@ -19,6 +40,7 @@
|
||||||
* \see HASHTABLETAG for mutable hashtables.
|
* \see HASHTABLETAG for mutable hashtables.
|
||||||
*/
|
*/
|
||||||
#define NAMESPACETAG "NSP"
|
#define NAMESPACETAG "NSP"
|
||||||
|
#define NAMESPACETV 5264206
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload of a namespace. The number of buckets is assigned at run-time,
|
* The payload of a namespace. The number of buckets is assigned at run-time,
|
||||||
|
|
@ -28,13 +50,13 @@
|
||||||
struct namespace_payload {
|
struct namespace_payload {
|
||||||
struct cons_pointer hash_fn; /* function for hashing values in this namespace, or
|
struct cons_pointer hash_fn; /* function for hashing values in this namespace, or
|
||||||
* `NIL` to use the default hashing function */
|
* `NIL` to use the default hashing function */
|
||||||
|
uint32_t n_buckets; /* number of hash buckets */
|
||||||
|
uint32_t unused; /* for word alignment and possible later expansion */
|
||||||
struct cons_pointer write_acl; /* it seems to me that it is likely that the
|
struct cons_pointer write_acl; /* it seems to me that it is likely that the
|
||||||
* principal difference between a hashtable and a
|
* principal difference between a hashtable and a
|
||||||
* namespace is that a hashtable has a write ACL
|
* namespace is that a hashtable has a write ACL
|
||||||
* of `NIL`, meaning not writeable by anyone */
|
* of `NIL`, meaning not writeable by anyone */
|
||||||
struct cons_pointer mutex; /* the mutex to lock when modifying this namespace.*/
|
struct cons_pointer mutex; /* the mutex to lock when modifying this namespace.*/
|
||||||
uint32_t n_buckets; /* number of hash buckets */
|
|
||||||
uint32_t unused; /* for word alignment and possible later expansion */
|
|
||||||
struct cons_pointer buckets[]; /* actual hash buckets, which should be `NIL`
|
struct cons_pointer buckets[]; /* actual hash buckets, which should be `NIL`
|
||||||
* or assoc lists or (possibly) further hashtables. */
|
* or assoc lists or (possibly) further hashtables. */
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@
|
||||||
/**
|
/**
|
||||||
* An ordinary nlambda cell:
|
* An ordinary nlambda cell:
|
||||||
*/
|
*/
|
||||||
#define CONSTAG "CNS"
|
#define NLAMBDATAG "NLM"
|
||||||
|
#define NLAMBDATV 5065806
|
||||||
|
|
||||||
/* nlambda shares a payload with lambda */
|
/* nlambda shares a payload with lambda */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,15 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An open read stream.
|
* An open read stream.
|
||||||
*/
|
*/
|
||||||
#define READTAG "REA"
|
#define READTAG "REA"
|
||||||
|
#define READTV 4277586
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* payload of a read or write stream cell.
|
* payload of a read or write stream cell.
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
* \see NLAMBDATAG.
|
* \see NLAMBDATAG.
|
||||||
*/
|
*/
|
||||||
#define SPECIALTAG "SFM"
|
#define SPECIALTAG "SFM"
|
||||||
|
#define SPECIALTV 5064275
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Payload of a special form cell.
|
* @brief Payload of a special form cell.
|
||||||
|
|
@ -30,14 +31,14 @@ struct special_payload {
|
||||||
* pointer to the source from which the special form was compiled, or NIL
|
* pointer to the source from which the special form was compiled, or NIL
|
||||||
* if it is a primitive.
|
* if it is a primitive.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer meta;
|
struct pso_pointer meta;
|
||||||
/** pointer to a function which takes a cons pointer (representing
|
/** pointer to a function which takes a cons pointer (representing
|
||||||
* its argument list) and a cons pointer (representing its environment) and a
|
* its argument list) and a cons pointer (representing its environment) and a
|
||||||
* stack frame (representing the previous stack frame) as arguments and returns
|
* stack frame (representing the previous stack frame) as arguments and returns
|
||||||
* a cons pointer (representing its result). */
|
* a cons pointer (representing its result). */
|
||||||
struct cons_pointer ( *executable ) ( struct stack_frame *,
|
struct pso_pointer ( *executable ) ( struct pso4 *,
|
||||||
struct cons_pointer,
|
struct pso_pointer,
|
||||||
struct cons_pointer );
|
struct pso_pointer );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* memory/stack.c
|
* payloads/stack.c
|
||||||
*
|
*
|
||||||
* The execution stack.
|
* The execution stack.
|
||||||
*
|
*
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory/stack.h"
|
#include "memory/node.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
#include "payloads/stack.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The maximum depth of stack before we throw an exception.
|
* @brief The maximum depth of stack before we throw an exception.
|
||||||
|
|
@ -19,19 +21,20 @@ uint32_t stack_limit = 0;
|
||||||
/**
|
/**
|
||||||
* Fetch a pointer to the value of the local variable at this index.
|
* Fetch a pointer to the value of the local variable at this index.
|
||||||
*/
|
*/
|
||||||
struct cons_pointer fetch_arg( struct stack_frame *frame, unsigned int index ) {
|
struct pso_pointer fetch_arg( struct pso4 *frame, unsigned int index ) {
|
||||||
struct cons_pointer result = NIL;
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
// TODO check that the frame is indeed a frame!
|
||||||
if ( index < args_in_frame ) {
|
if ( index < args_in_frame ) {
|
||||||
result = frame->arg[index];
|
result = frame->payload.stack_frame.arg[index];
|
||||||
} else {
|
} else {
|
||||||
struct cons_pointer p = frame->more;
|
struct pso_pointer p = frame->payload.stack_frame.more;
|
||||||
|
|
||||||
for ( int i = args_in_frame; i < index; i++ ) {
|
for ( int i = args_in_frame; i < index; i++ ) {
|
||||||
p = pointer2cell( p ).payload.cons.cdr;
|
p = pointer_to_object( p)->payload.cons.cdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = pointer2cell( p ).payload.cons.car;
|
result = pointer_to_object( p)->payload.cons.car;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
/**
|
/**
|
||||||
* memory/stack.h
|
* payloads/stack.h
|
||||||
*
|
*
|
||||||
* The execution stack.
|
* a Lisp stack frame.
|
||||||
|
*
|
||||||
|
* Sits in a pso4.
|
||||||
*
|
*
|
||||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __psse_payloads_stack_frame_h
|
#ifndef __psse_payloads_stack_h
|
||||||
#define __psse_payloads_stack_frame_h
|
#define __psse_payloads_stack_h
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* number of arguments stored in a stack frame
|
* number of arguments stored in a stack frame
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,9 +39,9 @@ struct stack_frame_payload {
|
||||||
/** the function to be called. */
|
/** the function to be called. */
|
||||||
struct pso_pointer function;
|
struct pso_pointer function;
|
||||||
/** the number of arguments provided. */
|
/** the number of arguments provided. */
|
||||||
int args;
|
uint32_t args;
|
||||||
/** the depth of the stack below this frame */
|
/** the depth of the stack below this frame */
|
||||||
int depth;
|
uint32_t depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
* @brief Tag for string of characters, organised as a linked list.
|
* @brief Tag for string of characters, organised as a linked list.
|
||||||
*/
|
*/
|
||||||
#define STRINGTAG "STR"
|
#define STRINGTAG "STR"
|
||||||
|
#define STRINGTV 5395539
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief payload of a string cell.
|
* @brief payload of a string cell.
|
||||||
|
|
@ -36,7 +37,7 @@ struct string_payload {
|
||||||
/** a hash of the string value, computed at store time. */
|
/** a hash of the string value, computed at store time. */
|
||||||
uint32_t hash;
|
uint32_t hash;
|
||||||
/** the remainder of the string following this character. */
|
/** the remainder of the string following this character. */
|
||||||
struct cons_pointer cdr;
|
struct pso_pointer cdr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
* Tag for a symbol: just like a keyword except not self-evaluating.
|
* Tag for a symbol: just like a keyword except not self-evaluating.
|
||||||
*/
|
*/
|
||||||
#define SYMBOLTAG "SYM"
|
#define SYMBOLTAG "SYM"
|
||||||
|
#define SYMBOLTV 5069139
|
||||||
|
|
||||||
/* TODO: for now, Symbol shares a payload with String, but this may change.
|
/* TODO: for now, Symbol shares a payload with String, but this may change.
|
||||||
* Strings are of indefinite length, but symbols are really not, and might
|
* Strings are of indefinite length, but symbols are really not, and might
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@
|
||||||
/**
|
/**
|
||||||
* @brief Tag for a time stamp.
|
* @brief Tag for a time stamp.
|
||||||
*/
|
*/
|
||||||
#define TIMETAG "TIME"
|
#define TIMETAG "TIM"
|
||||||
|
#define TIMETV 5065044
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The payload of a time cell: an unsigned 128 bit value representing micro-
|
* The payload of a time cell: an unsigned 128 bit value representing micro-
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
* @brief Tag for an open write stream.
|
* @brief Tag for an open write stream.
|
||||||
*/
|
*/
|
||||||
#define WRITETAG "WRT"
|
#define WRITETAG "WRT"
|
||||||
|
#define WRITETV 5264214
|
||||||
|
|
||||||
/* write stream shares a payload with /see read_streem.h */
|
/* write stream shares a payload with /see read_streem.h */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define TAGLENGTH 4
|
#define TAGLENGTH 3
|
||||||
|
|
||||||
struct dummy {
|
struct dummy {
|
||||||
union {
|
union {
|
||||||
|
|
@ -21,6 +21,6 @@ int main( int argc, char *argv[] ) {
|
||||||
|
|
||||||
strncpy( &buffer.tag.bytes[0], argv[i], TAGLENGTH );
|
strncpy( &buffer.tag.bytes[0], argv[i], TAGLENGTH );
|
||||||
|
|
||||||
printf( "%4.4s:\t%d\n", argv[i], buffer.tag.value);
|
printf( "%4.4s:\t%d\n", argv[i], buffer.tag.value & 0xffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue