Major step forward: equal is now working, and consequently so is assoc.

This commit is contained in:
Simon Brooke 2026-05-06 16:42:18 +01:00
parent 271b7da46a
commit 5e64a33965
11 changed files with 168 additions and 137 deletions

View file

@ -67,7 +67,7 @@ bind_function(struct pso_pointer frame_pointer, wchar_t *name, wchar_t *doc,
struct pso_pointer meta = make_cons(
frame_pointer,
make_cons(frame_pointer, privileged_keyword_bootstrap, nil),
make_cons(frame_pointer, privileged_keyword_layer, privileged_keyword_bootstrap),
make_cons(frame_pointer,
make_cons(frame_pointer, privileged_keyword_name, n),
make_cons(frame_pointer,
@ -79,11 +79,11 @@ bind_function(struct pso_pointer frame_pointer, wchar_t *name, wchar_t *doc,
debug_print(doc, DEBUG_BOOTSTRAP, 0);
if (!exceptionp(r)) {
debug_print(U"... bound\n", DEBUG_BOOTSTRAP, 0);
debug_print(L"... bound\n", DEBUG_BOOTSTRAP, 0);
result =
make_cons(frame_pointer, make_cons(frame_pointer, n, r), result);
} else {
debug_print(U"... failed to bind\n", DEBUG_BOOTSTRAP, 0);
debug_print(L"... failed to bind\n", DEBUG_BOOTSTRAP, 0);
}
return result;
@ -114,11 +114,11 @@ bind_special(struct pso_pointer frame_pointer, wchar_t *name, wchar_t *doc,
debug_print(doc, DEBUG_BOOTSTRAP, 0);
if (!exceptionp(r)) {
debug_print(U"... bound\n", DEBUG_BOOTSTRAP, 0);
debug_print(L"... bound\n", DEBUG_BOOTSTRAP, 0);
result =
make_cons(frame_pointer, make_cons(frame_pointer, n, r), result);
} else {
debug_print(U"... failed to bind\n", DEBUG_BOOTSTRAP, 0);
debug_print(L"... failed to bind\n", DEBUG_BOOTSTRAP, 0);
}
return result;
@ -140,152 +140,152 @@ struct function_data {
/** initialisers for functions */
struct function_data function_initialisers[] = {
#ifdef _psse_io_io_h
{U"close", U"(close stream): close `stream`.", &lisp_close},
{U"open",
U"(open stream), (open stream write?): open `stream`; if `write?` is "
U"present and is non-nil, open for writing, else for reading.",
{L"close", L"(close stream): close `stream`.", &lisp_close},
{L"open",
L"(open stream), (open stream write?): open `stream`; if `write?` is "
L"present and is non-nil, open for writing, else for reading.",
&lisp_open},
{U"slurp",
U"(slurp stream): read the whole contents of this `stream`, "
U"which may "
U"be an open stream open for reading or a URL, into a string, and return "
U"the "
U"string.",
{L"slurp",
L"(slurp stream): read the whole contents of this `stream`, "
L"which may "
L"be an open stream open for reading or a URL, into a string, and return "
L"the "
L"string.",
&lisp_slurp},
#endif
#ifdef __psse_io_peek_h
{U"peek",
U"(peek stream): return the next character which may be read from "
U"`stream`, without removing it.",
{L"peek",
L"(peek stream): return the next character which may be read from "
L"`stream`, without removing it.",
&peek},
#endif
#ifdef __psse_io_print_h
{U"print",
U"(print object), (print object stream) print this `object` in a format "
U"suitable to be read by `read`, q.v.; if `stream` is specified and is a "
U"stream open for writing, to that stream.",
{L"print",
L"(print object), (print object stream) print this `object` in a format "
L"suitable to be read by `read`, q.v.; if `stream` is specified and is a "
L"stream open for writing, to that stream.",
&print},
{U"princ",
U"(princ object), (princ object stream) print this `object` in a format "
U"more suited to human readers; if `stream` is specified and is a stream "
U"open for writing, to that stream.",
{L"princ",
L"(princ object), (princ object stream) print this `object` in a format "
L"more suited to human readers; if `stream` is specified and is a stream "
L"open for writing, to that stream.",
&print},
#endif
#ifdef __psse_io_read_h
{U"read",
U"(read stream) read one complete Lisp expression from `stream`, and "
U"return that expression unevaluated.",
{L"read",
L"(read stream) read one complete Lisp expression from `stream`, and "
L"return that expression unevaluated.",
&read},
{U"read-character",
U"(read-character stream): read a single character from `stream` and "
U"return it.",
{L"read-character",
L"(read-character stream): read a single character from `stream` and "
L"return it.",
&read_character},
{U"read-number",
U"(read-number stream): read a number from `stream` and return it.",
{L"read-number",
L"(read-number stream): read a number from `stream` and return it.",
&read_number},
{U"read-symbol",
U"(read-symbol stream): read a symbol from `stream` and return it.",
{L"read-symbol",
L"(read-symbol stream): read a symbol from `stream` and return it.",
&read_symbol},
#endif
#ifdef __psse_ops_assoc_h
{U"assoc",
U"(assoc key store): search `store` for the value associated with "
U"`key`.",
{L"assoc",
L"(assoc key store): search `store` for the value associated with "
L"`key`.",
&assoc},
#endif
#ifdef __psse_ops_bind_h
{U"bind!",
U"(bind! key value store): bind `key` to `value` in this store, modifying "
U"the store if it is writable to the user, otherwise returning a new "
U"store",
{L"bind!",
L"(bind! key value store): bind `key` to `value` in this store, modifying "
L"the store if it is writable to the user, otherwise returning a new "
L"store",
&bind},
#endif
#ifdef __psse_ops_eq_h
{U"eq",
U"(eq args...): shallow, cheap equality; returns `t` if all `args...` "
U"are the same object, else `nil`.",
{L"eq",
L"(eq args...): shallow, cheap equality; returns `t` if all `args...` "
L"are the same object, else `nil`.",
&eq},
{U"equal",
U"(equal a b): expensive, deep equality: returns `t` if objects `a` "
U"and `b` have recursively equal value.",
{L"equal",
L"(equal a b): expensive, deep equality: returns `t` if objects `a` "
L"and `b` have recursively equal value.",
&equal},
#endif
#ifdef __psse_ops_eval_apply_h
// TODO: there's a lot of other stuff in eval_apply.c, which ought to be in
// other files but at present isn't.
{U"apply",
U"(apply fn args...): apply this `fn` to these `args...` and return "
U"their value.",
{L"apply",
L"(apply fn args...): apply this `fn` to these `args...` and return "
L"their value.",
&lisp_apply},
{U"eval",
U"(eval expression): evaluate this `expression` and return its value",
{L"eval",
L"(eval expression): evaluate this `expression` and return its value",
&lisp_eval},
#endif
#ifdef __psse_ops_inspect_h
{U"inspect",
U"(inspect expr), (inspect expr write-stream): inspect one complete "
U"lisp expression and return `nil`. If `write-stream` is specified and "
U"is a write stream, then print to that stream, else to the stream "
U"which is the value of `*out*` in the environment.",
{L"inspect",
L"(inspect expr), (inspect expr write-stream): inspect one complete "
L"lisp expression and return `nil`. If `write-stream` is specified and "
L"is a write stream, then print to that stream, else to the stream "
L"which is the value of `*out*` in the environment.",
&lisp_inspect},
#endif
#ifdef __psse_ops_keys_h
{U"keys", U"(keys store): returns a list of the keys in this `store`.",
{L"keys", L"(keys store): returns a list of the keys in this `store`.",
&lisp_keys},
#endif
#ifdef __psse_ops_list_ops_h
{U"count",
U"(count sequence): returns the number of top level elements in "
U"`sequence`.",
{L"count",
L"(count sequence): returns the number of top level elements in "
L"`sequence`.",
&count},
#endif
#ifdef __psse_ops_mapcar_h
{U"mapcar",
U"(mapcar fn list): map this `fn` over this `list`, and return a list "
U"of the results.",
{L"mapcar",
L"(mapcar fn list): map this `fn` over this `list`, and return a list "
L"of the results.",
&lisp_mapcar},
#endif
#ifdef __psse_ops_progn_h
{U"progn",
U"(progn expressions...): Evaluate each expression in "
U"`expressions` in turn and return the value of the last.",
{L"progn",
L"(progn expressions...): Evaluate each expression in "
L"`expressions` in turn and return the value of the last.",
&lisp_progn},
#endif
#ifdef __psse_ops_repl_h
{U"repl", U"(repl show_prompt?): Start a new read, eval, print loop.",
{L"repl", L"(repl show_prompt?): Start a new read, eval, print loop.",
&repl},
#endif
#ifdef __psse_ops_reverse_h
{U"reverse",
U"(reverse sequence): return a sequence like this `sequence`, but with "
U"the order of top level elements reversed.",
{L"reverse",
L"(reverse sequence): return a sequence like this `sequence`, but with "
L"the order of top level elements reversed.",
&reverse},
#endif
#ifdef __psse_ops_truth_h
{U"and",
U"(and expressions...): returns `t` if none of these `expressions...` "
U"evaluates to `nil`, else `nil`.",
{L"and",
L"(and expressions...): returns `t` if none of these `expressions...` "
L"evaluates to `nil`, else `nil`.",
&and},
{U"nil?",
U"(nil? expression): returns `t` if `expression` evaluates to `nil`, else "
U"`nil`.",
{L"nil?",
L"(nil? expression): returns `t` if `expression` evaluates to `nil`, else "
L"`nil`.",
&nilp},
{U"not",
U"(not expression): returns `t` unless `expression` evaluates to `nil`, "
U"else "
U"`nil`.",
{L"not",
L"(not expression): returns `t` unless `expression` evaluates to `nil`, "
L"else "
L"`nil`.",
&not},
{U"or",
U"(or expressions...): returns `nil` if every one of these `expressions...` "
U"evaluates to `nil`, else `t`.",
{L"or",
L"(or expressions...): returns `nil` if every one of these `expressions...` "
L"evaluates to `nil`, else `t`.",
&or},
{U"true?",
U"(true? expression): returns `t` if `expression` evaluates to `t`, else "
U"`nil`.",
{L"true?",
L"(true? expression): returns `t` if `expression` evaluates to `t`, else "
L"`nil`.",
&truep},
#endif
{U"END MARKER", U"END MARKER", NULL}};
{L"END MARKER", L"END MARKER", NULL}};
/* right, the problem with all those pretty '#ifdefs' which might allow us to
* simply switch functions on and off just by including or not including .h
@ -296,22 +296,22 @@ struct function_data function_initialisers[] = {
/** initialisers for special forms */
struct function_data special_initialisers[] = {
#ifdef __psse_ops_cond_h
{U"cond",
U"(cond clauses...): special form; conditional. Each `clause` is expected "
U"to be a "
U"list; if the first item in such a list evaluates to non-nil, the "
U"remaining items in that list are evaluated in turn and the value of "
U"the last returned. If no arg `clause` has a first element which "
U"evaluates to non nil, then nil is returned",
{L"cond",
L"(cond clauses...): special form; conditional. Each `clause` is expected "
L"to be a "
L"list; if the first item in such a list evaluates to non-nil, the "
L"remaining items in that list are evaluated in turn and the value of "
L"the last returned. If no arg `clause` has a first element which "
L"evaluates to non nil, then nil is returned",
&lisp_cond},
#endif
#ifdef __psse_ops_quote_h
{U"quote",
U"(quote expression): special form; protect `expression` from "
U"evaluation.",
{L"quote",
L"(quote expression): special form; protect `expression` from "
L"evaluation.",
&quote},
#endif
{U"END MARKER", U"END MARKER", NULL}};
{L"END MARKER", L"END MARKER", NULL}};
struct pso_pointer
initialise_function_bindings(struct pso_pointer frame_pointer) {