I think read will now read integers and symbols, but it's untested.
Everything compiles.
This commit is contained in:
parent
cc8e96eda4
commit
9eb0d3c5a0
28 changed files with 594 additions and 293 deletions
|
|
@ -46,6 +46,7 @@
|
||||||
#include "ops/string_ops.h"
|
#include "ops/string_ops.h"
|
||||||
#include "ops/truth.h"
|
#include "ops/truth.h"
|
||||||
|
|
||||||
|
#include "payloads/character.h"
|
||||||
#include "payloads/cons.h"
|
#include "payloads/cons.h"
|
||||||
#include "payloads/exception.h"
|
#include "payloads/exception.h"
|
||||||
#include "payloads/integer.h"
|
#include "payloads/integer.h"
|
||||||
|
|
@ -81,7 +82,7 @@ wint_t ungotten = 0;
|
||||||
*
|
*
|
||||||
* @return 0 on success; any other value means failure.
|
* @return 0 on success; any other value means failure.
|
||||||
*/
|
*/
|
||||||
int io_init( ) {
|
int initialise_io( ) {
|
||||||
int result = curl_global_init( CURL_GLOBAL_SSL );
|
int result = curl_global_init( CURL_GLOBAL_SSL );
|
||||||
|
|
||||||
io_share = curl_share_init( );
|
io_share = curl_share_init( );
|
||||||
|
|
@ -252,6 +253,43 @@ wint_t url_ungetwc( wint_t wc, URL_FILE *input ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read one character object from this `read_stream`.
|
||||||
|
*
|
||||||
|
* @param read_stream a pointer to an object which should be a read stream
|
||||||
|
* object,
|
||||||
|
*
|
||||||
|
* @return a pointer to a character object on success, or `nil` on failure.
|
||||||
|
*/
|
||||||
|
struct pso_pointer get_character( struct pso_pointer read_stream ) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
if (readp( read_stream)) {
|
||||||
|
result = make_character( url_fgetwc( pointer_to_object_of_size_class(read_stream, 2)->payload.stream.stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Push back this character `c` onto this read stream `r`.
|
||||||
|
*
|
||||||
|
* @param c a pointer to an object which should be a character object;
|
||||||
|
* @param r a pointer to an object which should be a read stream object,
|
||||||
|
*
|
||||||
|
* @return `t` on success, else `nil`.
|
||||||
|
*/
|
||||||
|
struct pso_pointer push_back_character( struct pso_pointer c, struct pso_pointer r) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
if (characterp(c) && readp(r)) {
|
||||||
|
if (url_ungetwc( (wint_t)(pointer_to_object(c)->payload.character.character),
|
||||||
|
pointer_to_object(r)->payload.stream.stream) >= 0) {
|
||||||
|
result = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function, sort-of: close the file indicated by my first arg, and return
|
* Function, sort-of: close the file indicated by my first arg, and return
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
extern CURLSH *io_share;
|
extern CURLSH *io_share;
|
||||||
|
|
||||||
int io_init( );
|
int initialise_io( );
|
||||||
|
|
||||||
#define C_IO_IN L"*in*"
|
#define C_IO_IN L"*in*"
|
||||||
#define C_IO_OUT L"*out*"
|
#define C_IO_OUT L"*out*"
|
||||||
|
|
@ -30,6 +30,10 @@ URL_FILE *file_to_url_file( FILE * f );
|
||||||
wint_t url_fgetwc( URL_FILE * input );
|
wint_t url_fgetwc( URL_FILE * input );
|
||||||
wint_t url_ungetwc( wint_t wc, URL_FILE * input );
|
wint_t url_ungetwc( wint_t wc, URL_FILE * input );
|
||||||
|
|
||||||
|
struct pso_pointer get_character( struct pso_pointer read_stream );
|
||||||
|
|
||||||
|
struct pso_pointer push_back_character( struct pso_pointer c, struct pso_pointer r);
|
||||||
|
|
||||||
struct pso_pointer get_default_stream( bool inputp, struct pso_pointer env );
|
struct pso_pointer get_default_stream( bool inputp, struct pso_pointer env );
|
||||||
|
|
||||||
struct pso_pointer
|
struct pso_pointer
|
||||||
|
|
|
||||||
178
src/c/io/read.c
178
src/c/io/read.c
|
|
@ -23,16 +23,22 @@
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "memory/node.h"
|
|
||||||
#include "memory/pointer.h"
|
|
||||||
#include "memory/pso2.h"
|
|
||||||
|
|
||||||
#include "io/io.h"
|
#include "io/io.h"
|
||||||
#include "io/read.h"
|
#include "io/read.h"
|
||||||
|
#include "memory/node.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
#include "payloads/integer.h"
|
#include "payloads/integer.h"
|
||||||
#include "ops/stack_ops.h"
|
#include "payloads/read_stream.h"
|
||||||
|
|
||||||
|
#include "ops/assoc.h"
|
||||||
|
#include "ops/reverse.h"
|
||||||
|
#include "ops/stack_ops.h"
|
||||||
|
#include "ops/string_ops.h"
|
||||||
|
#include "ops/truth.h"
|
||||||
|
|
||||||
// TODO: what I've copied from 0.0.6 is *wierdly* over-complex for just now.
|
// TODO: what I've copied from 0.0.6 is *wierdly* over-complex for just now.
|
||||||
// I think I'm going to essentially delete all this and start again. We need
|
// I think I'm going to essentially delete all this and start again. We need
|
||||||
|
|
@ -57,29 +63,167 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example wrapper function while I work out how I'm going to do this.
|
* An example wrapper function while I work out how I'm going to do this.
|
||||||
|
*
|
||||||
|
* For this and all other `read` functions unless documented otherwise, the
|
||||||
|
* arguments in the frame are expected to be:
|
||||||
|
*
|
||||||
|
* 0. The input stream to read from;
|
||||||
|
* 1. The read table currently in use;
|
||||||
|
* 2. The character most recently read from that stream.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer read_example( struct pso4 *frame,
|
struct pso_pointer read_example( struct pso_pointer frame_pointer,
|
||||||
struct pso_pointer frame_pointer,
|
|
||||||
struct pso_pointer env) {
|
struct pso_pointer env) {
|
||||||
struct pso_pointer character = fetch_arg( frame, 0);
|
struct pso4 *frame = pointer_to_pso4( frame_pointer);
|
||||||
struct pso_pointer stream = fetch_arg( frame, 1);
|
struct pso_pointer stream = fetch_arg( frame, 0);
|
||||||
struct pso_pointer readtable = fetch_arg( frame, 2);
|
struct pso_pointer readtable = fetch_arg( frame, 1);
|
||||||
|
struct pso_pointer character = fetch_arg( frame, 2);
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
return character;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the next object on this input stream and return a pso_pointer to it.
|
* @brief Read one integer from the stream and return it.
|
||||||
|
*
|
||||||
|
* For this and all other `read` functions unless documented otherwise, the
|
||||||
|
* arguments in the frame are expected to be:
|
||||||
|
*
|
||||||
|
* 0. The input stream to read from;
|
||||||
|
* 1. The read table currently in use;
|
||||||
|
* 2. The character most recently read from that stream.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer read( struct pso4 *frame,
|
struct pso_pointer read_number( struct pso_pointer frame_pointer,
|
||||||
struct pso_pointer frame_pointer,
|
|
||||||
struct pso_pointer env) {
|
struct pso_pointer env) {
|
||||||
struct pso_pointer* character = fetch_arg( frame, 0);
|
struct pso4 *frame = pointer_to_pso4( frame_pointer);
|
||||||
struct pso_pointer stream = fetch_arg( frame, 1);
|
struct pso_pointer stream = fetch_arg( frame, 0);
|
||||||
struct pso_pointer readtable = fetch_arg( frame, 2);
|
struct pso_pointer readtable = fetch_arg( frame, 1);
|
||||||
|
struct pso_pointer character = fetch_arg( frame, 2);
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
int base = 10;
|
||||||
|
// TODO: should check for *read-base* in the environment
|
||||||
|
int64_t value = 0;
|
||||||
|
|
||||||
|
if (readp(stream)) {
|
||||||
|
if (nilp( character)) {
|
||||||
|
character = get_character( stream);
|
||||||
|
}
|
||||||
|
wchar_t c = nilp(character) ? 0 :
|
||||||
|
pointer_to_object( character)->payload.character.character;
|
||||||
|
|
||||||
|
URL_FILE * input = pointer_to_object(stream)->payload.stream.stream;
|
||||||
|
for ( ; iswdigit( c );
|
||||||
|
c = url_fgetwc( input ) ){
|
||||||
|
value = (value * base) + ((int)c - (int)L'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
url_ungetwc( c, input);
|
||||||
|
result = make_integer( value);
|
||||||
|
} // else exception?
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pso_pointer read_symbol( struct pso_pointer frame_pointer,
|
||||||
|
struct pso_pointer env) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( frame_pointer);
|
||||||
|
struct pso_pointer stream = fetch_arg( frame, 0);
|
||||||
|
struct pso_pointer readtable = fetch_arg( frame, 1);
|
||||||
|
struct pso_pointer character = fetch_arg( frame, 2);
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
if (readp(stream)) {
|
||||||
|
if (nilp( character)) {
|
||||||
|
character = get_character( stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t c = nilp(character) ? 0 :
|
||||||
|
pointer_to_object( character)->payload.character.character;
|
||||||
|
|
||||||
|
URL_FILE * input = pointer_to_object(stream)->payload.stream.stream;
|
||||||
|
for ( ; iswalnum( c );
|
||||||
|
c = url_fgetwc( input ) ){
|
||||||
|
result = make_string_like_thing(c, result, SYMBOLTAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
url_ungetwc( c, input);
|
||||||
|
result = reverse( result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read the next object on the input stream indicated by this stack
|
||||||
|
* frame, and return a pso_pointer to the object read.
|
||||||
|
*
|
||||||
|
* For this and all other `read` functions unless documented otherwise, the
|
||||||
|
* arguments in the frame are expected to be:
|
||||||
|
*
|
||||||
|
* 0. The input stream to read from;
|
||||||
|
* 1. The read table currently in use;
|
||||||
|
* 2. The character most recently read from that stream.
|
||||||
|
*/
|
||||||
|
struct pso_pointer read( struct pso_pointer frame_pointer,
|
||||||
|
struct pso_pointer env ) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( frame_pointer);
|
||||||
|
struct pso_pointer stream = fetch_arg( frame, 0);
|
||||||
|
struct pso_pointer readtable = fetch_arg( frame, 1);
|
||||||
|
struct pso_pointer character = fetch_arg( frame, 2);
|
||||||
|
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
if (nilp(stream)) {
|
if (nilp(stream)) {
|
||||||
|
stream = make_read_stream( file_to_url_file(stdin), nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nilp( readtable)) {
|
||||||
|
// TODO: check for the value of `*read-table*` in the environment and
|
||||||
|
// use that.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nilp( character)) {
|
||||||
|
character = get_character( stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pso_pointer readmacro = assoc(character, readtable);
|
||||||
|
|
||||||
|
if (!nilp( readmacro)) {
|
||||||
|
// invoke the read macro on the stream
|
||||||
|
} else if (readp( stream) && characterp(character)) {
|
||||||
|
wchar_t c = pointer_to_object( character)->payload.character.character;
|
||||||
|
URL_FILE * input = pointer_to_object(stream)->payload.stream.stream;
|
||||||
|
|
||||||
|
switch ( c ) {
|
||||||
|
case ';':
|
||||||
|
for ( c = url_fgetwc( input ); c != '\n';
|
||||||
|
c = url_fgetwc( input ) );
|
||||||
|
/* skip all characters from semi-colon to the end of the line */
|
||||||
|
break;
|
||||||
|
case EOF:
|
||||||
|
// result = throw_exception( c_string_to_lisp_symbol( L"read" ),
|
||||||
|
// c_string_to_lisp_string
|
||||||
|
// ( L"End of input while reading" ),
|
||||||
|
// frame_pointer );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
struct pso_pointer next = make_frame( frame_pointer, stream, readtable, make_character(c));
|
||||||
|
if ( iswdigit( c ) ) {
|
||||||
|
result =
|
||||||
|
read_number( next, env );
|
||||||
|
} else if ( iswalpha( c ) ) {
|
||||||
|
result = read_symbol( next, env );
|
||||||
|
} else {
|
||||||
|
// result =
|
||||||
|
// throw_exception( c_string_to_lisp_symbol( L"read" ),
|
||||||
|
// make_cons( c_string_to_lisp_string
|
||||||
|
// ( L"Unrecognised start of input character" ),
|
||||||
|
// make_string( c, NIL ) ),
|
||||||
|
// frame_pointer );
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
||||||
58
src/c/memory/destroy.c
Normal file
58
src/c/memory/destroy.c
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
* memory/free.c
|
||||||
|
*
|
||||||
|
* Centralised point for despatching free methods to types.
|
||||||
|
*
|
||||||
|
* TODO: In the long run, we need a type for tags, which defines a constructor
|
||||||
|
* and a free method, along with the minimum and maximum size classes
|
||||||
|
* allowable for that tag; and we need a namespace in which tags are
|
||||||
|
* canonically stored, probably ::system:tags, in which the tag is bound to
|
||||||
|
* the type record describing it. And this all needs to work in Lisp, not
|
||||||
|
* in the substrate.
|
||||||
|
*
|
||||||
|
* (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"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
|
#include "payloads/cons.h"
|
||||||
|
#include "payloads/exception.h"
|
||||||
|
#include "payloads/stack.h"
|
||||||
|
#include "payloads/psse_string.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Despatch destroy message to the handler for the type of the
|
||||||
|
* object indicated by `p`, if there is one. What the destroy handler
|
||||||
|
* needs to do is dec_ref all the objects pointed to by it.
|
||||||
|
*
|
||||||
|
* The handler has 0.1.0 lisp calling convention, since
|
||||||
|
* 1. we should be able to write destroy handlers in Lisp; and
|
||||||
|
* 2. in the long run this whole system should be rewritten in Lisp.
|
||||||
|
*
|
||||||
|
* The handler returns `nil` on success, an exception pointer on
|
||||||
|
* failure. This function returns that exception pointer. How we
|
||||||
|
* handle that exception pointer I simply don't know yet.
|
||||||
|
*/
|
||||||
|
struct pso_pointer destroy( struct pso_pointer p) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
struct pso_pointer f = make_frame( nil, p);
|
||||||
|
inc_ref( f);
|
||||||
|
|
||||||
|
switch (get_tag_value(p)) {
|
||||||
|
case CONSTV: destroy_cons(f, nil); break;
|
||||||
|
case EXCEPTIONTV: destroy_exception(f, nil); break;
|
||||||
|
case KEYTV :
|
||||||
|
case STRINGTV:
|
||||||
|
case SYMBOLTV: destroy_string(f, nil); break;
|
||||||
|
case STACKTV: destroy_stack_frame(f, nil); break;
|
||||||
|
// TODO: others.
|
||||||
|
}
|
||||||
|
|
||||||
|
dec_ref(f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
17
src/c/memory/destroy.h
Normal file
17
src/c/memory/destroy.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* memory/destroy.h
|
||||||
|
*
|
||||||
|
* Despatcher for destructor functions when objects are freed.
|
||||||
|
*
|
||||||
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __psse_memory_destroy_h
|
||||||
|
#define __psse_memory_destroy_h
|
||||||
|
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
struct pso_pointer destroy( struct pso_pointer p);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
#include "memory/page.h"
|
#include "memory/page.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
#include "memory/pso2.h"
|
#include "memory/pso2.h"
|
||||||
#include "memory/pso3.h"
|
#include "memory/pso3.h"
|
||||||
#include "memory/pso4.h"
|
#include "memory/pso4.h"
|
||||||
|
|
@ -124,6 +125,12 @@ struct pso_pointer allocate_page( uint8_t size_class ) {
|
||||||
L"Initialised page %d; freelist for size class %x updated.\n",
|
L"Initialised page %d; freelist for size class %x updated.\n",
|
||||||
npages_allocated, size_class );
|
npages_allocated, size_class );
|
||||||
|
|
||||||
|
if (npages_allocated == 0) {
|
||||||
|
// first page allocated; initialise nil and t
|
||||||
|
nil = lock_object( allocate(NILTAG, 2));
|
||||||
|
t = lock_object( allocate(TRUETAG, 2));
|
||||||
|
}
|
||||||
|
|
||||||
npages_allocated++;
|
npages_allocated++;
|
||||||
} else {
|
} else {
|
||||||
// TODO: exception when we have one.
|
// TODO: exception when we have one.
|
||||||
|
|
|
||||||
|
|
@ -29,24 +29,35 @@ struct pso_pointer make_pointer( uint32_t node, uint16_t page,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns the in-memory address of the object indicated by this
|
* @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
|
* pointer `p`.
|
||||||
|
*
|
||||||
|
* NOTE THAT: It's impossible, with our calling conventions, to pass an
|
||||||
|
* exception back from this function. Consequently, if anything goes wrong
|
||||||
|
* we return NULL. The caller *should* check for that and throw an exception.
|
||||||
|
*
|
||||||
|
* NOTE THAT: The return signature of these functions is pso2, because it is
|
||||||
|
* safe to cast any paged space object to a pso2, but safe to cast an object
|
||||||
|
* of a smaller size class to a larger one. If you know what size class you
|
||||||
|
* want, you should prefer `pointer_to_object_of_size_class()`, q.v.
|
||||||
|
*
|
||||||
|
* TODO: The reason I'm doing it this way is because I'm not
|
||||||
* certain reference counter updates work right it we work with 'the object'
|
* 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
|
* rather than 'the address of the object'. I really ought to have a
|
||||||
* conversation with someone who understands this bloody language.
|
* conversation with someone who understands this bloody language.
|
||||||
*
|
*
|
||||||
* @param pointer a pso_pointer which references an object.
|
* @param p a pso_pointer which references an object.
|
||||||
* @return struct pso2* the actual address in memory of that object.
|
*
|
||||||
|
* @return the actual address in memory of that object, or NULL if `p` is
|
||||||
|
* invalid.
|
||||||
*/
|
*/
|
||||||
struct pso2 *pointer_to_object( struct pso_pointer pointer ) {
|
struct pso2 *pointer_to_object( struct pso_pointer p ) {
|
||||||
struct pso2 *result = NULL;
|
struct pso2 *result = NULL;
|
||||||
|
|
||||||
if ( pointer.node == node_index ) {
|
if ( p.node == node_index ) {
|
||||||
if (pointer.page < get_pages_allocated() && pointer.offset < (PAGE_BYTES / 8)) {
|
if (p.page < get_pages_allocated() && p.offset < (PAGE_BYTES / 8)) {
|
||||||
// TODO: that's not really a safe test of whether this is a valid pointer.
|
// TODO: that's not really a safe test of whether this is a valid pointer.
|
||||||
union page *pg = pages[pointer.page];
|
union page *pg = pages[p.page];
|
||||||
result = ( struct pso2 * ) &pg->words[pointer.offset];
|
result = ( struct pso2 * ) &pg->words[p.offset];
|
||||||
} else {
|
|
||||||
// TODO: throw bad pointer exception.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: else if we have a copy of the object in cache, return that;
|
// TODO: else if we have a copy of the object in cache, return that;
|
||||||
|
|
@ -54,3 +65,51 @@ struct pso2 *pointer_to_object( struct pso_pointer pointer ) {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the memory address of the object indicated by this pointer
|
||||||
|
* `p`, if it is of this `size_class`.
|
||||||
|
*
|
||||||
|
* NOTE THAT: It's impossible, with our calling conventions, to pass an
|
||||||
|
* exception back from this function. Consequently, if anything goes wrong
|
||||||
|
* we return NULL. The caller *should* check for that and throw an exception.
|
||||||
|
*
|
||||||
|
* NOTE THAT: The return signature of these functions is pso2, because it is
|
||||||
|
* safe to cast any paged space object to a pso2, but safe to cast an object
|
||||||
|
* of a smaller size class to a larger one. You should check that the object
|
||||||
|
* returned has the size class you expect.
|
||||||
|
*
|
||||||
|
* @param p a pointer to an object;
|
||||||
|
* @param size_class a size class.
|
||||||
|
*
|
||||||
|
* @return the memory address of the object, provided it is a valid object and
|
||||||
|
* of the specified size class, else NULL.
|
||||||
|
*/
|
||||||
|
struct pso2 * pointer_to_object_of_size_class( struct pso_pointer p, uint8_t size_class) {
|
||||||
|
struct pso2 * result = pointer_to_object( p);
|
||||||
|
|
||||||
|
if (result->header.tag.bytes.size_class != size_class) {
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the memory address of the object indicated by this pointer
|
||||||
|
* `p`, if it has this `tag_value`.
|
||||||
|
*
|
||||||
|
* NOTE THAT: It's impossible, with our calling conventions, to pass an
|
||||||
|
* exception back from this function. Consequently, if anything goes wrong
|
||||||
|
* we return NULL. The caller *should* check for that and throw an exception.
|
||||||
|
*/
|
||||||
|
struct pso2 * pointer_to_object_with_tag_value( struct pso_pointer p, uint32_t tag_value) {
|
||||||
|
struct pso2 * result = pointer_to_object( p);
|
||||||
|
|
||||||
|
if ((result->header.tag.value & 0xffffff) != tag_value) {
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,4 +43,8 @@ struct pso_pointer make_pointer( uint32_t node, uint16_t page, uint16_t offset);
|
||||||
|
|
||||||
struct pso2* pointer_to_object( struct pso_pointer pointer);
|
struct pso2* pointer_to_object( struct pso_pointer pointer);
|
||||||
|
|
||||||
|
struct pso2 * pointer_to_object_of_size_class( struct pso_pointer p, uint8_t size_class);
|
||||||
|
|
||||||
|
struct pso2 * pointer_to_object_with_tag_value( struct pso_pointer p, uint32_t tag_value);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "memory/destroy.h"
|
||||||
#include "memory/header.h"
|
#include "memory/header.h"
|
||||||
#include "memory/memory.h"
|
#include "memory/memory.h"
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
|
|
@ -74,24 +75,6 @@ uint32_t payload_size( struct pso2 *object ) {
|
||||||
sizeof( struct pso_header ) );
|
sizeof( struct pso_header ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_cell( struct pso_pointer p ) {
|
|
||||||
struct pso2 *p2 = pointer_to_object( p );
|
|
||||||
uint32_t array_size = payload_size( p2 );
|
|
||||||
uint8_t size_class = p2->header.tag.bytes.size_class;
|
|
||||||
|
|
||||||
strncpy( ( char * ) ( p2->header.tag.bytes.mnemonic ), FREETAG,
|
|
||||||
TAGLENGTH );
|
|
||||||
|
|
||||||
/* will C just let me cheerfully walk off the end of the array I've declared? */
|
|
||||||
for ( int i = 0; i < array_size; i++ ) {
|
|
||||||
p2->payload.words[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: obtain mutex on freelist */
|
|
||||||
p2->payload.free.next = freelists[size_class];
|
|
||||||
freelists[size_class] = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* increment the reference count of the object at this cons pointer.
|
* increment the reference count of the object at this cons pointer.
|
||||||
*
|
*
|
||||||
|
|
@ -153,7 +136,7 @@ struct pso_pointer dec_ref( struct pso_pointer pointer ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( object->header.count == 0 ) {
|
if ( object->header.count == 0 ) {
|
||||||
free_cell( pointer );
|
free_object( pointer );
|
||||||
pointer = nil;
|
pointer = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -165,11 +148,46 @@ struct pso_pointer dec_ref( struct pso_pointer pointer ) {
|
||||||
* @brief Prevent an object ever being dereferenced.
|
* @brief Prevent an object ever being dereferenced.
|
||||||
*
|
*
|
||||||
* @param pointer pointer to an object to lock.
|
* @param pointer pointer to an object to lock.
|
||||||
|
*
|
||||||
|
* @return the `pointer`
|
||||||
*/
|
*/
|
||||||
void lock_object( struct pso_pointer pointer ) {
|
struct pso_pointer lock_object( struct pso_pointer pointer ) {
|
||||||
struct pso2 *object = pointer_to_object( pointer );
|
struct pso2 *object = pointer_to_object( pointer );
|
||||||
|
|
||||||
object->header.count = MAXREFERENCE;
|
object->header.count = MAXREFERENCE;
|
||||||
|
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief decrement all pointers pointed to by the object at this pointer;
|
||||||
|
* clear its memory, and return it to the freelist.
|
||||||
|
*/
|
||||||
|
struct pso_pointer free_object( struct pso_pointer p ) {
|
||||||
|
struct pso_pointer result = nil;
|
||||||
|
struct pso2 *obj = pointer_to_object( p );
|
||||||
|
uint32_t array_size = payload_size( obj );
|
||||||
|
uint8_t size_class = obj->header.tag.bytes.size_class;
|
||||||
|
|
||||||
|
result = destroy( p);
|
||||||
|
|
||||||
|
/* will C just let me cheerfully walk off the end of the array I've declared? */
|
||||||
|
for ( int i = 0; i < array_size; i++ ) {
|
||||||
|
obj->payload.words[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
strncpy( ( char * ) ( obj->header.tag.bytes.mnemonic ), FREETAG,
|
||||||
|
TAGLENGTH );
|
||||||
|
#ifdef DEBUG
|
||||||
|
debug_printf( DEBUG_ALLOC, 0, L"Freeing object of size class %d at {%d, %d, %d}",
|
||||||
|
size_class, p.node, p.page, p.offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TODO: obtain mutex on freelist */
|
||||||
|
obj->payload.free.next = freelists[size_class];
|
||||||
|
freelists[size_class] = p;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,234 +14,6 @@
|
||||||
|
|
||||||
#include "memory/header.h"
|
#include "memory/header.h"
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
// #include "payloads/cons.h"
|
|
||||||
// #include "payloads/exception.h"
|
|
||||||
// #include "payloads/free.h"
|
|
||||||
// #include "payloads/function.h"
|
|
||||||
// #include "payloads/hashtable.h"
|
|
||||||
// #include "payloads/integer.h"
|
|
||||||
// #include "payloads/keyword.h"
|
|
||||||
// #include "payloads/lambda.h"
|
|
||||||
// #include "payloads/mutex.h"
|
|
||||||
// #include "payloads/namespace.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 bytes[16];
|
|
||||||
// uint64_t words[2];
|
|
||||||
// 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 bytes[48];
|
|
||||||
// uint64_t words[6];
|
|
||||||
// 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 bytes[112];
|
|
||||||
// uint64_t words[14];
|
|
||||||
// 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 bytes[240];
|
|
||||||
// uint64_t words[30];
|
|
||||||
// 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 bytes[496];
|
|
||||||
// uint64_t words[62];
|
|
||||||
// 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 bytes[1008];
|
|
||||||
// uint64_t words[126];
|
|
||||||
// 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 bytes[2032];
|
|
||||||
// uint64_t words[254];
|
|
||||||
// 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 bytes[4080];
|
|
||||||
// uint64_t words[510];
|
|
||||||
// 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 bytes[8176];
|
|
||||||
// uint64_t words[1022];
|
|
||||||
// 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 bytes[16368];
|
|
||||||
// uint64_t words[2046];
|
|
||||||
// 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 bytes[32752];
|
|
||||||
// uint64_t words[4094];
|
|
||||||
// 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 bytes[65520];
|
|
||||||
// uint64_t words[8190];
|
|
||||||
// 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 bytes[131056];
|
|
||||||
// uint64_t words[16382];
|
|
||||||
// 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 bytes[262128];
|
|
||||||
// uint64_t words[32766];
|
|
||||||
// struct free_payload free;
|
|
||||||
// } payload;
|
|
||||||
// };
|
|
||||||
|
|
||||||
struct pso_pointer allocate( char* tag, uint8_t size_class);
|
struct pso_pointer allocate( char* tag, uint8_t size_class);
|
||||||
|
|
||||||
|
|
@ -249,8 +21,8 @@ struct pso_pointer dec_ref( struct pso_pointer pointer );
|
||||||
|
|
||||||
struct pso_pointer inc_ref( struct pso_pointer pointer );
|
struct pso_pointer inc_ref( struct pso_pointer pointer );
|
||||||
|
|
||||||
void lock_object( struct pso_pointer pointer);
|
struct pso_pointer lock_object( struct pso_pointer pointer);
|
||||||
|
|
||||||
// uint32_t get_tag_value( struct pso_pointer pointer);
|
struct pso_pointer free_object( struct pso_pointer p );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
17
src/c/memory/pso4.c
Normal file
17
src/c/memory/pso4.c
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/pso4.h"
|
||||||
|
|
||||||
|
struct pso4* pointer_to_pso4( struct pso_pointer p) {
|
||||||
|
struct pso4* result = (struct pso4*)pointer_to_object_of_size_class( p, 4);
|
||||||
|
}
|
||||||
|
|
@ -31,4 +31,6 @@ struct pso4 {
|
||||||
} payload;
|
} payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso4* pointer_to_pso4( struct pso_pointer p);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ bool check_tag( struct pso_pointer p, uint32_t v);
|
||||||
|
|
||||||
bool check_type( struct pso_pointer p, char* s);
|
bool check_type( struct pso_pointer p, char* s);
|
||||||
|
|
||||||
|
#define characterp(p) (check_tag(p, CHARACTERTV))
|
||||||
#define consp(p) (check_tag(p, CONSTV))
|
#define consp(p) (check_tag(p, CONSTV))
|
||||||
#define exceptionp(p) (check_tag(p, EXCEPTIONTV))
|
#define exceptionp(p) (check_tag(p, EXCEPTIONTV))
|
||||||
#define freep(p) (check_tag(p, FREETV))
|
#define freep(p) (check_tag(p, FREETV))
|
||||||
|
|
@ -116,6 +117,7 @@ bool check_type( struct pso_pointer p, char* s);
|
||||||
#define realp(p) (check_tag(p,REALTV))
|
#define realp(p) (check_tag(p,REALTV))
|
||||||
#define sequencep(p) (check_tag(p,CONSTV)||check_tag(p,STRINGTV)||check_tag(p,SYMBOLTV))
|
#define sequencep(p) (check_tag(p,CONSTV)||check_tag(p,STRINGTV)||check_tag(p,SYMBOLTV))
|
||||||
#define specialp(p) (check_tag(p,SPECIALTV))
|
#define specialp(p) (check_tag(p,SPECIALTV))
|
||||||
|
#define stackp(p) (check_tag(p, STACKTV))
|
||||||
#define streamp(p) (check_tag(p,READTV)||check_tag(p,WRITETV))
|
#define streamp(p) (check_tag(p,READTV)||check_tag(p,WRITETV))
|
||||||
#define stringp(p) (check_tag(p,STRINGTV))
|
#define stringp(p) (check_tag(p,STRINGTV))
|
||||||
#define symbolp(p) (check_tag(p,SYMBOLTV))
|
#define symbolp(p) (check_tag(p,SYMBOLTV))
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,20 @@ bool equal( struct pso_pointer a, struct pso_pointer b) {
|
||||||
if ( eq( a, b)) {
|
if ( eq( a, b)) {
|
||||||
result = true;
|
result = true;
|
||||||
} else if ( get_tag_value(a) == get_tag_value(b)) {
|
} else if ( get_tag_value(a) == get_tag_value(b)) {
|
||||||
|
struct pso2 *oa = pointer_to_object(a);
|
||||||
|
struct pso2 *ob = pointer_to_object(b);
|
||||||
|
|
||||||
switch ( get_tag_value(a)) {
|
switch ( get_tag_value(a)) {
|
||||||
|
case CHARACTERTV :
|
||||||
|
result = (oa->payload.character.character == ob->payload.character.character);
|
||||||
|
break;
|
||||||
case CONSTV :
|
case CONSTV :
|
||||||
result = (equal( car(a), car(b)) && equal( cdr(a), cdr(b)));
|
result = (equal( car(a), car(b)) && equal( cdr(a), cdr(b)));
|
||||||
break;
|
break;
|
||||||
case INTEGERTV :
|
case INTEGERTV :
|
||||||
result = (pointer_to_object(a)->payload.integer.value ==
|
result = (oa->payload.integer.value
|
||||||
pointer_to_object(b)->payload.integer.value);
|
==
|
||||||
|
ob->payload.integer.value);
|
||||||
break;
|
break;
|
||||||
case KEYTV:
|
case KEYTV:
|
||||||
case STRINGTV :
|
case STRINGTV :
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,16 @@
|
||||||
#include "ops/string_ops.h"
|
#include "ops/string_ops.h"
|
||||||
#include "ops/truth.h"
|
#include "ops/truth.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief reverse a sequence.
|
||||||
|
*
|
||||||
|
* A sequence is a list or a string-like-thing. A dotted pair is not a
|
||||||
|
* sequence.
|
||||||
|
*
|
||||||
|
* @param sequence a pointer to a sequence.
|
||||||
|
* @return a sequence like the `sequence` passed, but reversed; or `nil` if
|
||||||
|
* the argument was not a sequence.
|
||||||
|
*/
|
||||||
struct pso_pointer reverse( struct pso_pointer sequence) {
|
struct pso_pointer reverse( struct pso_pointer sequence) {
|
||||||
struct pso_pointer result = nil;
|
struct pso_pointer result = nil;
|
||||||
|
|
||||||
|
|
|
||||||
34
src/c/payloads/character.c
Normal file
34
src/c/payloads/character.c
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* payloads/character.c
|
||||||
|
*
|
||||||
|
* A character object.
|
||||||
|
*
|
||||||
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wide characters
|
||||||
|
*/
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
#include "memory/node.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
|
#include "ops/truth.h"
|
||||||
|
|
||||||
|
#include "payloads/character.h"
|
||||||
|
|
||||||
|
struct pso_pointer make_character( wint_t c) {
|
||||||
|
struct pso_pointer result = allocate( CHARACTERTAG, 2 );
|
||||||
|
|
||||||
|
if (!nilp(result)) {
|
||||||
|
pointer_to_object(result)->payload.character.character = (wchar_t) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -36,4 +36,5 @@ struct character_payload {
|
||||||
wchar_t character;
|
wchar_t character;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso_pointer make_character( wint_t c);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
#include "memory/pso.h"
|
#include "memory/pso.h"
|
||||||
#include "memory/pso2.h"
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/pso4.h"
|
||||||
#include "memory/tags.h"
|
#include "memory/tags.h"
|
||||||
|
|
||||||
#include "payloads/cons.h"
|
#include "payloads/cons.h"
|
||||||
|
|
@ -89,3 +90,19 @@ struct pso_pointer cdr( struct pso_pointer p ) {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief When a cons cell is freed, its car and cdr pointers must be
|
||||||
|
* decremented.
|
||||||
|
*
|
||||||
|
* Lisp calling conventions; one expected arg, the pointer to the cell to
|
||||||
|
* be destroyed.
|
||||||
|
*/
|
||||||
|
struct pso_pointer destroy_cons( struct pso_pointer fp, struct pso_pointer env) {
|
||||||
|
if (stackp(fp)) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( fp);
|
||||||
|
struct pso_pointer p = frame->payload.stack_frame.arg[0];
|
||||||
|
dec_ref( car( p));
|
||||||
|
dec_ref( cdr( p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,6 @@ struct pso_pointer cdr( struct pso_pointer cons );
|
||||||
|
|
||||||
struct pso_pointer cons( struct pso_pointer car, struct pso_pointer cdr );
|
struct pso_pointer cons( struct pso_pointer car, struct pso_pointer cdr );
|
||||||
|
|
||||||
bool consp( struct pso_pointer ptr );
|
struct pso_pointer destroy_cons( struct pso_pointer fp, struct pso_pointer env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,31 @@
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
#include "memory/pso.h"
|
#include "memory/pso.h"
|
||||||
|
#include "memory/pso4.h"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
#include "payloads/exception.h"
|
#include "payloads/exception.h"
|
||||||
|
|
||||||
struct pso_pointer make_exception( struct pso_pointer message, struct pso_pointer frame_pointer, struct pso_pointer cause) {
|
struct pso_pointer make_exception( struct pso_pointer message,
|
||||||
|
struct pso_pointer frame_pointer, struct pso_pointer cause) {
|
||||||
// TODO: not yet implemented
|
// TODO: not yet implemented
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief When an exception is freed, all its pointers must be decremented.
|
||||||
|
*
|
||||||
|
* Lisp calling conventions; one expected arg, the pointer to the object to
|
||||||
|
* be destroyed.
|
||||||
|
*/
|
||||||
|
struct pso_pointer destroy_exception( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env) {
|
||||||
|
if (stackp(fp)) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( fp);
|
||||||
|
struct pso_pointer p = frame->payload.stack_frame.arg[0];
|
||||||
|
|
||||||
|
// TODO: decrement every pointer indicated by an exception.
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,7 @@ struct exception_payload {
|
||||||
struct pso_pointer make_exception( struct pso_pointer message,
|
struct pso_pointer make_exception( struct pso_pointer message,
|
||||||
struct pso_pointer frame_pointer, struct pso_pointer cause);
|
struct pso_pointer frame_pointer, struct pso_pointer cause);
|
||||||
|
|
||||||
|
struct pso_pointer destroy_exception( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,28 @@
|
||||||
|
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
#include "memory/pso2.h"
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/pso4.h"
|
||||||
#include "memory/tags.h"
|
#include "memory/tags.h"
|
||||||
|
|
||||||
#include "ops/string_ops.h"
|
#include "ops/string_ops.h"
|
||||||
#include "ops/truth.h"
|
#include "ops/truth.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief When an string is freed, its cdr pointer must be decremented.
|
||||||
|
*
|
||||||
|
* Lisp calling conventions; one expected arg, the pointer to the object to
|
||||||
|
* be destroyed.
|
||||||
|
*/
|
||||||
|
struct pso_pointer destroy_string( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env) {
|
||||||
|
if (stackp(fp)) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( fp);
|
||||||
|
struct pso_pointer p = frame->payload.stack_frame.arg[0];
|
||||||
|
|
||||||
|
dec_ref( cdr(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,4 +35,7 @@ struct string_payload {
|
||||||
|
|
||||||
struct pso_pointer make_string( wint_t c, struct pso_pointer tail );
|
struct pso_pointer make_string( wint_t c, struct pso_pointer tail );
|
||||||
|
|
||||||
|
struct pso_pointer destroy_string( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
|
|
||||||
#include "io/fopen.h"
|
#include "io/fopen.h"
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/pso.h"
|
||||||
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
struct pso_pointer make_read_stream( URL_FILE *input,
|
struct pso_pointer make_read_stream( URL_FILE *input,
|
||||||
struct pso_pointer metadata ) {
|
struct pso_pointer metadata ) {
|
||||||
struct pso_pointer pointer = allocate( READTV, 2);
|
struct pso_pointer pointer = allocate( READTAG, 2);
|
||||||
struct pso2 *cell = pointer_to_object( pointer );
|
struct pso2 *cell = pointer_to_object( pointer );
|
||||||
|
|
||||||
cell->payload.stream.stream = input;
|
cell->payload.stream.stream = input;
|
||||||
|
|
|
||||||
|
|
@ -29,4 +29,7 @@ struct stream_payload {
|
||||||
struct pso_pointer meta;
|
struct pso_pointer meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso_pointer make_read_stream( URL_FILE *input,
|
||||||
|
struct pso_pointer metadata );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ struct pso_pointer make_frame( struct pso_pointer previous, ...) {
|
||||||
for ( ; cursor < count && cursor < args_in_frame; cursor++) {
|
for ( ; cursor < count && cursor < args_in_frame; cursor++) {
|
||||||
struct pso_pointer argument = va_arg( args, struct pso_pointer);
|
struct pso_pointer argument = va_arg( args, struct pso_pointer);
|
||||||
|
|
||||||
frame->payload.stack_frame.arg[cursor] = argument;
|
frame->payload.stack_frame.arg[cursor] = inc_ref( argument);
|
||||||
}
|
}
|
||||||
if ( cursor < count) {
|
if ( cursor < count) {
|
||||||
struct pso_pointer more_args = nil;
|
struct pso_pointer more_args = nil;
|
||||||
|
|
@ -64,3 +64,31 @@ struct pso_pointer make_frame( struct pso_pointer previous, ...) {
|
||||||
|
|
||||||
return frame_pointer;
|
return frame_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief When a stack frame is freed, all its pointers must be decremented.
|
||||||
|
*
|
||||||
|
* Lisp calling conventions; one expected arg, the pointer to the object to
|
||||||
|
* be destroyed.
|
||||||
|
*/
|
||||||
|
struct pso_pointer destroy_stack_frame( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env) {
|
||||||
|
if (stackp(fp)) {
|
||||||
|
struct pso4 *frame = pointer_to_pso4( fp);
|
||||||
|
struct pso4 * casualty =
|
||||||
|
pointer_to_pso4( frame->payload.stack_frame.arg[0]);
|
||||||
|
|
||||||
|
dec_ref( casualty->payload.stack_frame.previous);
|
||||||
|
dec_ref( casualty->payload.stack_frame.function);
|
||||||
|
dec_ref( casualty->payload.stack_frame.more);
|
||||||
|
|
||||||
|
for (int i = 0; i < args_in_frame; i++) {
|
||||||
|
dec_ref( casualty->payload.stack_frame.arg[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
casualty->payload.stack_frame.args = 0;
|
||||||
|
casualty->payload.stack_frame.depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,7 @@ struct stack_frame_payload {
|
||||||
|
|
||||||
struct pso_pointer make_frame( struct pso_pointer previous, ...);
|
struct pso_pointer make_frame( struct pso_pointer previous, ...);
|
||||||
|
|
||||||
|
struct pso_pointer destroy_stack_frame( struct pso_pointer fp,
|
||||||
|
struct pso_pointer env);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
16
src/c/psse.c
16
src/c/psse.c
|
|
@ -13,8 +13,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "psse.h"
|
#include "psse.h"
|
||||||
|
#include "io/io.h"
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
|
|
||||||
#include "ops/stack_ops.h"
|
#include "ops/stack_ops.h"
|
||||||
|
#include "ops/truth.h"
|
||||||
|
|
||||||
void print_banner( ) {
|
void print_banner( ) {
|
||||||
fwprintf( stdout, L"Post-Scarcity Software Environment version %s\n\n",
|
fwprintf( stdout, L"Post-Scarcity Software Environment version %s\n\n",
|
||||||
|
|
@ -63,10 +66,10 @@ int main( int argc, char *argv[] ) {
|
||||||
char *infilename = NULL;
|
char *infilename = NULL;
|
||||||
|
|
||||||
setlocale( LC_ALL, "" );
|
setlocale( LC_ALL, "" );
|
||||||
// if ( io_init( ) != 0 ) {
|
if ( initialise_io( ) != 0 ) {
|
||||||
// fputs( "Failed to initialise I/O subsystem\n", stderr );
|
fputs( "Failed to initialise I/O subsystem\n", stderr );
|
||||||
// exit( 1 );
|
exit( 1 );
|
||||||
// }
|
}
|
||||||
|
|
||||||
while ( ( option = getopt( argc, argv, "dhi:ps:v:" ) ) != -1 ) {
|
while ( ( option = getopt( argc, argv, "dhi:ps:v:" ) ) != -1 ) {
|
||||||
switch ( option ) {
|
switch ( option ) {
|
||||||
|
|
@ -98,7 +101,10 @@ int main( int argc, char *argv[] ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initialise_node( 0 );
|
if ( nilp( initialise_node( 0 ))) {
|
||||||
|
fputs( "Failed to initialise node\n", stderr );
|
||||||
|
exit( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
// repl( );
|
// repl( );
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue