diff --git a/src/c/arith/READMDE.md b/src/c/arith/READMDE.md new file mode 100644 index 0000000..f59b772 --- /dev/null +++ b/src/c/arith/READMDE.md @@ -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. \ No newline at end of file diff --git a/src/c/debug.c b/src/c/debug.c new file mode 100644 index 0000000..2bd417d --- /dev/null +++ b/src/c/debug.c @@ -0,0 +1,16 @@ +/** + * debug.h + * + * Post Scarcity Software Environment: entry point. + * + * Print debugging output. + * + * + * (c) 2026 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + + #include "debug.h" + + int verbosity = 0; + \ No newline at end of file diff --git a/src/c/debug.h b/src/c/debug.h new file mode 100644 index 0000000..deb4487 --- /dev/null +++ b/src/c/debug.h @@ -0,0 +1,96 @@ +/** + * debug.h + * + * Post Scarcity Software Environment: entry point. + * + * Print debugging output. + * + * + * (c) 2026 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + +#ifndef __psse_debug_h +#define __psse_debug_h +#include +#include +#include + +/** + * @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 \ No newline at end of file diff --git a/src/c/memory/memory.c b/src/c/memory/memory.c new file mode 100644 index 0000000..570083e --- /dev/null +++ b/src/c/memory/memory.c @@ -0,0 +1,14 @@ +/** + * memory/memory.c + * + * The memory management subsystem. + * + * (c) 2026 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + + #include + + int initialise_memory() { + fprintf( stderr, "TODO: Implement initialise_memory()"); + } \ No newline at end of file diff --git a/src/c/memory/memory.h b/src/c/memory/memory.h new file mode 100644 index 0000000..a632520 --- /dev/null +++ b/src/c/memory/memory.h @@ -0,0 +1,15 @@ +/** + * memory/memory.h + * + * The memory management subsystem. + * + * (c) 2026 Simon Brooke + * 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 diff --git a/src/c/memory/node.c b/src/c/memory/node.c new file mode 100644 index 0000000..efbb9d4 --- /dev/null +++ b/src/c/memory/node.c @@ -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 + * 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; +} diff --git a/src/c/memory/node.h b/src/c/memory/node.h new file mode 100644 index 0000000..e21ec86 --- /dev/null +++ b/src/c/memory/node.h @@ -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 + * 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; diff --git a/src/c/memory/page.c b/src/c/memory/page.c new file mode 100644 index 0000000..4b9fe0f --- /dev/null +++ b/src/c/memory/page.c @@ -0,0 +1,36 @@ +/** + * memory/page.c + * + * Page for paged space psoects. + * + * (c) 2026 Simon Brooke + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + +#include + +#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; +} \ No newline at end of file diff --git a/src/c/memory/pointer.h b/src/c/memory/pointer.h index 8b3b3bf..18c3aa9 100644 --- a/src/c/memory/pointer.h +++ b/src/c/memory/pointer.h @@ -37,3 +37,5 @@ struct pso_pointer { */ uint16_t offset; }; + +#endif diff --git a/src/c/memory/pso4.h b/src/c/memory/pso4.h index 68a351d..1384d12 100644 --- a/src/c/memory/pso4.h +++ b/src/c/memory/pso4.h @@ -13,7 +13,7 @@ #include #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 diff --git a/src/c/memory/stack.c b/src/c/memory/stack.c new file mode 100644 index 0000000..ab98c93 --- /dev/null +++ b/src/c/memory/stack.c @@ -0,0 +1,38 @@ +/** + * memory/stack.c + * + * The execution stack. + * + * (c) 2026 Simon Brooke + * 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; +} diff --git a/src/c/payloads/stack_frame.h b/src/c/memory/stack.h similarity index 67% rename from src/c/payloads/stack_frame.h rename to src/c/memory/stack.h index 2aefcfc..7e0b2b0 100644 --- a/src/c/payloads/stack_frame.h +++ b/src/c/memory/stack.h @@ -1,7 +1,7 @@ /** - * payloads/stack_frame.h + * memory/stack.h * - * A stack frame. + * The execution stack. * * (c) 2026 Simon Brooke * Licensed under GPL version 2.0, or, at your option, any later version. @@ -17,18 +17,25 @@ */ #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. */ struct stack_frame_payload { /** the previous frame. */ - struct cons_pointer previous; + struct pso_pointer previous; /** first 8 arument bindings. */ - struct cons_pointer arg[args_in_frame]; + struct pso_pointer arg[args_in_frame]; /** list of any further argument bindings. */ - struct cons_pointer more; + struct pso_pointer more; /** the function to be called. */ - struct cons_pointer function; + struct pso_pointer function; /** the number of arguments provided. */ int args; /** the depth of the stack below this frame */ diff --git a/src/c/ops/README.md b/src/c/ops/README.md new file mode 100644 index 0000000..80f3ccd --- /dev/null +++ b/src/c/ops/README.md @@ -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`. \ No newline at end of file diff --git a/src/c/ops/eq.c b/src/c/ops/eq.c new file mode 100644 index 0000000..0c2e192 --- /dev/null +++ b/src/c/ops/eq.c @@ -0,0 +1,56 @@ +/** + * ops/eq.c + * + * Post Scarcity Software Environment: eq. + * + * Test for pointer equality. + * + * (c) 2026 Simon Brooke + * 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; +} diff --git a/src/c/ops/eq.h b/src/c/ops/eq.h new file mode 100644 index 0000000..febb5af --- /dev/null +++ b/src/c/ops/eq.h @@ -0,0 +1,21 @@ +/** + * ops/eq.h + * + * Post Scarcity Software Environment: eq. + * + * Test for pointer equality. + * + * (c) 2026 Simon Brooke + * 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 \ No newline at end of file diff --git a/src/c/ops/eval.c b/src/c/ops/eval.c new file mode 100644 index 0000000..d76da2b --- /dev/null +++ b/src/c/ops/eval.c @@ -0,0 +1,65 @@ +/** + * ops/eval.c + * + * Post Scarcity Software Environment: eval. + * + * Evaluate an arbitrary Lisp expression. + * + * (c) 2026 Simon Brooke + * 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; +} \ No newline at end of file diff --git a/src/c/ops/repl.h b/src/c/ops/repl.h new file mode 100644 index 0000000..e69de29 diff --git a/src/c/psse.c b/src/c/psse.c new file mode 100644 index 0000000..636cde5 --- /dev/null +++ b/src/c/psse.c @@ -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 + * 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); +} \ No newline at end of file diff --git a/src/c/psse.h b/src/c/psse.h new file mode 100644 index 0000000..759c33c --- /dev/null +++ b/src/c/psse.h @@ -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 + * Licensed under GPL version 2.0, or, at your option, any later version. + */ + +#ifndef __psse_psse_h +#define __psse_psse_h + +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "memory/memory.h" +#include "memory/stack.h" +#include "version.h" + +#endif \ No newline at end of file