49 char *location_descriptor ) {
55 fprintf( stderr,
"ERROR: Exception at %s: ", location_descriptor );
170 "bind_symbol_value" );
175 cell->
count = UINT32_MAX;
196 fwprintf( stdout, L
"Post-Scarcity Software Environment version %s\n\n",
206 fwprintf( stream, L
"Expected options are:\n" );
208 L
"\t-d\tDump memory to standard out at end of run (copious!);\n" );
209 fwprintf( stream, L
"\t-h\tPrint this message and exit;\n" );
210 fwprintf( stream, L
"\t-p\tShow a prompt (default is no prompt);\n" );
213 L
"\t-v LEVEL\n\t\tSet verbosity to the specified level (0...512)\n" );
214 fwprintf( stream, L
"\t\tWhere bits are interpreted as follows:\n" );
215 fwprintf( stream, L
"\t\t1\tALLOC;\n" );
216 fwprintf( stream, L
"\t\t2\tARITH;\n" );
217 fwprintf( stream, L
"\t\t4\tBIND;\n" );
218 fwprintf( stream, L
"\t\t8\tBOOTSTRAP;\n" );
219 fwprintf( stream, L
"\t\t16\tEVAL;\n" );
220 fwprintf( stream, L
"\t\t32\tINPUT/OUTPUT;\n" );
221 fwprintf( stream, L
"\t\t64\tLAMBDA;\n" );
222 fwprintf( stream, L
"\t\t128\tREPL;\n" );
223 fwprintf( stream, L
"\t\t256\tSTACK.\n" );
231int main(
int argc,
char *argv[] ) {
233 bool dump_at_end =
false;
234 bool show_prompt =
false;
235 char *infilename = NULL;
237 setlocale( LC_ALL,
"" );
239 fputs(
"Failed to initialise I/O subsystem\n", stderr );
243 while ( ( option = getopt( argc, argv,
"phdv:i:" ) ) != -1 ) {
263 fwprintf( stderr, L
"Unexpected option %c\n", option );
299 fwide( sink->
handle.file, 1 );
301 FILE *infile = infilename == NULL ? stdin : fopen( infilename,
"r" );
311 ( L
"system:standard input" ) ),
320 ( L
"system:standard output]" ) ),
328 ( L
"system:standard log" ) ),
336 ( L
"system:standard sink" ) ),
350 L
"`(absolute arg)`: If `arg` is a number, return the absolute value of that number, else `nil`.",
353 L
"`(+ args...)`: If `args` are all numbers, return the sum of those numbers.",
356 L
"`(and args...)`: Return a logical `and` of all the arguments and return `t` only if all are truthy, else `nil`.",
359 L
"`(append args...)`: If args are all collections, return the concatenation of those collections.",
362 L
"`(apply f args)`: If `f` is usable as a function, and `args` is a collection, apply `f` to `args` and return the value.",
365 L
"`(assoc key store)`: Return the value associated with this `key` in this `store`.",
368 L
"`(car arg)`: If `arg` is a sequence, return the item which is the head of that sequence.",
371 L
"`(cdr arg)`: If `arg` is a sequence, return the remainder of that sequence with the first item removed.",
374 L
"`(close stream)`: If `stream` is a stream, close that stream.",
377 L
"`(cons a b)`: Return a cons cell whose `car` is `a` and whose `cdr` is `b`.",
380 L
"`(count s)`: Return the number of items in the sequence `s`.",
383 L
"`(/ a b)`: If `a` and `b` are both numbers, return the numeric result of dividing `a` by `b`.",
386 L
"`(eq? args...)`: Return `t` if all args are the exact same object, else `nil`.",
389 L
"`(equal? args...)`: Return `t` if all args have logically equivalent value, else `nil`.",
393 L
"`(exception message)`: Return (throw) an exception with this `message`.",
396 L
"`(get-hash arg)`: returns the natural number hash value of `arg`.",
399 L
"`(hashmap n-buckets hashfn store acl)`: Return a new hashmap, with `n-buckets` buckets and this `hashfn`, containing the content of this `store`.",
402 L
"`(inspect object ouput-stream)`: Print details of this `object` to this `output-stream` or `*out*`.",
405 L
"`(keys store)`: Return a list of all keys in this `store`.",
407 bind_function( L
"list", L
"`(list args...): Return a list of these `args`.",
410 L
"`(mapcar function sequence)`: Apply `function` to each element of `sequence` in turn, and return a sequence of the results.",
413 L
"`(meta symbol)`: If the binding of `symbol` has metadata, return that metadata, else `nil`.",
416 L
"`(metadata symbol)`: If the binding of `symbol` has metadata, return that metadata, else `nil`.",
419 L
"`(* args...)` Multiply these `args`, all of which should be numbers.",
422 L
"`(negative? n)`: Return `t` if `n` is a negative number, else `nil`.",
425 L
"`(not arg)`: Return`t` only if `arg` is `nil`, else `nil`.",
428 L
"`(oblist)`: Return the current symbol bindings, as a map.",
431 L
"`(open url write?)`: Open a stream to this `url`. If `write?` is present and is non-nil, open it for writing, else reading.",
434 L
"`(or args...)`: Return a logical `or` of all the arguments and return `t` if any is truthy, else `nil`.",
437 L
"`(print object stream)`: Print `object` to `stream`, if specified, else to `*out*`.",
440 L
"`(println stream)`: Print a new line character to `stream`, if specified, else to `*out*`.",
444 L
"`(put-all! dest source)`: If `dest` is a namespace and is writable, copies all key-value pairs from `source` into `dest`.",
447 L
"`(ratio->real r)`: If `r` is a rational number, return the real number equivalent.",
450 L
"`(read stream)`: read one complete lisp form and return it. If `stream` is specified and is a read stream, then read from that stream, else the stream which is the value of `*in*` in the environment.",
453 L
"`(read-char stream)`: Return the next character. If `stream` is specified and is a read stream, then read from that stream, else the stream which is the value of `*in*` in the environment.",
456 L
"`(repl prompt input output)`: Starts a new read-eval-print-loop. All arguments are optional.",
459 L
"`(reverse sequence)` Returns a sequence of the top level elements of this `sequence`, which may be a list or a string, in the reverse order.",
463 L
"`(slurp read-stream)` Read all the characters from `read-stream` to the end of stream, and return them as a string.",
466 L
"`(source object)`: If `object` is an interpreted function or interpreted special form, returns the source code; else nil.",
469 L
"`(- a b)`: Subtracts `b` from `a` and returns the result. Expects both arguments to be numbers.",
473 L
"`(time arg)`: Return a time object. If an `arg` is supplied, it should be an integer which will be interpreted as a number of microseconds since the big bang, which is assumed to have happened 441,806,400,000,000,000 seconds before the UNIX epoch.",
476 L
"`(type object)`: returns the type of the specified `object`. Currently (0.0.6) the type is returned as a four character string; this may change.",
479 L
"`(+ args...)`: If `args` are all numbers, return the sum of those numbers.",
482 L
"`(* args...)` Multiply these `args`, all of which should be numbers.",
485 L
"`(- a b)`: Subtracts `b` from `a` and returns the result. Expects both arguments to be numbers.",
488 L
"`(/ a b)`: If `a` and `b` are both numbers, return the numeric result of dividing `a` by `b`.",
491 L
"`(equal? args...)`: Return `t` if all args have logically equivalent value, else `nil`.",
497 L
"`(cond clauses...)`: Conditional evaluation, `clauses` is a sequence of lists of forms such that if evaluating the first form in any clause returns non-`nil`, the subsequent forms in that clause will be evaluated and the value of the last returned; but any subsequent clauses will not be evaluated.",
500 L
"`(lambda arg-list forms...)`: Construct an interpretable λ funtion.",
504 L
"`(let bindings forms)`: Bind these `bindings`, which should be specified as an association list, into the local environment and evaluate these forms sequentially in that context, returning the value of the last.",
507 L
"`(nlamda arg-list forms...)`: Construct an interpretable special form. When the form is interpreted, arguments specified in the `arg-list` will not be evaluated.",
509 bind_special( L
"n\u03bb", L
"`(nlamda arg-list forms...)`: Construct an interpretable special form. When the form is interpreted, arguments specified in the `arg-list` will not be evaluated.", &
lisp_nlambda );
511 L
"`(progn forms...)` Evaluate `forms` sequentially, and return the value of the last.",
514 L
"`(quote form)`: Returns `form`, unevaluated. More idiomatically expressed `'form`, where the quote mark is a reader macro which is expanded to `(quote form)`.",
517 L
"`(set! symbol value namespace)`: Binds `symbol` in `namespace` to the value of `value`, altering the namespace in so doing, and returns `value`. If `namespace` is not specified, it defaults to the default namespace.",
529 fprintf( stderr,
"Dangling refs on oblist: %d\n",
541 curl_global_cleanup( );
void dump_pages(URL_FILE *output)
dump the allocated pages to this output stream.
struct cons_pointer privileged_string_memory_exhausted
The exception message printed when the world blows up, initialised in maybe_bind_init_symbols() in in...
void summarise_allocation()
void initialise_cons_pages()
initialise the cons page system; to be called exactly once during startup.
struct cons_pointer make_special(struct cons_pointer meta, struct cons_pointer(*executable)(struct stack_frame *frame, struct cons_pointer, struct cons_pointer env))
Construct a cell which points to an executable Lisp special form.
struct cons_pointer c_string_to_lisp_keyword(wchar_t *symbol)
Return a lisp keyword representation of this wide character string.
struct cons_pointer make_function(struct cons_pointer meta, struct cons_pointer(*executable)(struct stack_frame *, struct cons_pointer, struct cons_pointer))
Construct a cell which points to an executable Lisp function.
struct cons_pointer make_write_stream(URL_FILE *output, struct cons_pointer metadata)
Construct a cell which points to a stream open for writing.
struct cons_pointer c_string_to_lisp_string(wchar_t *string)
Return a lisp string representation of this wide character string.
struct cons_pointer make_read_stream(URL_FILE *input, struct cons_pointer metadata)
Construct a cell which points to a stream open for reading.
struct cons_pointer c_string_to_lisp_symbol(wchar_t *symbol)
Return a lisp symbol representation of this wide character string.
struct cons_pointer dec_ref(struct cons_pointer pointer)
Decrement the reference count of the object at this cons pointer.
struct cons_pointer make_cons(struct cons_pointer car, struct cons_pointer cdr)
Construct a cons cell from this pair of pointers.
#define exceptionp(conspoint)
true if conspoint points to an exception, else false
union cons_space_object::@3 payload
#define NIL
a cons pointer which points to the special NIL cell
#define nilp(conspoint)
true if conspoint points to the special cell NIL, else false (there should only be one of these so it...
uint32_t count
the count of the number of references to this cell
#define TRUE
a cons pointer which points to the special T cell
struct cons_pointer c_string_to_lisp_symbol(wchar_t *symbol)
Return a lisp symbol representation of this wide character string.
struct cons_pointer dec_ref(struct cons_pointer pointer)
Decrement the reference count of the object at this cons pointer.
#define pointer2cell(pointer)
given a cons_pointer as argument, return the cell.
An indirect pointer to a cons cell.
int verbosity
the controlling flags for debug_print; set in init.c, q.v.
void debug_dump_object(struct cons_pointer pointer, int level)
Like dump_object, q.v., but protected by the verbosity mechanism.
void debug_print(wchar_t *message, int level)
print this debug message to stderr, if verbosity matches level.
#define DEBUG_BOOTSTRAP
Print messages debugging bootstrapping and teardown.
URL_FILE * url_fopen(const char *url, const char *operation)
union fcurl_data::@0 handle
struct cons_pointer lisp_hashmap_put_all(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Lisp function expecting two arguments, a hashmap and an assoc list.
struct cons_pointer lisp_get_hash(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
A lisp function signature conforming wrapper around get_hash, q.v.
struct cons_pointer lisp_hashmap_put(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Expects frame->arg[1] to be a hashmap or namespace; frame->arg[2] to be a string-like-thing (perhaps ...
struct cons_pointer lisp_make_hashmap(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Lisp funtion of up to four args (all optional), where.
struct cons_pointer check_exception(struct cons_pointer pointer, char *location_descriptor)
If pointer is an exception, display that exception to stderr, decrement that exception,...
int main(int argc, char *argv[])
main entry point; parse command line arguments, initialise the environment, and enter the read-eval-p...
void maybe_bind_init_symbols()
struct cons_pointer bind_special(wchar_t *name, wchar_t *doc, struct cons_pointer(*executable)(struct stack_frame *, struct cons_pointer, struct cons_pointer))
Bind this compiled executable function, as a Lisp special form, to this name in the oblist.
void print_options(FILE *stream)
Print command line options to this stream.
struct cons_pointer init_documentation_symbol
struct cons_pointer bind_function(wchar_t *name, wchar_t *doc, struct cons_pointer(*executable)(struct stack_frame *, struct cons_pointer, struct cons_pointer))
Bind this compiled executable function, as a Lisp function, to this name in the oblist.
struct cons_pointer init_name_symbol
struct cons_pointer init_primitive_symbol
struct cons_pointer bind_symbol_value(struct cons_pointer symbol, struct cons_pointer value, bool lock)
Bind this value to this symbol in the oblist.
struct cons_pointer bind_value(wchar_t *name, struct cons_pointer value, bool lock)
Bind this value to this name in the oblist.
struct cons_pointer privileged_symbol_nil
the symbol NIL, which is special!
struct cons_pointer make_hashmap(uint32_t n_buckets, struct cons_pointer hash_fn, struct cons_pointer write_acl)
Make a hashmap with this number of buckets, using this hash_fn.
struct cons_pointer oblist
The global object list/or, to put it differently, the root namespace.
struct cons_pointer deep_bind(struct cons_pointer key, struct cons_pointer value)
Binds this key to this value in the global oblist, and returns the key.
int io_init()
Initialise the I/O subsystem.
struct cons_pointer lisp_io_in
bound to the Lisp string representing C_IO_IN in initialisation.
struct cons_pointer lisp_open(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: return a stream open on the URL indicated by the first argument; if a second argument is pr...
struct cons_pointer lisp_io_out
bound to the Lisp string representing C_IO_OUT in initialisation.
struct cons_pointer lisp_slurp(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: return a string representing all characters from the stream indicated by arg 0; further arg...
URL_FILE * file_to_url_file(FILE *f)
given this file handle f, return a new url_file handle wrapping it.
struct cons_pointer lisp_close(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function, sort-of: close the file indicated by my first arg, and return nil.
struct cons_pointer lisp_read_char(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: return the next character from the stream indicated by arg 0; further arguments are ignored...
struct cons_pointer lisp_nlambda(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Construct an interpretable special form.
struct cons_pointer lisp_assoc(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; look up the value of a key in a store.
struct cons_pointer lisp_source(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function.
struct cons_pointer lisp_mapcar(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
struct cons_pointer lisp_cons(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; returns a cell constructed from a and b.
struct cons_pointer lisp_eq(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; are these two objects the same object? Shallow, cheap equality.
struct cons_pointer lisp_read(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; read one complete lisp form and return it.
struct cons_pointer lisp_exception(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; create an exception.
struct cons_pointer lisp_car(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; returns the first item (head) of a sequence.
struct cons_pointer lisp_count(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: return the number of top level forms in the object which is the first (and only) argument,...
struct cons_pointer lisp_let(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Special form: evaluate a series of forms in an environment in which these bindings are bound.
struct cons_pointer lisp_inspect(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: dump/inspect one complete lisp expression and return NIL.
struct cons_pointer lisp_or(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Boolean or of arbitrarily many arguments.
struct cons_pointer lisp_try(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
OK, the idea here (and I know this is less than perfect) is that the basic try special form in PSSE t...
struct cons_pointer lisp_apply(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; apply the function which is the result of evaluating the first argument to the list of valu...
struct cons_pointer lisp_eval(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; evaluate the expression which is the first argument in the frame; further arguments are ign...
struct cons_pointer lisp_type(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: get the Lisp type of the single argument.
struct cons_pointer lisp_progn(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Special form; evaluate the expressions which are listed in my arguments sequentially and return the v...
struct cons_pointer lisp_keys(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
struct cons_pointer lisp_equal(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; are these two arguments identical? Deep, expensive equality.
struct cons_pointer lisp_repl(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: the read/eval/print loop.
struct cons_pointer lisp_set_shriek(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Special form; binds symbol in the namespace to value of value, altering the namespace in so doing,...
struct cons_pointer lisp_append(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
should really be overwritten with a version in Lisp, since this is much easier to write in Lisp
struct cons_pointer lisp_not(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Logical inverese: if the first argument is nil, return t, else nil.
struct cons_pointer lisp_quote(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Special form; returns its argument (strictly first argument - only one is expected but this isn't at ...
struct cons_pointer lisp_set(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; binds the value of name in the namespace to value of value, altering the namespace in so do...
struct cons_pointer lisp_lambda(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Construct an interpretable function.
struct cons_pointer lisp_cdr(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; returns the remainder of a sequence when the head is removed.
struct cons_pointer lisp_list(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
construct and return a list of arbitrarily many arguments.
struct cons_pointer lisp_oblist(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Return the object list (root namespace).
struct cons_pointer lisp_cond(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Special form: conditional.
struct cons_pointer lisp_reverse(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; reverse the order of members in s sequence.
struct cons_pointer prompt_name
the name of the symbol to which the prompt is bound;
struct cons_pointer lisp_and(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Boolean and of arbitrarily many arguments.
struct cons_pointer lisp_absolute(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: calculate the absolute value of a number.
struct cons_pointer lisp_ratio_to_real(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: return a real (approcimately) equal in value to the ratio which is the first argument.
struct cons_pointer lisp_is_negative(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function: is this number negative?
struct cons_pointer lisp_subtract(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Subtract one number from another.
struct cons_pointer lisp_divide(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Divide one number by another.
struct cons_pointer lisp_multiply(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Multiply an indefinite number of numbers together.
struct cons_pointer lisp_add(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Add an indefinite number of numbers together.
struct cons_pointer print(URL_FILE *output, struct cons_pointer pointer)
Print the cons-space object indicated by pointer to the stream indicated by output.
struct cons_pointer lisp_print(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; print one complete lisp expression and return NIL.
struct cons_pointer lisp_time(struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env)
Function; return a time representation of the first argument in the frame; further arguments are igno...
void repl()
The read/eval/print loop.