Very close to a basic REPL now.

This commit is contained in:
Simon Brooke 2026-04-16 22:28:35 +01:00
parent 83537391a6
commit 4efe9eab87
23 changed files with 188 additions and 84 deletions

View file

@ -11,9 +11,14 @@
*/
#include <stdarg.h>
#include <stdlib.h>
#include "debug.h"
#include "io/fopen.h"
#include "io/io.h"
#include "io/print.h"
int verbosity = 0;
@ -45,14 +50,6 @@ void debug_print( wchar_t *message, int level, int indent ) {
#endif
}
void debug_print_object( struct pso_pointer object, int level, int indent ) {
// TODO: not yet implemented
}
void debug_dump_object( struct pso_pointer object, int level, int indent ) {
// TODO: not yet implemented
}
/**
* @brief print a 128 bit integer value to stderr, if `verbosity` matches `level`.
*
@ -133,5 +130,55 @@ void debug_printf( int level, int indent, wchar_t *format, ... ) {
#endif
}
// debug_dump_object, debug_print_binding, debug_print_exception, debug_print_object,
// not yet implemented but probably will be.
/**
* @brief print the object indicated by this `pointer` 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.
*/
void debug_print_object( struct pso_pointer pointer, int level, int indent ) {
#ifdef DEBUG
if ( level & verbosity ) {
URL_FILE *ustderr = file_to_url_file( stderr );
fwide( stderr, 1 );
in_print( pointer, ustderr );
free( ustderr );
}
#endif
}
/**
* @brief Like `dump_object`, q.v., but protected by the verbosity mechanism.
*
* `verbosity` is a set of flags, see debug_print.h; so you can
* turn debugging on for only one part of the system.
*/
void debug_dump_object( struct pso_pointer pointer, int level, int indent ) {
//#ifdef DEBUG
// if ( level & verbosity ) {
// URL_FILE *ustderr = file_to_url_file( stderr );
// fwide( stderr, 1 );
// dump_object( ustderr, pointer );
// free( ustderr );
// }
//#endif
}
///**
// * Standardise printing of binding trace messages.
// */
//void debug_print_binding( struct cons_pointer key, struct cons_pointer val,
// bool deep, int level, int indent ) {
//#ifdef DEBUG
// // wchar_t * depth = (deep ? L"Deep" : L"Shallow");
//
// debug_print( ( deep ? L"Deep" : L"Shallow" ), level, indent );
// debug_print( L" binding `", level, indent );
// debug_print_object( key, level, indent );
// debug_print( L"` to `", level, indent );
// debug_print_object( val, level, indent );
// debug_print( L"`\n", level, indent );
//#endif
//}

View file

@ -286,8 +286,8 @@ struct pso_pointer push_back_character( struct pso_pointer c,
if ( characterp( c ) && readp( r ) ) {
if ( url_ungetwc( ( wint_t )
( pointer_to_object( c )->payload.character.
character ),
( pointer_to_object( c )->payload.
character.character ),
pointer_to_object( r )->payload.stream.stream ) >=
0 ) {
result = t;
@ -315,8 +315,8 @@ lisp_close( struct pso_pointer frame_pointer, struct pso_pointer env ) {
if ( readp( fetch_arg( frame, 0 ) ) || writep( fetch_arg( frame, 0 ) ) ) {
if ( url_fclose
( pointer_to_object( fetch_arg( frame, 0 ) )->payload.
stream.stream )
( pointer_to_object( fetch_arg( frame, 0 ) )->payload.stream.
stream )
== 0 ) {
result = t;
}
@ -569,8 +569,8 @@ lisp_read_char( struct pso_pointer frame_pointer, struct pso_pointer env ) {
if ( readp( fetch_arg( frame, 0 ) ) ) {
result =
make_string( url_fgetwc
( pointer_to_object( fetch_arg( frame, 0 ) )->payload.
stream.stream ), nil );
( pointer_to_object( fetch_arg( frame, 0 ) )->
payload.stream.stream ), nil );
}
return result;

View file

@ -109,7 +109,7 @@ struct pso_pointer in_print( struct pso_pointer p, URL_FILE *output ) {
* @param stream if a pointer to an open write stream, print to there.
* @return struct pso_pointer `nil`, or an exception if some erroe occurred.
*/
struct pso_pointer print( struct pso_pointer p, struct pso_pointer stream ) {
struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ) {
URL_FILE *output = writep( stream ) ?
pointer_to_object( stream )->payload.stream.stream :
file_to_url_file( stdout );

View file

@ -14,6 +14,8 @@
#ifndef __psse_io_print_h
#define __psse_io_print_h
struct pso_pointer print( struct pso_pointer p, struct pso_pointer stream );
struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream );
struct pso_pointer in_print( struct pso_pointer p, URL_FILE * output );
#endif

View file

@ -49,7 +49,8 @@ struct pso_pointer initialise_memory( uint32_t node ) {
if ( memory_initialised ) {
result =
make_exception( c_string_to_lisp_string
( L"Attenpt to reinitialise memory." ), nil, nil, nil );
( L"Attenpt to reinitialise memory." ), nil, nil,
nil );
} else {
for ( uint8_t i = 0; i <= MAX_SIZE_CLASS; i++ ) {
freelists[i] = nil;

View file

@ -46,6 +46,11 @@ struct pso_pointer nil = ( struct pso_pointer ) { 0, 0, 0 };
*/
struct pso_pointer t = ( struct pso_pointer ) { 0, 0, 4 };
/**
* @brief The root of the data space.
*/
struct pso_pointer oblist = ( struct pso_pointer ) { 0, 0, 0 };
/**
* @brief Set up the basic informetion about this node.

View file

@ -31,6 +31,8 @@ extern struct pso_pointer nil;
*/
extern struct pso_pointer t;
extern struct pso_pointer oblist;
struct pso_pointer initialise_node( uint32_t index );
#endif

View file

@ -31,12 +31,14 @@ uint32_t get_tag_value( struct pso_pointer p ) {
*
* @param p must be a struct pso_pointer, indicating the appropriate object.
*/
struct pso_pointer get_tag_string( struct pso_pointer p) {
struct pso_pointer get_tag_string( struct pso_pointer p ) {
struct pso_pointer result = nil;
struct pso2 *object = pointer_to_object( p );
for ( int i = 2 - 1; i >= 0; i-- ) {
result = make_string( (wchar_t)(object->header.tag.bytes.mnemonic[i]), result );
result =
make_string( ( wchar_t ) ( object->header.tag.bytes.mnemonic[i] ),
result );
}
return result;

View file

@ -84,7 +84,7 @@
// #define get_tag_value(p)((pointer_to_object(p)->header.tag.value) & 0xffffff)
uint32_t get_tag_value( struct pso_pointer p );
struct pso_pointer get_tag_string( struct pso_pointer p);
struct pso_pointer get_tag_string( struct pso_pointer p );
/**
* @brief check that the tag of the object indicated by this poiner has this

View file

@ -87,8 +87,10 @@ struct pso_pointer eval(
( c_string_to_lisp_string
( L"Can't yet evaluate things of this type: " ),
result ), frame_pointer,
c_cons( c_cons( c_string_to_lisp_keyword(L"tag"),
get_tag_string(result)), nil), nil );
c_cons( c_cons
( c_string_to_lisp_keyword( L"tag" ),
get_tag_string( result ) ), nil ),
nil );
}
if ( exceptionp( result ) ) {
@ -98,8 +100,8 @@ struct pso_pointer eval(
if ( nilp( x->payload.exception.stack ) ) {
result =
make_exception( x->payload.exception.message, frame_pointer, nil,
result );
make_exception( x->payload.exception.message, frame_pointer,
nil, result );
}
}

View file

@ -65,8 +65,8 @@ struct pso_pointer c_reverse( struct pso_pointer sequence ) {
default:
result =
make_exception( c_cons( c_string_to_lisp_string
( L"Invalid object in sequence" ), cursor), nil,
nil , nil);
( L"Invalid object in sequence" ),
cursor ), nil, nil, nil );
goto exit;
break;
}

View file

@ -182,5 +182,3 @@ struct pso_pointer c_string_to_lisp_keyword( wchar_t *symbol ) {
return result;
}

View file

@ -82,11 +82,10 @@ struct pso_pointer c_cdr( struct pso_pointer p ) {
break;
default:
result =
make_exception(
c_cons(
c_string_to_lisp_string( L"Invalid type for cdr" ),
get_tag_string( p) ),
nil, nil, nil );
make_exception( c_cons
( c_string_to_lisp_string
( L"Invalid type for cdr" ),
get_tag_string( p ) ), nil, nil, nil );
break;
}

View file

@ -36,17 +36,18 @@
*/
struct pso_pointer make_exception( struct pso_pointer message,
struct pso_pointer frame,
struct pso_pointer meta,
struct pso_pointer meta,
struct pso_pointer cause ) {
struct pso_pointer result = allocate(EXCEPTIONTAG, 3);
struct pso_pointer result = allocate( EXCEPTIONTAG, 3 );
if (!nilp(result) && !exceptionp(result)) {
struct pso3* object = (struct pso3*)pointer_to_object( result);
if ( !nilp( result ) && !exceptionp( result ) ) {
struct pso3 *object = ( struct pso3 * ) pointer_to_object( result );
object->payload.exception.message = message;
object->payload.exception.stack = stackp(frame) ? frame : nil;
object->payload.exception.meta = (consp(meta) || hashtabp(meta)) ? meta : nil;
object->payload.exception.cause = exceptionp(cause) ? cause : nil;
object->payload.exception.message = message;
object->payload.exception.stack = stackp( frame ) ? frame : nil;
object->payload.exception.meta = ( consp( meta )
|| hashtabp( meta ) ) ? meta : nil;
object->payload.exception.cause = exceptionp( cause ) ? cause : nil;
}
return result;
@ -63,12 +64,12 @@ struct pso_pointer destroy_exception( struct pso_pointer fp,
if ( stackp( fp ) ) {
struct pso4 *frame = pointer_to_pso4( fp );
struct pso_pointer p = frame->payload.stack_frame.arg[0];
struct pso3* object = (struct pso3*)pointer_to_object( p);
struct pso3 *object = ( struct pso3 * ) pointer_to_object( p );
dec_ref( object->payload.exception.message);
dec_ref( object->payload.exception.stack);
dec_ref( object->payload.exception.meta);
dec_ref( object->payload.exception.cause);
dec_ref( object->payload.exception.message );
dec_ref( object->payload.exception.stack );
dec_ref( object->payload.exception.meta );
dec_ref( object->payload.exception.cause );
}
return nil;

View file

@ -16,7 +16,7 @@
* @brief An exception; required three pointers, so use object of size class 3.
*/
struct exception_payload {
/** @brief the exception message. Expected to be a string, but may be anything printable. */
/** @brief the exception message. Expected to be a string, but may be anything printable. */
struct pso_pointer message;
/** @brief the stack frame at which the exception was thrown. */
struct pso_pointer stack;
@ -28,7 +28,7 @@ struct exception_payload {
struct pso_pointer make_exception( struct pso_pointer message,
struct pso_pointer frame_pointer,
struct pso_pointer meta,
struct pso_pointer meta,
struct pso_pointer cause );
struct pso_pointer destroy_exception( struct pso_pointer fp,

View file

@ -12,13 +12,24 @@
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdbool.h>
#include <stdio.h>
#include <wchar.h>
#include <signal.h>
#include "debug.h"
#include "psse.h"
#include "io/io.h"
#include "memory/node.h"
#include "memory/pso.h"
#include "memory/tags.h"
#include "ops/stack_ops.h"
#include "ops/truth.h"
#include "payloads/cons.h"
#include "payloads/stack.h"
void print_banner( ) {
fwprintf( stdout, L"Post-Scarcity Software Environment version %s\n\n",
VERSION );
@ -54,6 +65,35 @@ void print_options( FILE *stream ) {
#endif
}
/**
* @brief Handle an interrupt signal.
*
* @param dummy
*/
void int_handler( int dummy ) {
wprintf( L"TODO: handle ctrl-C in a more interesting way\n" );
}
/**
* The read/eval/print loop.
*/
void repl( ) {
signal( SIGINT, int_handler );
debug_print( L"Entered repl\n", DEBUG_REPL, 0 );
struct pso_pointer env = consp( oblist ) ? oblist : c_cons( oblist, nil );
/* bottom of stack */
struct pso_pointer frame_pointer = make_frame( 1, nil, nil, env );
if ( !nilp( frame_pointer ) ) {
// lisp_repl( get_stack_frame( frame_pointer ), frame_pointer, env );
dec_ref( frame_pointer );
}
debug_print( L"Leaving repl\n", DEBUG_REPL, 0 );
}
/**
* main entry point; parse command line arguments, initialise the environment,
@ -101,7 +141,12 @@ int main( int argc, char *argv[] ) {
}
}
if ( nilp( initialise_node( 0 ) ) ) {
oblist = initialise_node( 0 );
debug_print( L"Oblist: ", DEBUG_BOOTSTRAP, 0 );
debug_print_object( oblist, DEBUG_BOOTSTRAP, 0 );
debug_println( DEBUG_BOOTSTRAP );
if ( nilp( oblist ) ) {
fputs( "Failed to initialise node\n", stderr );
exit( 1 );
}