Still doesn't compile, but I think excellent progress.
This commit is contained in:
parent
dbeb99759a
commit
aac4669a3d
34 changed files with 1128 additions and 673 deletions
|
|
@ -1,5 +1,13 @@
|
|||
# State of Play
|
||||
|
||||
## 20260427
|
||||
|
||||
### eval/apply, yet again
|
||||
|
||||
OK, OK. So the version of `eval`/`apply` written in C is the `:bootstrap` version — which is to say, sufficient to get Lisp bootstrapped, and to run the compiler. One or both can then be replaced by new implementations written in Lisp, to provide the `:system` versions. And any user should in principle be able to override the system versions with their own versions (although troubling worries about security come into that).
|
||||
|
||||
So yesterday, I decided to copy the versions of `eval` and `apply` from `0.0.6` (which, after all, do work — there are lots of problems with the `0.0.6` prototype, but the interpreter is not one of them) into `0.1.0`. But then last night I read the chapter in Cees de Groot's [The Genius of Lisp](https://cdegroot.com/programming/lisp/2026/02/17/why-i-wrote-the-genius-of-lisp.html) and I'm back to wanting to reimplement them *yet again*. I'm not sure that this is wise.
|
||||
|
||||
## 20260424
|
||||
|
||||
### To have `c_` functions or not to have `c_` functions, revisited
|
||||
|
|
|
|||
|
|
@ -97,6 +97,11 @@
|
|||
*/
|
||||
#define DEBUG_EQUAL 512
|
||||
|
||||
/**
|
||||
* @brief sum of all previous DEBUG_ values.
|
||||
*/
|
||||
#define DEBUG_ANY 1023
|
||||
|
||||
/**
|
||||
* @brief Verbosity (and content) of debugging output
|
||||
*
|
||||
|
|
|
|||
43
src/c/environment/privileged_keywords.c
Normal file
43
src/c/environment/privileged_keywords.c
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* privileged_keywords.c
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* Keywords essential to the operation of the system. I'm not certain that
|
||||
* there's any necessity to have privileged keywords, but as these are
|
||||
* keywords that will be used exceedingly frequently, we might as well
|
||||
* make them cheap to access.
|
||||
*
|
||||
* Copyright (c): 27 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include "environment/privileged_keywords.h"
|
||||
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
|
||||
#include "memory/pso.h"
|
||||
#include "payloads/cons.h"
|
||||
|
||||
#include "ops/string_ops.h"
|
||||
|
||||
|
||||
/**
|
||||
* location metadata for exceptions (and possibly location in other contexts).
|
||||
*/
|
||||
struct pso_pointer privileged_keyword_location;
|
||||
|
||||
/**
|
||||
* name metadata for compiled functions.
|
||||
*/
|
||||
struct pso_pointer privileged_keyword_name;
|
||||
|
||||
|
||||
#define load_and_lock(var,val)var = lock_object(c_string_to_lisp_keyword(nil, val))
|
||||
|
||||
|
||||
struct pso_pointer initialise_privileged_keywords( struct pso_pointer env){
|
||||
load_and_lock(privileged_keyword_location, PK_LOCATION);
|
||||
load_and_lock( privileged_keyword_name, PK_NAME);
|
||||
}
|
||||
23
src/c/environment/privileged_keywords.h
Normal file
23
src/c/environment/privileged_keywords.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* privileged_keywords.h
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* TODO: Edit purpose.
|
||||
*
|
||||
* Copyright (c): 27 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
||||
#define SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
||||
|
||||
#define PK_LOCATION U"location"
|
||||
#define PK_NAME = U"name"
|
||||
|
||||
#include "memory/pointer.h"
|
||||
extern struct pso_pointer privileged_keyword_location;
|
||||
extern struct pso_pointer privileged_keyword_name;
|
||||
|
||||
struct pso_pointer initialise_privileged_keywords( struct pso_pointer env);
|
||||
#endif /* SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_ */
|
||||
|
|
@ -135,6 +135,11 @@ bool check_type( struct pso_pointer p, char *s );
|
|||
// #define truep(p) ( !check_tag(p,NILTV))
|
||||
#define vectorpointp(p) (check_tag(p,VECTORPOINTTV))
|
||||
#define vectorp(p) (check_tag(p,VECTORTV))
|
||||
#define writep(p) (check_tag(p,WRITETV))
|
||||
#define writep(p) (check_tag(p, WRITETV))
|
||||
|
||||
/** a sequence is an object having a list structure with the pointer to the
|
||||
* remainder in the fourth word of each cell. I.e., cons, string, symbol,
|
||||
* keyword, possibly some others */
|
||||
#define sequencep(p)(consp(p) || keywordp(p) || stringp(p) || symbolp(p))
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,3 +35,4 @@ struct pso_pointer lisp_bind( struct pso_pointer frame_pointer ) {
|
|||
|
||||
return cons( make_frame( 2, frame_pointer, binding, store ) );
|
||||
}
|
||||
|
||||
|
|
|
|||
114
src/c/ops/cond.c
Normal file
114
src/c/ops/cond.c
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
|
||||
/**
|
||||
* @brief evaluate a single cond clause; if the test part succeeds return a
|
||||
* pair whose car is t and whose cdr is the value of the action part
|
||||
*/
|
||||
#include "debug.h"
|
||||
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso2.h"
|
||||
#include "memory/tags.h"
|
||||
|
||||
#include "ops/progn.h"
|
||||
#include "ops/stack_ops.h"
|
||||
#include "ops/truth.h"
|
||||
|
||||
#include "payloads/cons.h"
|
||||
#include "payloads/exception.h"
|
||||
|
||||
/**
|
||||
* if the car of a consp evaluates to non-nil, the clause succeeded and the
|
||||
* cond expression must conclude, even if the result of the clause is nil.
|
||||
*
|
||||
* Therefore this funtion will
|
||||
* @return nil if the test failed;
|
||||
* @return a pair `(t . <value>)` if the test succeeded.
|
||||
*/
|
||||
struct pso_pointer eval_cond_clause( struct pso_pointer clause,
|
||||
struct pso4 *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = nil;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug_print( L"\n\tCond clause: ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL);
|
||||
#endif
|
||||
|
||||
if ( consp( clause ) ) {
|
||||
struct pso_pointer val =
|
||||
eval_form( frame, frame_pointer, c_car( clause ),
|
||||
env );
|
||||
|
||||
if ( !c_nilp( val ) ) {
|
||||
result =
|
||||
cons( t,
|
||||
c_progn( frame, frame_pointer, c_cdr( clause ), env ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
debug_print( L"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||
debug_print( L" succeeded; returning: ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL);
|
||||
} else {
|
||||
debug_print( L"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||
debug_print( L" failed.\n", DEBUG_EVAL, 0 );
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
result = throw_exception( c_string_to_lisp_symbol( frame_pointer, L"cond" ),
|
||||
c_string_to_lisp_string
|
||||
(frame_pointer, L"Arguments to `cond` must be lists" ),
|
||||
frame_pointer );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special form: conditional. Each `clause` is expected to be a list; if the first
|
||||
* item in such a list evaluates to non-nil, the remaining items in that list
|
||||
* are evaluated in turn and the value of the last returned. If no arg `clause`
|
||||
* has a first element which evaluates to non nil, then nil is returned.
|
||||
*
|
||||
* * (cond clauses...)
|
||||
*
|
||||
* @param frame my stack frame.
|
||||
* @param frame_pointer a pointer to my pso4.
|
||||
* @param env the environment in which arguments will be evaluated.
|
||||
* @return the value of the last expression of the first successful `clause`.
|
||||
*/
|
||||
struct pso_pointer
|
||||
lisp_cond( struct pso4 *frame, struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = nil;
|
||||
bool done = false;
|
||||
|
||||
for ( int i = 0; ( i < frame->payload.stack_frame.args ) && !done; i++ ) {
|
||||
struct pso_pointer clause_pointer = fetch_arg( frame, i );
|
||||
|
||||
// TODO: WHOOPS! This isn't right. If the test of a cond clause
|
||||
// evaluates to non-nil, but the last form of the clause evaluates
|
||||
// to nil, the form still succeeded and we should still exit `cond`.
|
||||
//
|
||||
|
||||
result = eval_cond_clause( clause_pointer, frame, frame_pointer, env );
|
||||
|
||||
if ( !c_nilp( result ) && c_truep( c_car( result ) ) ) {
|
||||
result = c_cdr( result );
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
debug_print( L"\tCond returning: ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
140
src/c/ops/dump.c
Normal file
140
src/c/ops/dump.c
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* dump.c
|
||||
*
|
||||
* Dump representations of both cons space and vector space objects.
|
||||
*
|
||||
*
|
||||
* (c) 2018 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/pso2.h"
|
||||
#include "memory/tags.h"
|
||||
#include "io/print.h"
|
||||
|
||||
#include "payloads/lambda.h"
|
||||
|
||||
|
||||
void dump_string_cell( URL_FILE *output, wchar_t *prefix,
|
||||
struct pso_pointer pointer ) {
|
||||
struct pso2 *cell = pointer_to_object( pointer );
|
||||
if ( cell->payload.string.character == 0 ) {
|
||||
url_fwprintf( output,
|
||||
L"\t\t%ls cell: termination; next at page %d offset %d, count %u\n",
|
||||
prefix,
|
||||
cell->payload.string.cdr.page,
|
||||
cell->payload.string.cdr.offset, cell->header.count );
|
||||
} else {
|
||||
url_fwprintf( output,
|
||||
L"\t\t%ls cell: character '%lc' (%d) with hash %d; next at page %d offset %d, count %u\n",
|
||||
prefix,
|
||||
( wint_t ) cell->payload.string.character,
|
||||
cell->payload.string.character,
|
||||
cell->payload.string.hash,
|
||||
cell->payload.string.cdr.page,
|
||||
cell->payload.string.cdr.offset, cell->header.count );
|
||||
url_fwprintf( output, L"\t\t value: " );
|
||||
print( output, pointer );
|
||||
url_fwprintf( output, L"\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dump the object at this pso_pointer to this output stream.
|
||||
*/
|
||||
void dump_object( URL_FILE *output, struct pso_pointer pointer ) {
|
||||
struct pso2 *cell = pointer_to_object( pointer );
|
||||
url_fwprintf( output, L"\t%3.3s (%d) at page %d, offset %d count %u\n",
|
||||
cell->header.tag.bytes.mnemonic[0], get_tag_value( pointer ),
|
||||
pointer.page, pointer.offset, cell->header.count );
|
||||
|
||||
switch ( get_tag_value( pointer ) ) {
|
||||
case CONSTV:
|
||||
url_fwprintf( output,
|
||||
L"\t\tCons cell: car at page %d offset %d, cdr at page %d "
|
||||
L"offset %d, count %u :",
|
||||
cell->payload.cons.car.page,
|
||||
cell->payload.cons.car.offset,
|
||||
cell->payload.cons.cdr.page,
|
||||
cell->payload.cons.cdr.offset );
|
||||
print( output, pointer );
|
||||
url_fputws( L"\n", output );
|
||||
break;
|
||||
case EXCEPTIONTV:
|
||||
url_fwprintf( output, L"\t\tException cell: " );
|
||||
dump_stack_trace( output, pointer );
|
||||
break;
|
||||
case FREETV:
|
||||
url_fwprintf( output,
|
||||
L"\t\tFree cell: next at page %d offset %d\n",
|
||||
cell->payload.cons.cdr.page,
|
||||
cell->payload.cons.cdr.offset );
|
||||
break;
|
||||
case HASHTV:
|
||||
dump_map( output, pointer );
|
||||
break;
|
||||
case INTEGERTV:
|
||||
url_fwprintf( output, L"\t\tInteger cell: value %ld, count %u\n",
|
||||
cell->payload.integer.value, cell->header.count );
|
||||
break;
|
||||
case KEYTV:
|
||||
dump_string_cell( output, L"Keyword", pointer );
|
||||
break;
|
||||
case LAMBDATV:
|
||||
url_fwprintf( output, L"\t\t\u03bb cell;\n\t\t args: " );
|
||||
print( output, cell->payload.lambda.args );
|
||||
url_fwprintf( output, L";\n\t\t\tbody: " );
|
||||
print( output, cell->payload.lambda.body );
|
||||
url_fputws( L"\n", output );
|
||||
break;
|
||||
case NILTV:
|
||||
break;
|
||||
case NLAMBDATV:
|
||||
url_fwprintf( output, L"\t\tn\u03bb cell; \n\t\targs: " );
|
||||
print( output, cell->payload.lambda.args );
|
||||
url_fwprintf( output, L";\n\t\t\tbody: " );
|
||||
print( output, cell->payload.lambda.body );
|
||||
url_fputws( L"\n", output );
|
||||
break;
|
||||
case RATIOTV:
|
||||
url_fwprintf( output,
|
||||
L"\t\tRational cell: value %ld/%ld, count %u\n",
|
||||
pointer_to_object( cell->payload.ratio.
|
||||
dividend ).payload.integer.value,
|
||||
pointer_to_object( cell->payload.ratio.
|
||||
divisor ).payload.integer.value,
|
||||
cell->header.count );
|
||||
break;
|
||||
case READTV:
|
||||
url_fputws( L"\t\tInput stream; metadata: ", output );
|
||||
print( output, cell->payload.stream.meta );
|
||||
url_fputws( L"\n", output );
|
||||
break;
|
||||
case REALTV:
|
||||
url_fwprintf( output, L"\t\tReal cell: value %Lf, count %u\n",
|
||||
cell->payload.real.value, cell->header.count );
|
||||
break;
|
||||
case STACKTV:
|
||||
dump_frame( output, pointer );
|
||||
break;
|
||||
case STRINGTV:
|
||||
dump_string_cell( output, L"String", pointer );
|
||||
break;
|
||||
case SYMBOLTV:
|
||||
dump_string_cell( output, L"Symbol", pointer );
|
||||
break;
|
||||
case TRUETV:
|
||||
break;
|
||||
case WRITETV:
|
||||
url_fputws( L"\t\tOutput stream; metadata: ", output );
|
||||
print( output, cell->payload.stream.meta );
|
||||
url_fputws( L"\n", output );
|
||||
break;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -17,10 +17,10 @@
|
|||
#include "memory/pso4.h"
|
||||
#include "payloads/function.h"
|
||||
|
||||
struct pso_pointer apply( struct pso_pointer frame_pointer );
|
||||
struct pso_pointer lisp_apply( struct pso_pointer frame_pointer );
|
||||
|
||||
|
||||
struct pso_pointer eval( struct pso_pointer frame_pointer );
|
||||
struct pso_pointer lisp_eval( struct pso_pointer frame_pointer );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
64
src/c/ops/inspect.c
Normal file
64
src/c/ops/inspect.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* inspect.c
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* Display the contents of an object; later, in explorable form.
|
||||
*
|
||||
* Copyright (c): 25 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "io/fopen.h"
|
||||
#include "io/io.h"
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso2.h"
|
||||
#include "memory/pso4.h"
|
||||
#include "memory/tags.h"
|
||||
#include "ops/stack_ops.h"
|
||||
|
||||
/**
|
||||
* Function: dump/inspect one complete lisp expression and return nil. If
|
||||
* write-stream is specified and is a write stream, then print to that stream,
|
||||
* else the stream which is the value of
|
||||
* `*out*` in the environment.
|
||||
*
|
||||
* * (inspect expr)
|
||||
* * (inspect expr write-stream)
|
||||
*
|
||||
* TODO: IT OCCURS TO ME that if `inspect` returns a Markdown formatted string
|
||||
* then it will be readable right away, but wrappable in a browser later to
|
||||
* allow interactive exploration.
|
||||
*
|
||||
* @param frame my pso4.
|
||||
* @param frame_pointer a pointer to my pso4.
|
||||
* @param env my environment (from which the stream may be extracted).
|
||||
* @return nil.
|
||||
*/
|
||||
struct pso_pointer lisp_inspect(struct pso_pointer frame_pointer) {
|
||||
debug_print( L"Entering lisp_inspect\n", DEBUG_IO, 0 );
|
||||
struct pso_pointer result = nil;
|
||||
|
||||
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
||||
|
||||
struct pso_pointer out_stream = writep( frame->payload.stack_frame.arg[1] )
|
||||
? frame->payload.stack_frame.arg[1]
|
||||
: get_default_stream( false, fetch_env( frame_pointer ) );
|
||||
URL_FILE *output;
|
||||
|
||||
if ( writep( out_stream ) ) {
|
||||
debug_print( L"lisp_inspect: setting output stream\n", DEBUG_IO, 0 );
|
||||
debug_dump_object( out_stream, DEBUG_IO );
|
||||
output = pointer_to_object( out_stream )->payload.stream.stream;
|
||||
} else {
|
||||
output = file_to_url_file( stderr );
|
||||
}
|
||||
|
||||
dump_object( output, frame->payload.stack_frame.arg[0] );
|
||||
|
||||
debug_print( L"Leaving lisp_inspect", DEBUG_IO, 0 );
|
||||
|
||||
return result;
|
||||
}
|
||||
16
src/c/ops/inspect.h
Normal file
16
src/c/ops/inspect.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* inspect.h
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* Display the contents of an object; later, in explorable form.
|
||||
*
|
||||
* Copyright (c): 25 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef psse_ops_inspect
|
||||
#define psse_ops_inspect
|
||||
|
||||
struct pso_pointer lisp_inspect( struct pso_pointer frame_pointer );
|
||||
#endif
|
||||
49
src/c/ops/keys.c
Normal file
49
src/c/ops/keys.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* ops/keys.c
|
||||
*
|
||||
* Post Scarcity Software Environment: eval and apply.
|
||||
*
|
||||
* keys: return an unsorted list of the keys bound in a store.
|
||||
*
|
||||
* (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/tags.h"
|
||||
#include "ops/truth.h"
|
||||
#include "payloads/cons.h"
|
||||
|
||||
/**
|
||||
* @brief an implementation of `keys` convenient for calling from C
|
||||
*
|
||||
* @param */
|
||||
struct pso_pointer c_keys( struct pso_pointer store ) {
|
||||
struct pso_pointer result = nil;
|
||||
|
||||
if ( consp( store ) ) {
|
||||
for ( struct pso_pointer pair = c_car( store ); !c_nilp( pair );
|
||||
pair = c_car( store ) ) {
|
||||
if ( consp( pair ) ) {
|
||||
result = cons( c_car( pair ), result );
|
||||
// } else if ( hashtabp( pair ) ) {
|
||||
// result = c_append( hashmap_keys( pair ), result );
|
||||
}
|
||||
|
||||
store = c_cdr( store );
|
||||
}
|
||||
// } else if ( hashtabp( store ) ) {
|
||||
// result = hashmap_keys( store );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct pso_pointer lisp_keys( struct pso_pointer frame_pointer) {
|
||||
return c_keys( pointer_to_pso4(frame_pointer)->payload.stack_frame.arg[0] );
|
||||
}
|
||||
|
||||
19
src/c/ops/keys.h
Normal file
19
src/c/ops/keys.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* ops/keys.h
|
||||
*
|
||||
* Post Scarcity Software Environment: keys.
|
||||
*
|
||||
* keys: return an unsorted list of the keys bound in a store.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef psse_ops_keys
|
||||
#define psse_ops_keys
|
||||
|
||||
struct pso_pointer c_keys( struct pso_pointer store );
|
||||
|
||||
struct pso_pointer lisp_keys(struct pso_pointer frame_pointer);
|
||||
|
||||
#endif
|
||||
|
|
@ -13,20 +13,24 @@
|
|||
#include "memory/pso4.h"
|
||||
|
||||
#include "ops/stack_ops.h"
|
||||
|
||||
#include "payloads/cons.h"
|
||||
#include "payloads/integer.h"
|
||||
#include "payloads/stack.h"
|
||||
|
||||
#include "ops/truth.h"
|
||||
|
||||
struct pso_pointer length( struct pso_pointer frame_pointer ) {
|
||||
struct pso_pointer count( struct pso_pointer frame_pointer ) {
|
||||
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
||||
|
||||
struct pso_pointer list = fetch_arg( frame, 0 );
|
||||
int count = 0;
|
||||
int c = 0;
|
||||
|
||||
for ( struct pso_pointer cursor = list; !c_nilp( cursor );
|
||||
cursor = cdr( make_frame( 1, frame_pointer, list ) ) ) {
|
||||
count++;
|
||||
cursor = c_cdr( cursor ) ) {
|
||||
c++;
|
||||
}
|
||||
|
||||
return make_integer( frame_pointer, count );
|
||||
return acquire_integer( frame_pointer, c );
|
||||
}
|
||||
|
||||
|
|
|
|||
62
src/c/ops/mapcar.c
Normal file
62
src/c/ops/mapcar.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* ops/mapcar.c
|
||||
*
|
||||
* Post Scarcity Software Environment: mapcar.
|
||||
*
|
||||
* map a function across a sequence of forms.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso.h"
|
||||
#include "memory/tags.h"
|
||||
#include "ops/reverse.h"
|
||||
#include "ops/truth.h"
|
||||
#include "payloads/cons.h"
|
||||
|
||||
struct pso_pointer lisp_mapcar( struct pso4 *frame,
|
||||
struct pso_pointer frame_pointer,
|
||||
struct pso_pointer env ) {
|
||||
struct pso_pointer result = nil;
|
||||
debug_print( U"Mapcar: ", DEBUG_EVAL, 0 );
|
||||
debug_dump_object( frame_pointer, DEBUG_EVAL, 0 );
|
||||
int i = 0;
|
||||
|
||||
for ( struct pso_pointer c = frame->payload.stack_frame.arg[1]; c_truep( c );
|
||||
c = c_cdr( c ) ) {
|
||||
struct pso_pointer expr =
|
||||
cons( frame->payload.stack_frame.arg[0], cons( c_car( c ), nil ) );
|
||||
|
||||
debug_printf( DEBUG_EVAL, 0, U"Mapcar %d, evaluating ", i );
|
||||
debug_print_object( expr, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL, 0 );
|
||||
|
||||
struct pso_pointer r = eval_form( frame, frame_pointer, expr, env );
|
||||
|
||||
if ( exceptionp( r ) ) {
|
||||
result = r;
|
||||
inc_ref( expr ); // to protect exception from the later dec_ref
|
||||
break;
|
||||
} else {
|
||||
result = cons( r, result );
|
||||
}
|
||||
debug_printf( DEBUG_EVAL, 0, U"Mapcar %d, result is ", i++ );
|
||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL);
|
||||
|
||||
dec_ref( expr );
|
||||
}
|
||||
|
||||
result = consp( result ) ? c_reverse( result ) : result;
|
||||
|
||||
debug_print( U"Mapcar returning: ", DEBUG_EVAL, 0 );
|
||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||
debug_println( DEBUG_EVAL );
|
||||
|
||||
return result;
|
||||
}
|
||||
0
src/c/ops/mapcar.h
Normal file
0
src/c/ops/mapcar.h
Normal file
84
src/c/ops/progn.c
Normal file
84
src/c/ops/progn.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* ops/progn.c
|
||||
*
|
||||
* Post Scarcity Software Environment: progn.
|
||||
*
|
||||
* Evaluate a sequence of expressions and return the value of the last.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso4.h"
|
||||
#include "memory/tags.h"
|
||||
|
||||
#include "ops/eval_apply.h"
|
||||
#include "ops/stack_ops.h"
|
||||
|
||||
#include "payloads/cons.h"
|
||||
#include "payloads/stack.h"
|
||||
|
||||
|
||||
/**
|
||||
* Evaluate each of these expressions in this `env`ironment over this `frame`,
|
||||
* returning only the value of the last.
|
||||
*/
|
||||
struct pso_pointer
|
||||
c_progn( struct pso4 *frame, struct pso_pointer frame_pointer,
|
||||
struct pso_pointer expressions, struct pso_pointer env ) {
|
||||
struct pso_pointer result = nil;
|
||||
struct pso_pointer next_pointer =
|
||||
push_local(frame_pointer, make_frame(1, frame_pointer, nil));
|
||||
struct pso4 *next_frame = pointer_to_pso4(next_pointer);
|
||||
|
||||
while ( consp( expressions ) ) {
|
||||
next_frame->payload.stack_frame.arg[0] = c_car(expressions);
|
||||
|
||||
result = lisp_eval( next_pointer);
|
||||
|
||||
expressions = exceptionp( result ) ? nil : c_cdr( expressions );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special form; evaluate the expressions which are listed in my arguments
|
||||
* sequentially and return the value of the last. This function is called 'do'
|
||||
* in some dialects of Lisp.
|
||||
*
|
||||
* * (progn expressions...)
|
||||
*
|
||||
* @param frame my stack frame.
|
||||
* @param frame_pointer a pointer to my pso4.
|
||||
* @param env the environment in which expressions are evaluated.
|
||||
* @return the value of the last `expression` of the sequence which is my single
|
||||
* argument.
|
||||
*/
|
||||
struct pso_pointer
|
||||
lisp_progn( struct pso_pointer frame_pointer) {
|
||||
struct pso_pointer result = nil;
|
||||
struct pso4 *frame = pointer_to_pso4(frame_pointer);
|
||||
struct pso_pointer next_pointer =
|
||||
push_local(frame_pointer, make_frame(1, frame_pointer, nil));
|
||||
struct pso4 *next_frame = pointer_to_pso4(next_pointer);
|
||||
|
||||
for (int i = 0; i < args_in_frame; i++) {
|
||||
next_frame->payload.stack_frame.arg[0] =
|
||||
frame->payload.stack_frame.arg[i];
|
||||
|
||||
result = push_local(frame_pointer, lisp_eval(next_pointer));
|
||||
}
|
||||
|
||||
if (consp(frame->payload.stack_frame.more)) {
|
||||
result =
|
||||
c_progn(frame, frame_pointer, frame->payload.stack_frame.more, env);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
23
src/c/ops/progn.h
Normal file
23
src/c/ops/progn.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* ops/progn.c
|
||||
*
|
||||
* Post Scarcity Software Environment: progn.
|
||||
*
|
||||
* Evaluate a sequence of expressions and return the value of the last.
|
||||
*
|
||||
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef __psse_ops_progn_h
|
||||
#define __psse_ops_progn_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso4.h"
|
||||
|
||||
struct pso_pointer c_progn(struct pso4 *frame, struct pso_pointer frame_pointer,
|
||||
struct pso_pointer expressions,
|
||||
struct pso_pointer env);
|
||||
|
||||
struct pso_pointer lisp_progn(struct pso_pointer frame_pointer);
|
||||
#endif
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include "ops/truth.h"
|
||||
|
||||
#include "payloads/exception.h"
|
||||
#include "payloads/symbol.h"
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -100,45 +101,6 @@ struct pso_pointer make_string_like_thing( struct pso_pointer frame_pointer,
|
|||
return pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a string from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the string which is being built.
|
||||
*/
|
||||
struct pso_pointer make_string( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, STRINGTAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a keyword from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the keyword which is being built.
|
||||
*/
|
||||
struct pso_pointer make_keyword( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, KEYTAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a symbol from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the symbol which is being built.
|
||||
*/
|
||||
struct pso_pointer make_symbol( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, SYMBOLTAG );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a lisp string representation of this wide character string.
|
||||
|
|
@ -245,3 +207,15 @@ struct pso_pointer c_string_to_lisp_keyword( struct pso_pointer frame_pointer,
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return t if `arg` represents an end of string, else false.
|
||||
* \todo candidate for moving to a memory/string.c file
|
||||
*/
|
||||
bool end_of_stringp( struct pso_pointer arg ) {
|
||||
return c_nilp( arg ) ||
|
||||
( stringp( arg ) &&
|
||||
pointer_to_object( arg )->payload.string.character ==
|
||||
( wint_t ) '\0' );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#ifndef __psse_ops_string_ops_h
|
||||
#define __psse_ops_string_ops_h
|
||||
|
||||
#include <stdbool.h>
|
||||
/*
|
||||
* wide characters
|
||||
*/
|
||||
|
|
@ -21,15 +21,6 @@ struct pso_pointer make_string_like_thing( struct pso_pointer frame_pointer,
|
|||
wint_t c, struct pso_pointer tail,
|
||||
char *tag );
|
||||
|
||||
struct pso_pointer make_string( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
struct pso_pointer make_keyword( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
struct pso_pointer make_symbol( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
struct pso_pointer c_string_to_lisp_string( struct pso_pointer frame_pointer,
|
||||
wchar_t *string );
|
||||
char *lisp_string_to_c_string( struct pso_pointer s );
|
||||
|
|
@ -41,4 +32,6 @@ struct pso_pointer c_string_to_lisp_keyword( struct pso_pointer frame_pointer,
|
|||
struct pso_pointer c_string_to_lisp_symbol( struct pso_pointer frame_pointer,
|
||||
char32_t * symbol );
|
||||
|
||||
bool end_of_stringp(struct pso_pointer arg);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ struct pso_pointer make_cons( struct pso_pointer frame_pointer,
|
|||
*/
|
||||
#define make_cons2(car,cdr) (cons(make_frame(2, frame_pointer, car, cdr)))
|
||||
|
||||
#define c_car(p)(consp(p) ? pointer_to_object(p)->payload.cons.car : nil)
|
||||
#define c_cdr(p)(consp(p) ? pointer_to_object(p)->payload.cons.cdr : nil)
|
||||
#define c_car(p)(sequencep(p) ? pointer_to_object(p)->payload.cons.car : nil)
|
||||
#define c_cdr(p)(sequencep(p) ? pointer_to_object(p)->payload.cons.cdr : nil)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <wctype.h>
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
#include "environment/privileged_keywords.h"
|
||||
#include "memory/node.h"
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/pso.h"
|
||||
|
|
@ -26,6 +28,7 @@
|
|||
|
||||
#include "ops/stack_ops.h"
|
||||
#include "ops/truth.h"
|
||||
#include "payloads/cons.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -92,3 +95,71 @@ struct pso_pointer destroy_exception( struct pso_pointer fp ) {
|
|||
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception with a cause.
|
||||
* `throw_exception` is a misnomer, because it doesn't obey the calling signature of a
|
||||
* lisp function; but it is nevertheless to be preferred to make_exception. A
|
||||
* real `throw_exception`, which does, will be needed.
|
||||
* object pointing to it. Then this should become a normal lisp function
|
||||
* which expects a normally bound frame and environment, such that
|
||||
* frame->payload.stack_frame.arg[0] is the payload, frame->payload.stack_frame.arg[1] is the cause, and frame->payload.stack_frame.arg[2] is the cons-space
|
||||
* pointer to the frame in which the exception occurred.
|
||||
*/
|
||||
struct pso_pointer throw_exception_with_cause( struct pso_pointer location,
|
||||
struct pso_pointer message,
|
||||
struct pso_pointer cause,
|
||||
struct pso_pointer
|
||||
frame_pointer ) {
|
||||
struct pso_pointer result = nil;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug_print( U"\nERROR: `", DEBUG_ANY, 0 );
|
||||
debug_print_object( message, DEBUG_ANY, 0 );
|
||||
debug_print( U"` at `", DEBUG_ANY, 0 );
|
||||
debug_print_object( location, DEBUG_ANY, 0 );
|
||||
debug_print( U"`\n", DEBUG_ANY, 0 );
|
||||
if ( !c_nilp( cause ) ) {
|
||||
debug_print( U"\tCaused by: ", DEBUG_ANY, 0 );
|
||||
debug_print_object( cause, DEBUG_ANY, 0);
|
||||
debug_print( U"`\n", DEBUG_ANY, 0 );
|
||||
}
|
||||
#endif
|
||||
struct pso2 *cell = pointer_to_object( message );
|
||||
|
||||
if (get_tag_value( message)) {
|
||||
result = message;
|
||||
} else {
|
||||
struct pso_pointer x_frame = inc_ref(make_frame(
|
||||
2, frame_pointer, message,
|
||||
(nilp(location)
|
||||
? nil
|
||||
: make_cons(frame_pointer,
|
||||
make_cons(frame_pointer,
|
||||
privileged_keyword_location, location),
|
||||
nil)),
|
||||
cause));
|
||||
|
||||
result = push_local(frame_pointer, make_exception(x_frame));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception.
|
||||
* `throw_exception` is a misnomer, because it doesn't obey the calling signature of a
|
||||
* lisp function; but it is nevertheless to be preferred to make_exception. A
|
||||
* real `throw_exception`, which does, will be needed.
|
||||
* object pointing to it. Then this should become a normal lisp function
|
||||
* which expects a normally bound frame and environment, such that
|
||||
* frame->payload.stack_frame.arg[0] is the payload, frame->payload.stack_frame.arg[1] is the cause, and frame->payload.stack_frame.arg[2] is the cons-space
|
||||
* pointer to the frame in which the exception occurred.
|
||||
*/
|
||||
struct pso_pointer
|
||||
throw_exception( struct pso_pointer location,
|
||||
struct pso_pointer payload,
|
||||
struct pso_pointer frame_pointer ) {
|
||||
return throw_exception_with_cause( location, payload, nil, frame_pointer );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ struct function_payload {
|
|||
*/
|
||||
struct pso_pointer meta;
|
||||
|
||||
#ifdef MANAGED_POINTER_ONLY
|
||||
/**
|
||||
* pointer to a C function which takes a managed pointer to the same stack
|
||||
* frame and a managed pointer to the environment as arguments. Arguments
|
||||
|
|
@ -38,16 +37,6 @@ struct function_payload {
|
|||
* invocation.
|
||||
*/
|
||||
struct pso_pointer ( *executable ) ( struct pso_pointer frame_pointer );
|
||||
#else
|
||||
/**
|
||||
* pointer to a C function which takes an unmanaged pointer to a stack frame,
|
||||
* a managed pointer to the same stack frame, and a managed pointer to the
|
||||
* environment as arguments. Arguments to the Lisp function are assumed to be
|
||||
* loaded into the frame before invocation.
|
||||
*/
|
||||
struct pso_pointer ( *executable ) ( struct pso4 * frame,
|
||||
struct pso_pointer frame_pointer );
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
27
src/c/payloads/keyword.c
Normal file
27
src/c/payloads/keyword.c
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* keyword.c
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* TODO: Edit purpose.
|
||||
*
|
||||
* Copyright (c): 27 Apr 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/tags.h"
|
||||
#include "ops/string_ops.h"
|
||||
|
||||
/**
|
||||
* Construct a keyword from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the keyword which is being built.
|
||||
*/
|
||||
struct pso_pointer make_keyword( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, KEYTAG );
|
||||
}
|
||||
|
|
@ -11,9 +11,13 @@
|
|||
#define __psse_payloads_keyword_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include <wctype.h>
|
||||
|
||||
/* TODO: for now, Keyword shares a payload with String, but this may change.
|
||||
* Strings are of indefinite length, but keywords are really not, and might
|
||||
* fit into any size class. */
|
||||
|
||||
struct pso_pointer make_keyword( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
24
src/c/payloads/lambda.c
Normal file
24
src/c/payloads/lambda.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* lambda.c
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* TODO: Edit purpose.
|
||||
*
|
||||
* Copyright (c): 27 Apr 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"
|
||||
|
||||
struct pso_pointer make_lambda_like_thing(struct pso_pointer frame_pointer,
|
||||
struct pso_pointer args,
|
||||
struct pso_pointer body, char *tag) {
|
||||
|
||||
struct pso_pointer result = allocate(frame_pointer, tag, 2);
|
||||
struct pso2 *object = pointer_to_object(result);
|
||||
object->payload.lambda.args = args;
|
||||
object->payload.lambda.body = body;
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#define __psse_payloads_lambda_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/tags.h"
|
||||
|
||||
/**
|
||||
* @brief Tag for lambda cell. Lambdas are the interpretable (source) versions of functions.
|
||||
|
|
@ -29,5 +30,9 @@ struct lambda_payload {
|
|||
struct pso_pointer body;
|
||||
};
|
||||
|
||||
|
||||
struct pso_pointer make_lambda_like_thing(struct pso_pointer frame_pointer,
|
||||
struct pso_pointer args,
|
||||
struct pso_pointer body, char *tag);
|
||||
|
||||
#define make_lambda(f,a,b) (make_lambda_like_thing( f, a, b, LAMBDATAG))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@
|
|||
#define __psse_payloads_nlambda_h
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/tags.h"
|
||||
|
||||
#include "payloads/lambda.h"
|
||||
/* nlambda shares a payload with lambda */
|
||||
|
||||
#define make_nlambda(f,a,b)(make_lambda_like_thing(f, a, b, NLAMBDATAG))
|
||||
|
||||
#endif
|
||||
|
|
|
|||
33
src/c/payloads/packed_string.h
Normal file
33
src/c/payloads/packed_string.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* packed_string.h
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* The idea of a packed string is that it is an array of wide characters,
|
||||
* packed into a paged space object. Any size of paged space object may be
|
||||
* used.
|
||||
*
|
||||
* The initial inspiration is I wanted to use swprintf to produce formatted
|
||||
* strings. Eventually, we will have a `format` function in Lisp similar to
|
||||
* Common Lisp's or Clojure's, so this issue will go away. But it may still
|
||||
* be useful to have an array of character as an explicit type.
|
||||
*
|
||||
* Copyright (c): 22 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#ifndef SRC_C_PAYLOADS_PACKED_STRING_H_
|
||||
#define SRC_C_PAYLOADS_PACKED_STRING_H_
|
||||
#include <stdint.h>
|
||||
/*
|
||||
* wide characters
|
||||
*/
|
||||
#include <wchar.h>
|
||||
|
||||
struct packed_string_payload {
|
||||
uint32_t length; /* number of characters */
|
||||
wchar_t chars[]; /* actual characters. */
|
||||
};
|
||||
|
||||
|
||||
#endif /* SRC_C_PAYLOADS_PACKED_STRING_H_ */
|
||||
|
|
@ -20,11 +20,25 @@
|
|||
#include "memory/pso4.h"
|
||||
#include "memory/tags.h"
|
||||
|
||||
#include "ops/string_ops.h"
|
||||
#include "payloads/cons.h"
|
||||
|
||||
#include "ops/stack_ops.h"
|
||||
|
||||
|
||||
/**
|
||||
* Construct a string from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the string which is being built.
|
||||
*/
|
||||
struct pso_pointer make_string( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, STRINGTAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief When an string is freed, its cdr pointer must be decremented.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ struct string_payload {
|
|||
struct pso_pointer cdr;
|
||||
};
|
||||
|
||||
struct pso_pointer make_string( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
struct pso_pointer destroy_string( struct pso_pointer fp );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
29
src/c/payloads/symbol.c
Normal file
29
src/c/payloads/symbol.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* symbol.c
|
||||
*
|
||||
* Post Scarcity Soctware Environment
|
||||
*
|
||||
* TODO: Edit purpose.
|
||||
*
|
||||
* Copyright (c): 27 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||
*/
|
||||
|
||||
#include <wctype.h>
|
||||
|
||||
#include "memory/pointer.h"
|
||||
#include "memory/tags.h"
|
||||
#include "ops/string_ops.h"
|
||||
|
||||
/**
|
||||
* Construct a symbol from the character `c` and this `tail`. A string is
|
||||
* implemented as a flat list of cells each of which has one character and a
|
||||
* pointer to the next; in the last cell the pointer to next is NIL.
|
||||
*
|
||||
* @param c the character to add (prepend);
|
||||
* @param tail the symbol which is being built.
|
||||
*/
|
||||
struct pso_pointer make_symbol( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail ) {
|
||||
return make_string_like_thing( frame_pointer, c, tail, SYMBOLTAG );
|
||||
}
|
||||
|
|
@ -10,10 +10,15 @@
|
|||
#ifndef __psse_payloads_symbol_h
|
||||
#define __psse_payloads_symbol_h
|
||||
|
||||
#include <wctype.h>
|
||||
|
||||
#include "memory/pointer.h"
|
||||
|
||||
/* TODO: for now, Symbol shares a payload with String, but this may change.
|
||||
* Strings are of indefinite length, but symbols are really not, and might
|
||||
* fit into any size class. */
|
||||
|
||||
struct pso_pointer make_symbol( struct pso_pointer frame_pointer, wint_t c,
|
||||
struct pso_pointer tail );
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue