Added work on making namespaces threadsafe.
This commit is contained in:
parent
154cda8da3
commit
1afb1b9fad
38 changed files with 1074 additions and 517 deletions
118
src/c/debug.c
118
src/c/debug.c
|
|
@ -10,7 +10,119 @@
|
|||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "debug.h"
|
||||
|
||||
int verbosity = 0;
|
||||
|
||||
int verbosity = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief print this debug `message` to stderr, if `verbosity` matches `level`.
|
||||
*
|
||||
* `verbosity` is a set of flags, see debug_print.h; so you can
|
||||
* turn debugging on for only one part of the system.
|
||||
*
|
||||
* NOTE THAT: contrary to behaviour in the 0.0.X prototypes, a line feed is
|
||||
* always printed before a debug_print message. Hopefully this will result
|
||||
* in clearer formatting.
|
||||
*
|
||||
* @param message The message to be printed, in *wide* (32 bit) characters.
|
||||
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
||||
* `level` is non-zero, print this `message`, else don't.
|
||||
* @param indent print `indent` spaces before the message.
|
||||
*/
|
||||
void debug_print( wchar_t *message, int level, int indent ) {
|
||||
#ifdef DEBUG
|
||||
if ( level & verbosity ) {
|
||||
fwide( stderr, 1 );
|
||||
fputws( L"\n", stderr );
|
||||
for ( int i = 0; i < indent; i++ ) {
|
||||
fputws( L" ", stderr );
|
||||
}
|
||||
fputws( message, stderr );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief print a 128 bit integer value to stderr, if `verbosity` matches `level`.
|
||||
*
|
||||
* `verbosity` is a set of flags, see debug_print.h; so you can
|
||||
* turn debugging on for only one part of the system.
|
||||
*
|
||||
* stolen from https://stackoverflow.com/questions/11656241/how-to-print-uint128-t-number-using-gcc
|
||||
*
|
||||
* @param n the large integer to print.
|
||||
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
||||
* `level` is non-zero, print this `message`, else don't.
|
||||
*/
|
||||
void debug_print_128bit( __int128_t n, int level ) {
|
||||
#ifdef DEBUG
|
||||
if ( level & verbosity ) {
|
||||
if ( n == 0 ) {
|
||||
fwprintf( stderr, L"0" );
|
||||
} else {
|
||||
char str[40] = { 0 }; // log10(1 << 128) + '\0'
|
||||
char *s = str + sizeof( str ) - 1; // start at the end
|
||||
while ( n != 0 ) {
|
||||
if ( s == str )
|
||||
return; // never happens
|
||||
|
||||
*--s = "0123456789"[n % 10]; // save last digit
|
||||
n /= 10; // drop it
|
||||
}
|
||||
fwprintf( stderr, L"%s", s );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief print a line feed to stderr, if `verbosity` matches `level`.
|
||||
*
|
||||
* `verbosity` is a set of flags, see debug_print.h; so you can
|
||||
* turn debugging on for only one part of the system.
|
||||
*
|
||||
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
||||
* `level` is non-zero, print this `message`, else don't.
|
||||
*/
|
||||
void debug_println( int level ) {
|
||||
#ifdef DEBUG
|
||||
if ( level & verbosity ) {
|
||||
fwide( stderr, 1 );
|
||||
fputws( L"\n", stderr );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief `wprintf` adapted for the debug logging system.
|
||||
*
|
||||
* Print to stderr only if `verbosity` matches `level`. All other arguments
|
||||
* as for `wprintf`.
|
||||
*
|
||||
* @param level a mask for `verbosity`. If a bitwise and of `verbosity` and
|
||||
* `level` is non-zero, print this `message`, else don't.
|
||||
* @param indent print `indent` spaces before the message.
|
||||
* @param format Format string in *wide characters*, but otherwise as used by
|
||||
* `printf` and friends.
|
||||
*
|
||||
* Remaining arguments should match the slots in the format string.
|
||||
*/
|
||||
void debug_printf( int level, int indent, wchar_t *format, ... ) {
|
||||
#ifdef DEBUG
|
||||
if ( level & verbosity ) {
|
||||
fwide( stderr, 1 );
|
||||
fputws( L"\n", stderr );
|
||||
for ( int i = 0; i < indent; i++ ) {
|
||||
fputws( L" ", stderr );
|
||||
}
|
||||
va_list( args );
|
||||
va_start( args, format );
|
||||
vfwprintf( stderr, format, args );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// debug_dump_object, debug_print_binding, debug_print_exception, debug_print_object,
|
||||
// not yet implemented but probably will be.
|
||||
|
|
@ -93,4 +93,12 @@
|
|||
*/
|
||||
extern int verbosity;
|
||||
|
||||
void debug_print( wchar_t *message, int level, int indent );
|
||||
|
||||
void debug_print_128bit( __int128_t n, int level );
|
||||
|
||||
void debug_println( int level );
|
||||
|
||||
void debug_printf( int level, int indent, wchar_t *format, ... );
|
||||
|
||||
#endif
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#ifndef __psse_memory_header_h
|
||||
#define __psse_memory_header_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <bits/stdint-uintn.h>
|
||||
|
||||
#define TAGLENGTH 3
|
||||
|
||||
|
|
@ -25,8 +25,8 @@ struct pso_header {
|
|||
struct {
|
||||
/** mnemonic for this type; */
|
||||
char mnemonic[TAGLENGTH];
|
||||
/** sizetag for this object */
|
||||
uint8_t sizetag;
|
||||
/** size class for this object */
|
||||
uint8_t size_class;
|
||||
} tag;
|
||||
/** the tag considered as a number */
|
||||
uint32_t value;
|
||||
|
|
|
|||
|
|
@ -9,11 +9,19 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "memory/pointer.h"
|
||||
/**
|
||||
* @brief Freelists for each size class.
|
||||
*
|
||||
* TODO: I don't know if that +1 is needed, my mind gets confused by arrays
|
||||
* indexed from zero. But it does little harm.
|
||||
*/
|
||||
struct pso_pointer freelists[MAX_SIZE_CLASS + 1];
|
||||
|
||||
|
||||
int initialise_memory( int node ) {
|
||||
fprintf( stderr, "TODO: Implement initialise_memory()" );
|
||||
|
||||
int initialise_memory( int node) {
|
||||
fprintf( stderr, "TODO: Implement initialise_memory()");
|
||||
|
||||
}
|
||||
for (uint8_t i = 0; i <= MAX_SIZE_CLASS; i++) {
|
||||
freelists[i] = nil;S
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,19 @@
|
|||
#ifndef __psse_memory_memory_h
|
||||
#define __psse_memory_memory_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
/**
|
||||
* @brief Maximum size class
|
||||
*
|
||||
* Size classes are poweres of 2, in words; so an object of size class 2
|
||||
* has an allocation size of four words; of size class 3, of eight words,
|
||||
* and so on. Size classes of 0 and 1 do not work for managed objects,
|
||||
* since managed objects require a two word header; it's unlikely that
|
||||
* these undersized size classes will be used at all.
|
||||
*/
|
||||
#define MAX_SIZE_CLASS = 0xf
|
||||
|
||||
int initialise_memory();
|
||||
int initialise_memory( );
|
||||
|
||||
extern struct pso_pointer out_of_memory_exception;
|
||||
|
||||
extern struct pso_pointer freelists[];
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@
|
|||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include "memory/memory.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "node.h"
|
||||
|
||||
#include <bits/stdint-uintn.h>
|
||||
|
||||
#include "ops/equal.h"
|
||||
#include "memory.h"
|
||||
#include "pointer.h"
|
||||
|
||||
/**
|
||||
* @brief Flag to prevent the node being initialised more than once.
|
||||
|
|
@ -20,6 +25,9 @@ bool node_initialised = false;
|
|||
/**
|
||||
* @brief The index of this node in the hypercube.
|
||||
*
|
||||
* TODO: once we have a hypercube, this must be set to the correct value
|
||||
* IMMEDIATELY on startup, before starting to initalise any other part of
|
||||
* the Lisp system.
|
||||
*/
|
||||
uint32_t node_index = 0;
|
||||
|
||||
|
|
@ -27,28 +35,29 @@ uint32_t node_index = 0;
|
|||
* @brief The canonical `nil` pointer
|
||||
*
|
||||
*/
|
||||
struct pso_pointer nil = struct pso_pointer{ 0, 0, 0};
|
||||
struct pso_pointer nil = struct pso_pointer { 0, 0, 0 };
|
||||
|
||||
/**
|
||||
* @brief the canonical `t` (true) pointer.
|
||||
*
|
||||
*/
|
||||
struct pso_pointer t = struct pso_pointer{ 0, 0, 1};
|
||||
struct pso_pointer t = struct pso_pointer { 0, 0, 1 };
|
||||
|
||||
/**
|
||||
* @brief Set up the basic informetion about this node
|
||||
* @brief Set up the basic informetion about this node.
|
||||
*
|
||||
* @param index
|
||||
* @return struct pso_pointer
|
||||
*/
|
||||
struct pso_pointer initialise_node( uint32_t index) {
|
||||
struct pso_pointer initialise_node( uint32_t index ) {
|
||||
node_index = index;
|
||||
nil = pso_pointer{ index, 0, 0};
|
||||
t = pso_pointer( index, 0, 1);
|
||||
pso_pointer result = initialise_memory(index);
|
||||
nil = pso_pointer { index, 0, 0};
|
||||
t = pso_pointer( index, 0, 1 );
|
||||
|
||||
if ( eq( result, t)) {
|
||||
result = initialise_environment();
|
||||
pso_pointer result = initialise_memory( index );
|
||||
|
||||
if ( eq( result, t ) ) {
|
||||
result = initialise_environment( index );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@
|
|||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/memory.h"
|
||||
#include "memory/node.h"
|
||||
#include "memory/page.h"
|
||||
#include "memory/pso2.h"
|
||||
#include "memory/pso3.h"
|
||||
|
|
@ -24,13 +27,104 @@
|
|||
#include "memory/psod.h"
|
||||
#include "memory/psoe.h"
|
||||
#include "memory/psof.h"
|
||||
#include "payloads/free.h"
|
||||
|
||||
void * malloc_page( uint8_t size_class) {
|
||||
void * result = malloc( sizeof( page));
|
||||
/**
|
||||
* @brief The pages which have so far been initialised.
|
||||
*
|
||||
* TODO: This is temporary. We cannot afford to allocate an array big enough
|
||||
* to hold the number of pages we *might* create at start up time. We need a
|
||||
* way to grow the number of pages, while keeping access to them cheap.
|
||||
*/
|
||||
struct page * pages[NPAGES];
|
||||
|
||||
if (result != NULL) {
|
||||
/**
|
||||
* @brief the number of pages which have thus far been allocated.
|
||||
*
|
||||
*/
|
||||
uint32_t npages_allocated = 0
|
||||
|
||||
struct cons_pointer initialise_page( struct page * result, uint16_t page_index, uint8_t size_class, pso_pointer freelist) {
|
||||
struct cons_pointer result = freelist;
|
||||
int obj_size = pow(2, size_class);
|
||||
int obj_bytes = obj_size * sizeof(uint64_t);
|
||||
int objs_in_page = PAGE_BYTES/obj_bytes;
|
||||
|
||||
for (int i = objs_in_page - 1; i >= 0; i--) {
|
||||
// it should be safe to cast any pso object to a pso2
|
||||
struct pso2* object = (pso2 *)(result + (i * obj_bytes));
|
||||
|
||||
object->header.tag.size_class = size_class;
|
||||
strncpy( (char *)(object->header.tag.mnemonic), FREETAG, TAGLENGTH);
|
||||
object->payload.free.next = result;
|
||||
|
||||
result = make_pointer( node_index, page_index, (uint16_t)( i * obj_size));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate a page for objects of this size class, initialise it, and
|
||||
* link the objects in it into the freelist for this size class.
|
||||
*
|
||||
* Because we can't return an exception at this low level, and because there
|
||||
* are multiple possible causes of failure, for the present this function will
|
||||
* print errors to stderr. We cast the error stream to wide, since we've
|
||||
* probably (but not certainly) already cast it to wide, and we can't reliably
|
||||
* cast it back.
|
||||
*
|
||||
* @param size_class an integer in the range 0...MAX_SIZE_CLASS.
|
||||
* @return a pointer to the page, or NULL if an error occurred.
|
||||
*/
|
||||
void *allocate_page( uint8_t size_class ) {
|
||||
void *result = NULL;
|
||||
|
||||
if ( npages_allocated == 0) {
|
||||
for (int i = 0; i < NPAGES; i++) {
|
||||
pages[i] = NULL;
|
||||
}
|
||||
debug_print( L"Pages array zeroed.\n", DEBUG_ALLOC, 0);
|
||||
}
|
||||
|
||||
if ( npages_allocated < NPAGES) {
|
||||
if ( size_class >= 2 && size_class <= MAX_SIZE_CLASS ) {
|
||||
result = malloc( sizeof( page ) );
|
||||
|
||||
if ( result != NULL ) {
|
||||
memset( result, 0, sizeof( page ) );
|
||||
pages[ npages_allocated] = result;
|
||||
debug_printf( DEBUG_ALLOC, 0,
|
||||
L"Allocated page %d for objects of size class %x.\n",
|
||||
npages_allocated, size_class);
|
||||
|
||||
freelists[size_class] =
|
||||
initialise_page( result, npages_allocated, size_class, freelists[size_class] );
|
||||
|
||||
debug_printf( DEBUG_ALLOC, 0,
|
||||
L"Initialised page %d; freelist for size class %x updated.\n",
|
||||
npages_allocated,
|
||||
size_class);
|
||||
|
||||
npages_allocated ++;
|
||||
} else {
|
||||
fwide( stderr, 1 );
|
||||
fwprintf( stderr,
|
||||
L"\nCannot allocate page: heap exhausted,\n",
|
||||
size_class, MAX_SIZE_CLASS );
|
||||
}
|
||||
} else {
|
||||
fwide( stderr, 1 );
|
||||
fwprintf( stderr,
|
||||
L"\nCannot allocate page for size class %x, min is 2 max is %x.\n",
|
||||
size_class, MAX_SIZE_CLASS );
|
||||
}
|
||||
} else {
|
||||
fwide( stderr, 1 );
|
||||
fwprintf( stderr,
|
||||
L"\nCannot allocate page: page space exhausted.\n",
|
||||
size_class, MAX_SIZE_CLASS );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,20 @@
|
|||
#include "memory/psoe.h"
|
||||
#include "memory/psof.h"
|
||||
|
||||
#define PAGE_SIZE 1048576
|
||||
/**
|
||||
* the size of a page, **in bytes**.
|
||||
*/
|
||||
#define PAGE_BYTES 1048576
|
||||
|
||||
/**
|
||||
* the number of pages we will initially allow for. For
|
||||
* convenience we'll set up an array of cons pages this big; however,
|
||||
* TODO: later we will want a mechanism for this to be able to grow
|
||||
* dynamically to the maximum we can allow.
|
||||
*/
|
||||
#define NPAGES 64
|
||||
|
||||
extern struct page *pages[NPAGES];
|
||||
|
||||
/**
|
||||
* @brief A page is a megabyte of memory which contains objects all of which
|
||||
|
|
@ -40,22 +53,22 @@
|
|||
* collection they will be returned to that freelist.
|
||||
*/
|
||||
union page {
|
||||
uint8_t[PAGE_SIZE] bytes;
|
||||
uint64_t[PAGE_SIZE / 8] words;
|
||||
struct pso2[PAGE_SIZE / 32] pso2s;
|
||||
struct pso3[PAGE_SIZE / 64] pso3s;
|
||||
struct pso4[PAGE_SIZE / 128] pso4s;
|
||||
struct pso5[PAGE_SIZE / 256] pso5s;
|
||||
struct pso6[PAGE_SIZE / 512] pso6s;
|
||||
struct pso7[PAGE_SIZE / 1024] pso7s;
|
||||
struct pso8[PAGE_SIZE / 2048] pso8s;
|
||||
struct pso9[PAGE_SIZE / 4096] pso9s;
|
||||
struct psoa[PAGE_SIZE / 8192] psoas;
|
||||
struct psob[PAGE_SIZE / 16384] psobs;
|
||||
struct psoc[PAGE_SIZE / 32768] psocs;
|
||||
struct psod[PAGE_SIZE / 65536] psods;
|
||||
struct psoe[PAGE_SIZE / 131072] psoes;
|
||||
struct psof[PAGE_SIZE / 262144] psofs;
|
||||
uint8_t[PAGE_BYTES] bytes;
|
||||
uint64_t[PAGE_BYTES / 8] words;
|
||||
struct pso2[PAGE_BYTES / 32] pso2s;
|
||||
struct pso3[PAGE_BYTES / 64] pso3s;
|
||||
struct pso4[PAGE_BYTES / 128] pso4s;
|
||||
struct pso5[PAGE_BYTES / 256] pso5s;
|
||||
struct pso6[PAGE_BYTES / 512] pso6s;
|
||||
struct pso7[PAGE_BYTES / 1024] pso7s;
|
||||
struct pso8[PAGE_BYTES / 2048] pso8s;
|
||||
struct pso9[PAGE_BYTES / 4096] pso9s;
|
||||
struct psoa[PAGE_BYTES / 8192] psoas;
|
||||
struct psob[PAGE_BYTES / 16384] psobs;
|
||||
struct psoc[PAGE_BYTES / 32768] psocs;
|
||||
struct psod[PAGE_BYTES / 65536] psods;
|
||||
struct psoe[PAGE_BYTES / 131072] psoes;
|
||||
struct psof[PAGE_BYTES / 262144] psofs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
47
src/c/memory/pointer.c
Normal file
47
src/c/memory/pointer.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* memory/pointer.h
|
||||
*
|
||||
* A pointer to a paged space object.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso.h"
|
||||
|
||||
/**
|
||||
* @brief Make a pointer to a paged-space object.
|
||||
*
|
||||
* @param node The index of the node on which the object is curated;
|
||||
* @param page The memory page in which the object resides;
|
||||
* @param offset The offset, in words, within that page, of the object.
|
||||
* @return struct pso_pointer a pointer referencing the specified object.
|
||||
*/
|
||||
struct pso_pointer make_pointer( uint32_t node, uint16_t page, uint16_t offset) {
|
||||
return struct pso_pointer{ node, page, pointer};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the in-memory address of the object indicated by this
|
||||
* pointer. TODO: Yhe reason I'm doing it this way is because I'm not
|
||||
* certain reference counter updates work right it we work with 'the object'
|
||||
* rather than 'the address of the object'. I really ought to have a
|
||||
* conversation with someone who understands this bloody language.
|
||||
*
|
||||
* @param pointer a pso_pointer which references an object.
|
||||
* @return struct pso2* the actual address in memory of that object.
|
||||
*/
|
||||
struct pso2* pointer_to_object( struct pso_pointer pointer) {
|
||||
struct pso2* result = NULL;
|
||||
|
||||
if ( pointer.node == node_index) {
|
||||
result = (struct pso2*) &(pages[pointer.node] + (pointer.offset * sizeof( uint64_t)));
|
||||
}
|
||||
// TODO: else if we have a copy of the object in cache, return that;
|
||||
// else request a copy of the object from the node which curates it.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -38,4 +38,6 @@ struct pso_pointer {
|
|||
uint16_t offset;
|
||||
};
|
||||
|
||||
struct pso_pointer make_pointer( uint32_t node, uint16_t page, uint16_t offset);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
47
src/c/memory/pso.c
Normal file
47
src/c/memory/pso.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* memory/pso.c
|
||||
*
|
||||
* Paged space objects.
|
||||
*
|
||||
* Broadly, it should be save to cast any paged space object to a pso2, since
|
||||
* that is the smallest actually used size class. This should work to extract
|
||||
* the tag and size class fields from the header, for example. I'm not
|
||||
* confident enough of my understanding of C to know whether it is similarly
|
||||
* safe to cast something passed to you as a pso2 up to something larger, even
|
||||
* if you know from the size class field that it actually is something larger.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
struct cons_pointer allocate( char* tag, uint8_t size_class) {
|
||||
struct cons_pointer result = nil;
|
||||
|
||||
if (size_class <= MAX_SIZE_CLASS) {
|
||||
if ( not( freelists[size_class] ) ) {
|
||||
result = freelists[size_class];
|
||||
struct pso2* object = pointer_to_object( result);
|
||||
freelists[size_class] = object->payload.free.next;
|
||||
|
||||
strncpy( (char *)(object->header.tag.mnemonic), tag, TAGLENGTH);
|
||||
|
||||
/* the object ought already to have the right size class in its tag
|
||||
* because it was popped off the freelist for that size class. */
|
||||
if ( object->header.tag.size_class != size_class) {
|
||||
// TODO: return an exception instead? Or warn, set it, and continue?
|
||||
}
|
||||
/* the objext ought to have a reference count ot zero, because it's
|
||||
* on the freelist, but again we should sanity check. */
|
||||
if ( object->header.count != 0) {
|
||||
// TODO: return an exception instead? Or warn, set it, and continue?
|
||||
}
|
||||
|
||||
}
|
||||
} // TODO: else throw exception
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct cons_pointer get_tag_value( struct cons_pointer pointer) {
|
||||
result =
|
||||
}
|
||||
240
src/c/memory/pso.h
Normal file
240
src/c/memory/pso.h
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* memory/pso.h
|
||||
*
|
||||
* Paged space objects.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso_h
|
||||
#define __psse_memory_pso_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
#include "payloads/cons.h"
|
||||
#include "payloads/free.h"
|
||||
#include "payloads/function.h"
|
||||
#include "payloads/integer.h"
|
||||
#include "payloads/ketwod.h"
|
||||
#include "payloads/lambda.h"
|
||||
#include "payloads/mutex.h"
|
||||
#include "payloads/nlambda.h"
|
||||
#include "payloads/read_stream.h"
|
||||
#include "payloads/special.h"
|
||||
#include "payloads/stack.h"
|
||||
#include "payloads/string.h"
|
||||
#include "payloads/symbol.h"
|
||||
#include "payloads/time.h"
|
||||
#include "payloads/vector_pointer.h"
|
||||
#include "payloads/write_stream.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 2, four words total, two words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso2 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[16] bytes;
|
||||
uint64_t[2] words;
|
||||
struct cons_payload cons;
|
||||
struct free_payload free;
|
||||
struct function_payload function;
|
||||
struct integer_payload integer;
|
||||
struct lambda_payload lambda;
|
||||
struct special_payload special;
|
||||
struct stream_payload stream;
|
||||
struct time_payload time;
|
||||
struct vectorp_payload vectorp;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 3, 8 words total, 6 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso3 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[48] bytes;
|
||||
uint64_t[6] words;
|
||||
struct exception_payload exception;
|
||||
struct free_payload free;
|
||||
struct mutex_payload mutex;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 4, 16 words total, 14 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso4 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[112] bytes;
|
||||
uint64_t[14] words;
|
||||
struct free_payload free;
|
||||
struct stack_frame_payload stack_frame;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 5, 32 words total, 30 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso5 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[240] bytes;
|
||||
uint64_t[30] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 6, 64 words total, 62 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso6 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[496] bytes;
|
||||
uint64_t[62] words;
|
||||
struct free_payload free;
|
||||
struct hashtable_payload hashtable;
|
||||
struct namespace_payload namespace;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 7, 128 words total, 126 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso7 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[1008] bytes;
|
||||
uint64_t[126] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 8, 256 words total, 254 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso8 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[2032] bytes;
|
||||
uint64_t[254] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 9, 512 words total, 510 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso9 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[4080] bytes;
|
||||
uint64_t[510] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class a, 1024 words total, 1022 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoa {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[8176] bytes;
|
||||
uint64_t[1022] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class b, 2048 words total, 2046 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psob {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[16368] bytes;
|
||||
uint64_t[2046] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class c, 4096 words total, 4094 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoc {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[32752] bytes;
|
||||
uint64_t[4094] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class d, 8192 words total, 8190 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psod {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[65520] bytes;
|
||||
uint64_t[8190] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class e, 16384 words total, 16382 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoe {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[131056] bytes;
|
||||
uint64_t[16382] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class f, 32768 words total, 32766 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psof {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[262128] bytes;
|
||||
uint64_t[32766] words;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* memory/pso2.h
|
||||
*
|
||||
* Paged space object of size class 2, four words total, two words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso2_h
|
||||
#define __psse_memory_pso2_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
#include "payloads/cons.h"
|
||||
#include "payloads/free.h"
|
||||
#include "payloads/function.h"
|
||||
#include "payloads/integer.h"
|
||||
#include "payloads/ketwod.h"
|
||||
#include "payloads/lambda.h"
|
||||
#include "payloads/nlambda.h"
|
||||
#include "payloads/read_stream.h"
|
||||
#include "payloads/special.h"
|
||||
#include "payloads/string.h"
|
||||
#include "payloads/symbol.h"
|
||||
#include "payloads/time.h"
|
||||
#include "payloads/vector_pointer.h"
|
||||
#include "payloads/write_stream.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 2, four words total, two words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso2 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[16] bytes;
|
||||
uint64_t[2] words;
|
||||
struct cons_payload cons;
|
||||
struct free_payload free;
|
||||
struct function_payload function;
|
||||
struct integer_payload integer;
|
||||
struct lambda_payload lambda;
|
||||
struct special_payload special;
|
||||
struct stream_payload stream;
|
||||
struct time_payload time;
|
||||
struct vectorp_payload vectorp;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/**
|
||||
* memory/pso3.h
|
||||
*
|
||||
* Paged space object of size class 3, 8 words total, 6 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso3_h
|
||||
#define __psse_memory_pso3_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
#include "payloads/exception.h"
|
||||
#include "payloads/free.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 3, 8 words total, 6 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso3 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[48] bytes;
|
||||
uint64_t[6] words;
|
||||
struct exception_payload exception;
|
||||
struct free_payload free;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/**
|
||||
* memory/pso4.h
|
||||
*
|
||||
* Paged space object of size class 4, 16 words total, 14 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso4_h
|
||||
#define __psse_memory_pso4_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
#include "memory/stack.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 4, 16 words total, 14 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso4 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[112] bytes;
|
||||
uint64_t[14] words;
|
||||
struct stack_frame_payload stack_frame;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/pso5.h
|
||||
*
|
||||
* Paged space object of size class 5, 32 words total, 30 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso5_h
|
||||
#define __psse_memory_pso5_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 5, 32 words total, 30 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso5 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[240] bytes;
|
||||
uint64_t[30] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/pso6.h
|
||||
*
|
||||
* Paged space object of size class 6, 64 words total, 62 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso6_h
|
||||
#define __psse_memory_pso6_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 6, 64 words total, 62 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso6 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[496] bytes;
|
||||
uint64_t[62] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/pso7.h
|
||||
*
|
||||
* Paged space object of size class 7, 128 words total, 126 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso7_h
|
||||
#define __psse_memory_pso7_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 7, 128 words total, 126 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso7 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[1008] bytes;
|
||||
uint64_t[126] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/pso8.h
|
||||
*
|
||||
* Paged space object of size class 8, 256 words total, 254 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso8_h
|
||||
#define __psse_memory_pso8_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 8, 256 words total, 254 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso8 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[2032] bytes;
|
||||
uint64_t[254] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/pso9.h
|
||||
*
|
||||
* Paged space object of size class 9, 512 words total, 510 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_pso9_h
|
||||
#define __psse_memory_pso9_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class 9, 512 words total, 510 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct pso9 {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[4080] bytes;
|
||||
uint64_t[510] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psoa.h
|
||||
*
|
||||
* Paged space object of size class a, 1024 words total, 1022 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psoa_h
|
||||
#define __psse_memory_psoa_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class a, 1024 words total, 1022 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoa {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[8176] bytes;
|
||||
uint64_t[1022] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psob.h
|
||||
*
|
||||
* Paged space object of size class b, 2048 words total, 2046 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psob_h
|
||||
#define __psse_memory_psob_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class b, 2048 words total, 2046 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psob {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[16368] bytes;
|
||||
uint64_t[2046] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psoc.h
|
||||
*
|
||||
* Paged space object of size class c, 4096 words total, 4094 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psoc_h
|
||||
#define __psse_memory_psoc_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class c, 4096 words total, 4094 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoc {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[32752] bytes;
|
||||
uint64_t[4094] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psod.h
|
||||
*
|
||||
* Paged space object of size class d, 8192 words total, 8190 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psod_h
|
||||
#define __psse_memory_psod_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class d, 8192 words total, 8190 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psod {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[65520] bytes;
|
||||
uint64_t[8190] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psoe.h
|
||||
*
|
||||
* Paged space object of size class e, 16384 words total, 16382 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psoe_h
|
||||
#define __psse_memory_psoe_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class e, 16384 words total, 16382 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psoe {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[131056] bytes;
|
||||
uint64_t[16382] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* memory/psof.h
|
||||
*
|
||||
* Paged space object of size class f, 32768 words total, 32766 words payload.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_memory_psof_h
|
||||
#define __psse_memory_psof_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "memory/header.h"
|
||||
|
||||
/**
|
||||
* @brief A paged space object of size class f, 32768 words total, 32766 words
|
||||
* payload.
|
||||
*
|
||||
*/
|
||||
struct psof {
|
||||
struct pso_header header;
|
||||
union {
|
||||
char[262128] bytes;
|
||||
uint64_t[32766] words;
|
||||
} payload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
* @param b another pointer;
|
||||
* @return `true` if they are the same, else `false`
|
||||
*/
|
||||
bool eq( struct pso_pointer a, struct pso_pointer b) {
|
||||
return ( a.node == b.node && a.page == b.page && a.offset == b.offset);
|
||||
bool eq( struct pso_pointer a, struct pso_pointer b ) {
|
||||
return ( a.node == b.node && a.page == b.page && a.offset == b.offset );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -42,8 +42,8 @@ bool eq( struct pso_pointer a, struct pso_pointer b) {
|
|||
* @return `t` if all args are pointers to the same object, else `nil`;
|
||||
*/
|
||||
struct pso_pointer lisp_eq( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = t;
|
||||
|
||||
if ( frame->args > 1 ) {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
#ifndef __psse_ops_eq_h
|
||||
#define __psse_ops_eq_h
|
||||
|
||||
bool eq( struct pso_pointer a, struct pso_pointer b);
|
||||
bool eq( struct pso_pointer a, struct pso_pointer b );
|
||||
|
||||
struct pso_pointer lisp_eq( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env );
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env );
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,8 +26,9 @@
|
|||
* @param env the evaluation environment.
|
||||
* @return struct pso_pointer
|
||||
*/
|
||||
struct pso_pointer eval_despatch( struct stack_frame *frame, struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer eval_despatch( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = frame->arg[0];
|
||||
|
||||
// switch ( get_tag_value( result)) {
|
||||
|
|
@ -52,14 +53,15 @@ struct pso_pointer eval_despatch( struct stack_frame *frame, struct pso_pointer
|
|||
return result;
|
||||
}
|
||||
|
||||
struct pso_pointer lisp_eval( struct stack_frame *frame, struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = eval_despatch( frame, frame_pointer, env);
|
||||
struct pso_pointer lisp_eval( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = eval_despatch( frame, frame_pointer, env );
|
||||
|
||||
if (exceptionp( result)) {
|
||||
if ( exceptionp( result ) ) {
|
||||
// todo: if result doesn't have a stack frame, create a new exception wrapping
|
||||
// result with this stack frame.
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
94
src/c/ops/truth.c
Normal file
94
src/c/ops/truth.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* ops/truth.c
|
||||
*
|
||||
* Post Scarcity Software Environment: nil? true? not.
|
||||
*
|
||||
* Functions associated with truthiness.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief true if `p` points to `nil`, else false.
|
||||
*
|
||||
* Note that every node has its own copy of `t` and `nil`, and each instance of
|
||||
* each is considered equivalent. So we don't check the node when considering
|
||||
* whether `nil` really is `nil`, or `t` really is `t`.
|
||||
*
|
||||
* @param p a pointer
|
||||
* @return true if `p` points to `nil`.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool nilp( struct pso_pointer p) {
|
||||
return (p.page == 0 && p.offset = 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return `true` if `p` points to `nil`, else `false`.
|
||||
*
|
||||
* @param p a pointer
|
||||
* @return true if `p` points to `nil`;
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool not( struct pso_pointer p) {
|
||||
return !nilp( p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief `true` if `p` points to `t`, else `false`.
|
||||
*
|
||||
* Note that every node has its own copy of `t` and `nil`, and each instance of
|
||||
* each is considered equivalent. So we don't check the node when considering
|
||||
* whether `nil` really is `nil`, or `t` really is `t`.
|
||||
*
|
||||
* @param p a pointer
|
||||
* @return true if `p` points to `t`.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool truep( struct pso_pointer p) {
|
||||
return (p.page == 0 && p.offset = 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return `t` if the first argument in this frame is `nil`, else `t`.
|
||||
*
|
||||
* @param frame The current stack frame;
|
||||
* @param frame_pointer A pointer to the current stack frame;
|
||||
* @param env the evaluation environment.
|
||||
* @return `t` if the first argument in this frame is `nil`, else `t`
|
||||
*/
|
||||
pso_pointer lisp_nilp( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ){
|
||||
return (nilp(frame->arg[0]) ? t : nil);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return `t` if the first argument in this frame is `t`, else `nil`.
|
||||
*
|
||||
* @param frame The current stack frame;
|
||||
* @param frame_pointer A pointer to the current stack frame;
|
||||
* @param env the evaluation environment.
|
||||
* @return `t` if the first argument in this frame is `t`, else `nil`.
|
||||
*/
|
||||
pso_pointer lisp_truep( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ){
|
||||
return (truep(frame->arg[0]) ? t : nil);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return `t` if the first argument in this frame is not `nil`, else
|
||||
* `t`.
|
||||
*
|
||||
* @param frame The current stack frame;
|
||||
* @param frame_pointer A pointer to the current stack frame;
|
||||
* @param env the evaluation environment.
|
||||
* @return `t` if the first argument in this frame is not `nil`, else `t`.
|
||||
*/
|
||||
pso_pointer lisp_not( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ){
|
||||
return (not(frame->arg[0]) ? t : nil);
|
||||
}
|
||||
33
src/c/ops/truth.h
Normal file
33
src/c/ops/truth.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* ops/truth.h
|
||||
*
|
||||
* Post Scarcity Software Environment: truth functions.
|
||||
*
|
||||
* Tests for truth.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_ops_truth_h
|
||||
#define __psse_ops_truth_h
|
||||
|
||||
bool nilp( struct pso_pointer a, struct pso_pointer b );
|
||||
|
||||
struct pso_pointer lisp_nilp( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env );
|
||||
|
||||
bool not( struct pso_pointer a, struct pso_pointer b );
|
||||
|
||||
struct pso_pointer lisp_not( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env );
|
||||
|
||||
bool truep( struct pso_pointer a, struct pso_pointer b );
|
||||
|
||||
struct pso_pointer lisp_truep( struct stack_frame *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env );
|
||||
|
||||
#endif
|
||||
40
src/c/payloads/hashtable.h
Normal file
40
src/c/payloads/hashtable.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* payloads/hashtable.h
|
||||
*
|
||||
* an ordinary Lisp hashtable - one whose contents are immutable.
|
||||
*
|
||||
* Can sensibly sit in any pso from size class 6 upwards.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_payloads_hashtable_h
|
||||
#define __psse_payloads_hashtable_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
|
||||
/**
|
||||
* @brief Tag for an ordinary Lisp hashtable - one whose contents are immutable.
|
||||
* \see NAMESPACETAG for mutable hashtables.
|
||||
*/
|
||||
#define HASHTABLETAG "HTB"
|
||||
/**
|
||||
* 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:
|
||||
* i.e. either an assoc list or a further hashtable.
|
||||
*/
|
||||
struct hashtable_payload {
|
||||
struct cons_pointer hash_fn; /* function for hashing values in this hashtable, or `NIL` to use
|
||||
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 unused; /* for word alignment and possible later expansion */
|
||||
struct cons_pointer buckets[]; /* actual hash buckets, which should be `NIL`
|
||||
* or assoc lists or (possibly) further hashtables. */
|
||||
};
|
||||
|
||||
#endif
|
||||
66
src/c/payloads/mutex.h
Normal file
66
src/c/payloads/mutex.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* payloads/mutex.h
|
||||
*
|
||||
* A mutex (mutual exclusion lock) cell. Requires a size class 3 object.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_payloads_mutex_h
|
||||
#define __psse_payloads_mutex_h
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "memory/pointer.h"
|
||||
|
||||
/**
|
||||
* @brief Tag for mutex cell. mutexes are thread-safe locks, required by
|
||||
* mutable objects.
|
||||
* \see FUNCTIONTAG.
|
||||
*/
|
||||
#define MUTEXTAG "MTX"
|
||||
|
||||
/**
|
||||
* @brief payload for mutex objects.
|
||||
*
|
||||
* NOTE that the size of `pthread_mutex_t` is variable dependent on hardware
|
||||
* architecture, but the largest known size is 40 bytes (five words).
|
||||
*/
|
||||
struct mutex_payload {
|
||||
pthread_mutex_t mutex;
|
||||
}
|
||||
|
||||
struct pso_pointer make_mutex();
|
||||
|
||||
/**
|
||||
* @brief evaluates these forms within the context of a thread-safe lock.
|
||||
*
|
||||
* 1. wait until the specified mutex can be locked;
|
||||
* 2. evaluate each of the forms sequentially in the context of that locked
|
||||
* mutex;
|
||||
* 3. if evaluation of any of the forms results in the throwing of an
|
||||
* exception, catch the exception, unlock the mutex, and then re-throw the
|
||||
* exception;
|
||||
* 4. on successful completion of the evaluation of the forms, unlock the mutex
|
||||
* and return the value of the last form.
|
||||
*
|
||||
* @param lock the lock: a mutex (MTX) object;
|
||||
* @param forms a list of arbitrary Lisp forms.
|
||||
* @return struct pso_pointer the result.
|
||||
*/
|
||||
struct pso_pointer with_lock( struct pso_pointer lock, struct pso_pointer forms);
|
||||
|
||||
/**
|
||||
* @brief as with_lock, q.v. but attempts to obtain a lock and returns an
|
||||
* exception on failure
|
||||
*
|
||||
* 1. attempt to lock the specified mutex;
|
||||
* 2. if successful, proceed as `with_lock`;
|
||||
* 3. otherwise, return a specific exception which can be trapped for.
|
||||
*
|
||||
* @param lock the lock: a mutex (MTX) object;
|
||||
* @param forms a list of arbitrary Lisp forms.
|
||||
* @return struct pso_pointer the result.
|
||||
*/
|
||||
struct pso_pointer attempt_with_lock( struct pso_pointer lock, struct pso_pointer forms);
|
||||
42
src/c/payloads/namespace.h
Normal file
42
src/c/payloads/namespace.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* payloads/namespace.h
|
||||
*
|
||||
* a Lisp namespace - a hashtable whose contents are mutable.
|
||||
*
|
||||
* Can sensibly sit in any pso from size class 6 upwards.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_payloads_namespace_h
|
||||
#define __psse_payloads_namespace_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
|
||||
/**
|
||||
* @brief Tag for a Lisp namespace - a hashtable whose contents are mutable.
|
||||
* \see HASHTABLETAG for mutable hashtables.
|
||||
*/
|
||||
#define NAMESPACETAG "NSP"
|
||||
|
||||
/**
|
||||
* The payload of a namespace. The number of buckets is assigned at run-time,
|
||||
* and is stored in n_buckets. Each bucket is something ASSOC can consume:
|
||||
* i.e. either an assoc list or a further namespace.
|
||||
*/
|
||||
struct namespace_payload {
|
||||
struct cons_pointer hash_fn; /* function for hashing values in this namespace, or
|
||||
* `NIL` to use 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 */
|
||||
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`
|
||||
* or assoc lists or (possibly) further hashtables. */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -97,9 +97,9 @@ int main( int argc, char *argv[] ) {
|
|||
}
|
||||
}
|
||||
|
||||
initialise_node( 0);
|
||||
initialise_node( 0 );
|
||||
|
||||
repl();
|
||||
repl( );
|
||||
|
||||
exit( 0);
|
||||
}
|
||||
exit( 0 );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,4 +27,4 @@
|
|||
#include "memory/stack.h"
|
||||
#include "version.h"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue