Lots more code written, and I think most of it's OK; but it doesn't compile yet.

This commit is contained in:
Simon Brooke 2026-03-26 09:01:46 +00:00
parent 604fca3c24
commit 6c4be8f283
19 changed files with 634 additions and 7 deletions

24
src/c/arith/READMDE.md Normal file
View file

@ -0,0 +1,24 @@
# README: PSSE substrate arithmetic
This folder/pseudo package is to implement enough of arithmetic for bootstrap:
that is, enough that all more sophisticated arithmetic can be built on top of
it.
Ratio arithmetic will not be implemented in the substrate, but `make-ratio`
will. The signature for `make-ratio` will be:
`(make-ratio dividend divisor) => ratio`
Both divisor and dividend should be integers. If the divisor is `1` it will
return the dividend (as an integer). If the divisor is 0 it will return ∞.
This implies we need a privileged data item representing infinity...
Bignum arithmetic will not be implemented in the substrate, but `make-bignum`
will be. The signature for `make-bignum` will be
`(make-bignum integer) => bignum`
If the integer argument is less than 64 bits, the argument will be returned
unmodified. If it is more than 64 bits, a bignum of the same value will be
returned.

16
src/c/debug.c Normal file
View file

@ -0,0 +1,16 @@
/**
* debug.h
*
* Post Scarcity Software Environment: entry point.
*
* Print debugging output.
*
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "debug.h"
int verbosity = 0;

96
src/c/debug.h Normal file
View file

@ -0,0 +1,96 @@
/**
* debug.h
*
* Post Scarcity Software Environment: entry point.
*
* Print debugging output.
*
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __psse_debug_h
#define __psse_debug_h
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
/**
* @brief Print messages debugging memory allocation.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_ALLOC 1
/**
* @brief Print messages debugging arithmetic operations.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_ARITH 2
/**
* @brief Print messages debugging symbol binding.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_BIND 4
/**
* @brief Print messages debugging bootstrapping and teardown.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_BOOTSTRAP 8
/**
* @brief Print messages debugging evaluation.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_EVAL 16
/**
* @brief Print messages debugging input/output operations.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_IO 32
/**
* @brief Print messages debugging lambda functions (interpretation).
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_LAMBDA 64
/**
* @brief Print messages debugging the read eval print loop.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_REPL 128
/**
* @brief Print messages debugging stack operations.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_STACK 256
/**
* @brief Print messages about equality tests.
*
* Flag interpretation for the value of `verbosity`, defined in `debug.c`, q.v.
*/
#define DEBUG_EQUAL 512
/**
* @brief Verbosity (and content) of debugging output
*
* Interpreted as a sequence of topic-specific flags, see above.
*/
extern int verbosity;
#endif

14
src/c/memory/memory.c Normal file
View file

@ -0,0 +1,14 @@
/**
* memory/memory.c
*
* The memory management subsystem.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdio.h>
int initialise_memory() {
fprintf( stderr, "TODO: Implement initialise_memory()");
}

15
src/c/memory/memory.h Normal file
View file

@ -0,0 +1,15 @@
/**
* memory/memory.h
*
* The memory management subsystem.
*
* (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
int initialise_memory();
#endif

55
src/c/memory/node.c Normal file
View file

@ -0,0 +1,55 @@
/**
* memory/node.c
*
* Top level data about the actual node on which this memory system sits.
* May not belong in `memory`.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "memory/memory.h"
#include "memory/pointer.h"
/**
* @brief Flag to prevent the node being initialised more than once.
*
*/
bool node_initialised = false;
/**
* @brief The index of this node in the hypercube.
*
*/
uint32_t node_index = 0;
/**
* @brief The canonical `nil` pointer
*
*/
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};
/**
* @brief Set up the basic informetion about this node
*
* @param index
* @return struct pso_pointer
*/
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);
if ( eq( result, t)) {
result = initialise_environment();
}
return result;
}

31
src/c/memory/node.h Normal file
View file

@ -0,0 +1,31 @@
/**
* memory/node.h
*
* Top level data about the actual node on which this memory system sits.
* May not belong in `memory`.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __psse_memory_node_h
#define __psse_memory_node_h
/**
* @brief The index of this node in the hypercube.
*
*/
extern int node_index;
/**
* @brief The canonical `nil` pointer
*
*/
extern struct pso_pointer nil;
/**
* @brief the canonical `t` (true) pointer.
*
*/
extern struct pso_pointer t;

36
src/c/memory/page.c Normal file
View file

@ -0,0 +1,36 @@
/**
* memory/page.c
*
* Page for paged space psoects.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdint.h>
#include "memory/page.h"
#include "memory/pso2.h"
#include "memory/pso3.h"
#include "memory/pso4.h"
#include "memory/pso5.h"
#include "memory/pso6.h"
#include "memory/pso7.h"
#include "memory/pso8.h"
#include "memory/pso9.h"
#include "memory/psoa.h"
#include "memory/psob.h"
#include "memory/psoc.h"
#include "memory/psod.h"
#include "memory/psoe.h"
#include "memory/psof.h"
void * malloc_page( uint8_t size_class) {
void * result = malloc( sizeof( page));
if (result != NULL) {
}
return result;
}

View file

@ -37,3 +37,5 @@ struct pso_pointer {
*/ */
uint16_t offset; uint16_t offset;
}; };
#endif

View file

@ -13,7 +13,7 @@
#include <stdint.h> #include <stdint.h>
#include "memory/header.h" #include "memory/header.h"
#include "payloads/stack_frame.h" #include "memory/stack.h"
/** /**
* @brief A paged space object of size class 4, 16 words total, 14 words * @brief A paged space object of size class 4, 16 words total, 14 words

38
src/c/memory/stack.c Normal file
View file

@ -0,0 +1,38 @@
/**
* memory/stack.c
*
* The execution stack.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "memory/stack.h"
/**
* @brief The maximum depth of stack before we throw an exception.
*
* `0` is interpeted as `unlimited`.
*/
uint32_t stack_limit = 0;
/**
* 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 cons_pointer result = NIL;
if ( index < args_in_frame ) {
result = frame->arg[index];
} else {
struct cons_pointer p = frame->more;
for ( int i = args_in_frame; i < index; i++ ) {
p = pointer2cell( p ).payload.cons.cdr;
}
result = pointer2cell( p ).payload.cons.car;
}
return result;
}

View file

@ -1,7 +1,7 @@
/** /**
* payloads/stack_frame.h * memory/stack.h
* *
* A stack frame. * The execution stack.
* *
* (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.
@ -17,18 +17,25 @@
*/ */
#define args_in_frame 8 #define args_in_frame 8
/**
* @brief The maximum depth of stack before we throw an exception.
*
* `0` is interpeted as `unlimited`.
*/
extern uint32_t stack_limit;
/** /**
* A stack frame. * A stack frame.
*/ */
struct stack_frame_payload { struct stack_frame_payload {
/** the previous frame. */ /** the previous frame. */
struct cons_pointer previous; struct pso_pointer previous;
/** first 8 arument bindings. */ /** first 8 arument bindings. */
struct cons_pointer arg[args_in_frame]; struct pso_pointer arg[args_in_frame];
/** list of any further argument bindings. */ /** list of any further argument bindings. */
struct cons_pointer more; struct pso_pointer more;
/** the function to be called. */ /** the function to be called. */
struct cons_pointer function; struct pso_pointer function;
/** the number of arguments provided. */ /** the number of arguments provided. */
int args; int args;
/** the depth of the stack below this frame */ /** the depth of the stack below this frame */

16
src/c/ops/README.md Normal file
View file

@ -0,0 +1,16 @@
# README: PSSE substrate operations
This folder/pseudo-package is for things which implement basic Lisp functions.
These will be the functions which make up the `:bootstrap` and `:substrate`
packages in Lisp.
For each basic function the intention is that there should be one `.c` file
(and normally one `.h` file as well). This file will provide one version of the
function with Lisp calling conventions, called `lisp_xxxx`, and one with C
calling conventions, called `xxxx`. It does not matter whether the lisp version
calls the C version or vice versa, but one should call the other so there are
not two different versions of the logic.
Substrate I/O functions will not be provided in this pseudo-package but in `io`.
Substrate arithmetic functions will not be provided in this pseudo-package but
in `arith`.

56
src/c/ops/eq.c Normal file
View file

@ -0,0 +1,56 @@
/**
* ops/eq.c
*
* Post Scarcity Software Environment: eq.
*
* Test for pointer equality.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "memory/memory.h"
#include "memory/pointer.h"
#include "memory/stack.h"
/**
* @brief Function; do these two pointers point to the same object?
*
* Shallow, cheap equality.
*
* TODO: if either of these pointers points to a cache cell, then what
* we need to check is the cached value, which is not so cheap. Ouch!
*
* @param a a pointer;
* @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);
}
/**
* Function; do all arguments to this finction point to the same object?
*
* Shallow, cheap equality.
*
* * (eq? args...)
*
* @param frame my stack_frame.
* @param frame_pointer a pointer to my stack_frame.
* @param env my environment (ignored).
* @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 result = t;
if ( frame->args > 1 ) {
for ( int b = 1; ( truep( result ) ) && ( b < frame->args ); b++ ) {
result = eq( frame->arg[0], fetch_arg( frame, b ) ) ? t : nil;
}
}
return result;
}

21
src/c/ops/eq.h Normal file
View file

@ -0,0 +1,21 @@
/**
* ops/eq.h
*
* Post Scarcity Software Environment: eq.
*
* Test for pointer equality.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __psse_ops_eq_h
#define __psse_ops_eq_h
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 );
#endif

65
src/c/ops/eval.c Normal file
View file

@ -0,0 +1,65 @@
/**
* ops/eval.c
*
* Post Scarcity Software Environment: eval.
*
* Evaluate an arbitrary Lisp expression.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "memory/pointer"
#include "memory/stack.h"
#include "payloads/cons.h"
#include "payloads/function.h"
#include "payloads/keyword.h"
#include "payloads/lambda.h"
#include "payloads/nlambda.h"
#include "payloads/special.h"
/**
* @brief Despatch eval based on tag of the form in the first position.
*
* @param frame The current stack frame;
* @param frame_pointer A pointer to the current stack frame;
* @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 result = frame->arg[0];
// switch ( get_tag_value( result)) {
// case CONSTV:
// result = eval_cons( frame, frame_pointer, env);
// break;
// case KEYTV:
// case SYMBOLTV:
// result = eval_symbol( frame, frame_pointer, env);
// break;
// case LAMBDATV:
// result = eval_lambda( frame, frame_pointer, env);
// break;
// case NLAMBDATV:
// result = eval_nlambda( frame, frame_pointer, env);
// break;
// case SPECIALTV:
// result = eval_special( frame, frame_pointer, env);
// break;
// }
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);
if (exceptionp( result)) {
// todo: if result doesn't have a stack frame, create a new exception wrapping
// result with this stack frame.
}
return result;
}

0
src/c/ops/repl.h Normal file
View file

105
src/c/psse.c Normal file
View file

@ -0,0 +1,105 @@
/**
* psse.c
*
* Post Scarcity Software Environment: entry point.
*
* Start up and initialise the environement - just enough to get working
* and (ultimately) hand off to the executive.
*
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include "psse.h"
#include "memory/node.h"
void print_banner( ) {
fwprintf( stdout, L"Post-Scarcity Software Environment version %s\n\n",
VERSION );
}
/**
* Print command line options to this `stream`.
*
* @stream the stream to print to.
*/
void print_options( FILE *stream ) {
fwprintf( stream, L"Expected options are:\n" );
fwprintf( stream,
L"\t-d\tDump memory to standard out at end of run (copious!);\n" );
fwprintf( stream, L"\t-h\tPrint this message and exit;\n" );
fwprintf( stream, L"\t-p\tShow a prompt (default is no prompt);\n" );
fwprintf( stream,
L"\t-s LIMIT\n\t\tSet the maximum stack depth to this LIMIT (int)\n" );
#ifdef DEBUG
fwprintf( stream,
L"\t-v LEVEL\n\t\tSet verbosity to the specified level (0...512)\n" );
fwprintf( stream, L"\t\tWhere bits are interpreted as follows:\n" );
fwprintf( stream, L"\t\t1\tALLOC;\n" );
fwprintf( stream, L"\t\t2\tARITH;\n" );
fwprintf( stream, L"\t\t4\tBIND;\n" );
fwprintf( stream, L"\t\t8\tBOOTSTRAP;\n" );
fwprintf( stream, L"\t\t16\tEVAL;\n" );
fwprintf( stream, L"\t\t32\tINPUT/OUTPUT;\n" );
fwprintf( stream, L"\t\t64\tLAMBDA;\n" );
fwprintf( stream, L"\t\t128\tREPL;\n" );
fwprintf( stream, L"\t\t256\tSTACK;\n" );
fwprintf( stream, L"\t\t512\tEQUAL.\n" );
#endif
}
/**
* main entry point; parse command line arguments, initialise the environment,
* and enter the read-eval-print loop.
*/
int main( int argc, char *argv[] ) {
int option;
bool dump_at_end = false;
bool show_prompt = false;
char *infilename = NULL;
setlocale( LC_ALL, "" );
// if ( io_init( ) != 0 ) {
// fputs( "Failed to initialise I/O subsystem\n", stderr );
// exit( 1 );
// }
while ( ( option = getopt( argc, argv, "dhi:ps:v:" ) ) != -1 ) {
switch ( option ) {
case 'd':
dump_at_end = true;
break;
case 'h':
print_banner( );
print_options( stdout );
exit( 0 );
break;
case 'i':
infilename = optarg;
break;
case 'p':
show_prompt = true;
break;
case 's':
stack_limit = atoi( optarg );
break;
case 'v':
verbosity = atoi( optarg );
break;
default:
fwprintf( stderr, L"Unexpected option %c\n", option );
print_options( stderr );
exit( 1 );
break;
}
}
initialise_node( 0);
repl();
exit( 0);
}

30
src/c/psse.h Normal file
View file

@ -0,0 +1,30 @@
/**
* psse.h
*
* Post Scarcity Software Environment: entry point.
*
* Start up and initialise the environement - just enough to get working
* and (ultimately) hand off to the executive.
*
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#ifndef __psse_psse_h
#define __psse_psse_h
#include <getopt.h>
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wchar.h>
#include "debug.h"
#include "memory/memory.h"
#include "memory/stack.h"
#include "version.h"
#endif