Started work on binding functions. Not yet complete.
This commit is contained in:
parent
f4303247b9
commit
efa6a3246d
17 changed files with 321 additions and 41 deletions
|
|
@ -24,7 +24,35 @@ The answer, dear reader, is that Emacs is determined to get in my way in every p
|
||||||
|
|
||||||
#### Eclipse
|
#### Eclipse
|
||||||
|
|
||||||
When I finally switched away from using Emacs for everything
|
When I finally switched away from using Emacs for everything, sometime around 2000, I tried a number of things and ended up with [Eclipse](https://eclipseide.org/), which was at the time a fairly simple but fairly solid Java oriented integrated development environment (IDE). I stayed with Eclipse then for about a decade; but when I moved to mainly developing in Clojure, Eclipse just didn't do Clojure very well, I switched back to Emacs for a while, was driven mad by it again, and found LightTable as a blissful release; which takes us back to the beginning of this section.
|
||||||
|
|
||||||
|
Last month, when I was searching for something to replace VSCodium and had realised once again how much I hate using Emacs for serious development, I tried Eclipse.
|
||||||
|
|
||||||
|
It's... not awful? It's become a very polished, very configurable IDE; it has excellent facilities for C development. But I found it intrusively over-helpful: its continual 'helpful' suggestions got in my way. I used it for about ten days. I wasn't enjoying it. But what made me give up on it was because it won't follow your configured desktop colour theme, and I wasn't able to find a dark-mode theme for it that worked for me: there are plenty of themes , but they are only applied to the editing panels, not to the chrome or to any of the other panels. I find white backgrounds really unpleasant on my eyes.
|
||||||
|
|
||||||
|
#### KDevelop and Gnome Builder
|
||||||
|
|
||||||
|
I know I tried [KDevelop](https://kdevelop.org/) at some stage in this process. I can't remember why I rejected it. There's probably a reason. I also tried [Gnome Builder](https://apps.gnome.org/en-GB/Builder/) and rejected it very quickly, again I can't remember why; having a wee play with it just now it feels quite nice, and I may have another try. However, the Debian package of Gnome Builder [does not include the help files](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1111418), and, without them, I haven't found out how to invoke the debugger.
|
||||||
|
|
||||||
|
#### Basic text editors
|
||||||
|
|
||||||
|
I obviously have a basic text editor, [gedit](https://gedit-text-editor.org/), on my system. It does C syntax highlighting very well, but doesn't do code completion, and doesn't have any integration with a build system or debugger. I have various debugger user interfaces — I like [seergdb](https://github.com/epasveer/seer) — but I do have it convenient to have a debugger integrated into my editor, rather than having to switch between two separate applications. Similarly, it's convenient to have a terminal integrated with the development environment, although it doesn't need to be. GEdit, plus seergdb, plus a terminal, plus some sort of a git browser, would work for me.
|
||||||
|
|
||||||
|
#### New editors
|
||||||
|
|
||||||
|
People online have suggested I try two new editors: [Zed](https://zed.dev/) and Gram: these are essentially the same editor, in fact. Zed proudly announces itself as
|
||||||
|
|
||||||
|
> a minimal code editor crafted for speed and collaboration with humans and AI
|
||||||
|
|
||||||
|
The Zed project seems to want to monetise their work by selling you AI tokens. Which LLM is behind their AI I don't know. Open Source development needs to be funded somehow; funding it through a tax on people who use AI is as good a way as any.
|
||||||
|
|
||||||
|
Dear reader, I do **not want** to collaborate with AI; I don't want any of that shit in my working environment. So that immediately got my back up. It also doesn't have a Debian installer. But I was able to build it from source, and have been using it consistently over the last couple of days, and it's very pleasant. There's a built in debugger, but I cannot get it to work. Beyond that, my build crashes occasionally — maybe once every two or three hours; but it doesn't seem to lose anything when it crashes, so this is not obnoxious. If I ignore the 'AI' features, the lack of a working debugger is the only mark against it.
|
||||||
|
|
||||||
|
[Gram](https://gram.liten.app/) is said to be a fork of Zed with the AI features removed. It has a proper Debian installation repository, which is a significant step up over Zed. Unfortunately, it won't run on my desktop machine, due to [a problem with the video card](https://codeberg.org/GramEditor/gram/issues/256). On my laptop, it runs fine, and seems generally usable — although, again, I can't get the debugger to work.
|
||||||
|
|
||||||
|
#### Conclusion for now
|
||||||
|
|
||||||
|
The conclusion for now is that I don't have a conclusion for now. Any of Gnome Builder, Zed and Gram are sort of good enough. Zed crashes, which is not desirable; Gram only launches on my laptop, but I mostly do serious development on my desktop; I can't yet work out how to launch the debugger on any of them. But none are annoying, none get in my way. I'll keep on evaluating.
|
||||||
|
|
||||||
## 20260503
|
## 20260503
|
||||||
|
|
||||||
|
|
|
||||||
175
src/c/environment/function_bindings.c
Normal file
175
src/c/environment/function_bindings.c
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**
|
||||||
|
* environment/function_bindings.c
|
||||||
|
*
|
||||||
|
* Post Scarcity Software Environment:
|
||||||
|
*
|
||||||
|
* Provide bindings for substrate functions. At least in theory, these
|
||||||
|
* bindings only need to be initialised on node zero.
|
||||||
|
* todo: they really ought to be in a namespace ::system:bootstrap, once I
|
||||||
|
* have namespaces and paths working.
|
||||||
|
*
|
||||||
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
#include "environment/privileged_keywords.h"
|
||||||
|
#include "memory/node.h"
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
#include "memory/tags.h"
|
||||||
|
|
||||||
|
#include "ops/assoc.h"
|
||||||
|
#include "ops/bind.h"
|
||||||
|
#include "ops/cond.h"
|
||||||
|
#include "ops/eval_apply.h"
|
||||||
|
#include "ops/eq.h"
|
||||||
|
#include "ops/inspect.h"
|
||||||
|
#include "ops/stack_ops.h"
|
||||||
|
#include "ops/string_ops.h"
|
||||||
|
|
||||||
|
#include "payloads/cons.h"
|
||||||
|
#include "payloads/function.h"
|
||||||
|
#include "payloads/special.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind this compiled `executable` function, as a Lisp function, to
|
||||||
|
* this name in the `oblist`.
|
||||||
|
* \todo where a function is not compiled from source, we could cache
|
||||||
|
* the name on the source pointer. Would make stack frames potentially
|
||||||
|
* more readable and aid debugging generally.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct pso_pointer
|
||||||
|
bind_function(struct pso_pointer frame_pointer, wchar_t *name, wchar_t *doc,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer)) {
|
||||||
|
struct pso_pointer result = fetch_env(frame_pointer);
|
||||||
|
struct pso_pointer n = c_string_to_lisp_symbol(frame_pointer, name);
|
||||||
|
struct pso_pointer d = c_string_to_lisp_string(frame_pointer, doc);
|
||||||
|
|
||||||
|
struct pso_pointer meta =
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_bootstrap, nil),
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_name, n),
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_documentation, d), nil)));
|
||||||
|
|
||||||
|
struct pso_pointer r = make_function(frame_pointer, meta, executable);
|
||||||
|
|
||||||
|
if (!exceptionp(r)) {
|
||||||
|
result = make_cons( frame_pointer, make_cons( frame_pointer, n, r), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind this compiled `executable` function, as a Lisp special form, to
|
||||||
|
* this `name` in the `oblist`.
|
||||||
|
*/
|
||||||
|
struct pso_pointer
|
||||||
|
bind_special(struct pso_pointer frame_pointer, wchar_t *name, wchar_t *doc,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer)) {
|
||||||
|
struct pso_pointer result = fetch_env(frame_pointer);
|
||||||
|
struct pso_pointer n = c_string_to_lisp_symbol(frame_pointer, name);
|
||||||
|
struct pso_pointer d = c_string_to_lisp_string(frame_pointer, doc);
|
||||||
|
|
||||||
|
struct pso_pointer meta =
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_bootstrap, nil),
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_name, n),
|
||||||
|
make_cons( frame_pointer, make_cons( frame_pointer, privileged_keyword_documentation, d), nil)));
|
||||||
|
|
||||||
|
struct pso_pointer r = make_special(frame_pointer, meta, executable);
|
||||||
|
|
||||||
|
if (!exceptionp(r)) {
|
||||||
|
result = make_cons( frame_pointer, make_cons( frame_pointer, n, r), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct function_data {
|
||||||
|
char32_t *name;
|
||||||
|
char32_t *documentation;
|
||||||
|
void* executable;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* files is that the C compiler is too primitive to know how many items there
|
||||||
|
* are in an array. So this number must be edited manually, and must be right.
|
||||||
|
*/
|
||||||
|
#define N_FUNCTION_INITIALISERS 4
|
||||||
|
|
||||||
|
/** initialisers for functions */
|
||||||
|
struct function_data function_initialisers[] = {
|
||||||
|
#ifdef __psse_ops_assoc_h
|
||||||
|
{U"assoc",
|
||||||
|
U"(assoc key store): search `store` for the value associated with "
|
||||||
|
U"`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",
|
||||||
|
&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`.",
|
||||||
|
&eq},
|
||||||
|
{U"equal",
|
||||||
|
U"(equal a b): expensive, deep equality: returns `t` if objects `a` "
|
||||||
|
U"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.",
|
||||||
|
&lisp_apply},
|
||||||
|
{U"eval",
|
||||||
|
U"(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.",
|
||||||
|
&lisp_inspect
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* files is that the C compiler is too primitive to know how many items there
|
||||||
|
* are in an array */
|
||||||
|
#define N_SPECIAL_INITIALISERS 1
|
||||||
|
|
||||||
|
/** initialisers for special forms */
|
||||||
|
struct function_data special_initialisers[] = {
|
||||||
|
#ifdef __psse_ops_cond_h
|
||||||
|
{U"cond",
|
||||||
|
U"(cond clauses...): conditional. Each `clause` is expected 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",
|
||||||
|
&lisp_cond},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pso_pointer
|
||||||
|
initialise_function_bindings(struct pso_pointer frame_pointer) {
|
||||||
|
struct pso_pointer result = fetch_env(frame_pointer);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
0
src/c/environment/function_bindings.h
Normal file
0
src/c/environment/function_bindings.h
Normal file
|
|
@ -23,6 +23,13 @@
|
||||||
#include "ops/string_ops.h"
|
#include "ops/string_ops.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* layer metadata for functions written in C
|
||||||
|
*/
|
||||||
|
struct pso_pointer privileged_keyword_bootstrap;
|
||||||
|
|
||||||
|
struct pso_pointer privileged_keyword_documentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* location metadata for exceptions (and possibly location in other contexts).
|
* location metadata for exceptions (and possibly location in other contexts).
|
||||||
*/
|
*/
|
||||||
|
|
@ -37,7 +44,9 @@ struct pso_pointer privileged_keyword_name;
|
||||||
#define load_and_lock(var,val)var = lock_object(c_string_to_lisp_keyword(nil, val))
|
#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){
|
struct pso_pointer initialise_privileged_keywords(struct pso_pointer env) {
|
||||||
|
load_and_lock(privileged_keyword_bootstrap, PK_BOOTSTRAP);
|
||||||
|
load_and_lock(privileged_keyword_documentation, PK_DOCUMENTATION);
|
||||||
load_and_lock(privileged_keyword_location, PK_LOCATION);
|
load_and_lock(privileged_keyword_location, PK_LOCATION);
|
||||||
load_and_lock( privileged_keyword_name, PK_NAME);
|
load_and_lock( privileged_keyword_name, PK_NAME);
|
||||||
}
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Post Scarcity Soctware Environment
|
* Post Scarcity Soctware Environment
|
||||||
*
|
*
|
||||||
* TODO: Edit purpose.
|
* Keywords guaranteed to be present in the environment on each node.
|
||||||
*
|
*
|
||||||
* Copyright (c): 27 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
* Copyright (c): 27 Apr 2026 Simon Brooke <simon@journeyman.cc>
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
|
|
@ -11,11 +11,15 @@
|
||||||
|
|
||||||
#ifndef SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
#ifndef SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
||||||
#define SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
#define SRC_C_ENVIRONMENT_PRIVILEGED_KEYWORDS_H_
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
#define PK_BOOTSTRAP U"bootstrap"
|
||||||
|
#define PK_DOCUMENTATION U"documentation"
|
||||||
#define PK_LOCATION U"location"
|
#define PK_LOCATION U"location"
|
||||||
#define PK_NAME U"name"
|
#define PK_NAME U"name"
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
extern struct pso_pointer privileged_keyword_bootstrap;
|
||||||
|
extern struct pso_pointer privileged_keyword_documentation;
|
||||||
extern struct pso_pointer privileged_keyword_location;
|
extern struct pso_pointer privileged_keyword_location;
|
||||||
extern struct pso_pointer privileged_keyword_name;
|
extern struct pso_pointer privileged_keyword_name;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,13 +115,8 @@ bool c_internedp( struct pso_pointer key, struct pso_pointer store ) {
|
||||||
* @return a pointer to the value of the key in the store, or nil if not found
|
* @return a pointer to the value of the key in the store, or nil if not found
|
||||||
*/
|
*/
|
||||||
struct pso_pointer assoc(
|
struct pso_pointer assoc(
|
||||||
#ifndef MANAGED_POINTER_ONLY
|
|
||||||
struct pso4 *frame,
|
|
||||||
#endif
|
|
||||||
struct pso_pointer frame_pointer ) {
|
struct pso_pointer frame_pointer ) {
|
||||||
#ifdef MANAGED_POINTER_ONLY
|
|
||||||
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
||||||
#endif
|
|
||||||
struct pso_pointer key = fetch_arg( frame, 0 );
|
struct pso_pointer key = fetch_arg( frame, 0 );
|
||||||
struct pso_pointer store = or( make_frame( 2, frame_pointer,
|
struct pso_pointer store = or( make_frame( 2, frame_pointer,
|
||||||
fetch_arg( frame, 1 ),
|
fetch_arg( frame, 1 ),
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
struct pso_pointer assoc(struct pso_pointer frame_pointer);
|
||||||
|
|
||||||
struct pso_pointer search( struct pso_pointer key,
|
struct pso_pointer search( struct pso_pointer key,
|
||||||
struct pso_pointer store, bool return_key );
|
struct pso_pointer store, bool return_key );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "memory/node.h"
|
#include "memory/node.h"
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
#include "memory/pso2.h"
|
#include "memory/pso2.h"
|
||||||
|
#include "memory/pso4.h"
|
||||||
#include "memory/tags.h"
|
#include "memory/tags.h"
|
||||||
|
|
||||||
#include "ops/eval_apply.h"
|
#include "ops/eval_apply.h"
|
||||||
|
|
@ -29,12 +30,12 @@
|
||||||
*/
|
*/
|
||||||
struct pso_pointer eval_cond_clause( struct pso_pointer clause,
|
struct pso_pointer eval_cond_clause( struct pso_pointer clause,
|
||||||
struct pso4 *frame,
|
struct pso4 *frame,
|
||||||
struct pso_pointer frame_pointer,
|
struct pso_pointer frame_pointer) {
|
||||||
struct pso_pointer env ) {
|
|
||||||
struct pso_pointer result = nil;
|
struct pso_pointer result = nil;
|
||||||
|
struct pso_pointer env = fetch_env(frame_pointer);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug_print( L"\n\tCond clause: ", DEBUG_EVAL, 0 );
|
debug_print( U"\n\tCond clause: ", DEBUG_EVAL, 0 );
|
||||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||||
debug_println( DEBUG_EVAL);
|
debug_println( DEBUG_EVAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -49,19 +50,19 @@ struct pso_pointer eval_cond_clause( struct pso_pointer clause,
|
||||||
c_progn( frame, frame_pointer, c_cdr( clause ), env ) );
|
c_progn( frame, frame_pointer, c_cdr( clause ), env ) );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug_print( L"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
debug_print( U"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
||||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||||
debug_print( L" succeeded; returning: ", DEBUG_EVAL, 0 );
|
debug_print( U" succeeded; returning: ", DEBUG_EVAL, 0 );
|
||||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||||
debug_println( DEBUG_EVAL);
|
debug_println( DEBUG_EVAL);
|
||||||
} else {
|
} else {
|
||||||
debug_print( L"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
debug_print( U"\n\t\tCond clause ", DEBUG_EVAL, 0 );
|
||||||
debug_print_object( clause, DEBUG_EVAL, 0 );
|
debug_print_object( clause, DEBUG_EVAL, 0 );
|
||||||
debug_print( L" failed.\n", DEBUG_EVAL, 0 );
|
debug_print( U" failed.\n", DEBUG_EVAL, 0 );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result = throw_exception( c_string_to_lisp_symbol( frame_pointer, L"cond" ),
|
result = throw_exception( c_string_to_lisp_symbol( frame_pointer, U"cond" ),
|
||||||
c_string_to_lisp_string
|
c_string_to_lisp_string
|
||||||
(frame_pointer, L"Arguments to `cond` must be lists" ),
|
(frame_pointer, L"Arguments to `cond` must be lists" ),
|
||||||
frame_pointer );
|
frame_pointer );
|
||||||
|
|
@ -78,14 +79,10 @@ struct pso_pointer eval_cond_clause( struct pso_pointer clause,
|
||||||
*
|
*
|
||||||
* * (cond clauses...)
|
* * (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`.
|
* @return the value of the last expression of the first successful `clause`.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer
|
struct pso_pointer lisp_cond(struct pso_pointer frame_pointer) {
|
||||||
lisp_cond( struct pso4 *frame, struct pso_pointer frame_pointer,
|
struct pso4 *frame = pointer_to_pso4(frame_pointer);
|
||||||
struct pso_pointer env ) {
|
|
||||||
struct pso_pointer result = nil;
|
struct pso_pointer result = nil;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
|
|
@ -97,7 +94,7 @@ lisp_cond( struct pso4 *frame, struct pso_pointer frame_pointer,
|
||||||
// to nil, the form still succeeded and we should still exit `cond`.
|
// to nil, the form still succeeded and we should still exit `cond`.
|
||||||
//
|
//
|
||||||
|
|
||||||
result = eval_cond_clause( clause_pointer, frame, frame_pointer, env );
|
result = eval_cond_clause( clause_pointer, frame, frame_pointer );
|
||||||
|
|
||||||
if ( !c_nilp( result ) && c_truep( c_car( result ) ) ) {
|
if ( !c_nilp( result ) && c_truep( c_car( result ) ) ) {
|
||||||
result = c_cdr( result );
|
result = c_cdr( result );
|
||||||
|
|
@ -106,7 +103,7 @@ lisp_cond( struct pso4 *frame, struct pso_pointer frame_pointer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
debug_print( L"\tCond returning: ", DEBUG_EVAL, 0 );
|
debug_print( U"\tCond returning: ", DEBUG_EVAL, 0 );
|
||||||
debug_print_object( result, DEBUG_EVAL, 0 );
|
debug_print_object( result, DEBUG_EVAL, 0 );
|
||||||
debug_println( DEBUG_EVAL);
|
debug_println( DEBUG_EVAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
20
src/c/ops/cond.h
Normal file
20
src/c/ops/cond.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* ops/cond.h
|
||||||
|
*
|
||||||
|
* Post Scarcity Software Environment: cond.
|
||||||
|
*
|
||||||
|
* cond a name to a value 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_cond_h
|
||||||
|
#define __psse_ops_cond_h
|
||||||
|
|
||||||
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct pso_pointer lisp_cond( struct pso_pointer frame_pointer );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -131,7 +131,7 @@ struct pso_pointer eq(
|
||||||
* * symbols
|
* * symbols
|
||||||
* * strings
|
* * strings
|
||||||
*
|
*
|
||||||
* * (equal? arg1 qrg2)
|
* * (equal? arg1 arg2)
|
||||||
*
|
*
|
||||||
* @return `t` if all args are pointers to the same object, else `nil`;
|
* @return `t` if all args are pointers to the same object, else `nil`;
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -260,8 +260,7 @@ struct pso_pointer eval_forms( struct pso_pointer frame_pointer ) {
|
||||||
*
|
*
|
||||||
* This is experimental. It almost certainly WILL change.
|
* This is experimental. It almost certainly WILL change.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer lisp_try( struct pso_pointer frame_pointer,
|
struct pso_pointer lisp_try( struct pso_pointer frame_pointer) {
|
||||||
struct pso_pointer env ) {
|
|
||||||
struct pso_pointer result = nil;
|
struct pso_pointer result = nil;
|
||||||
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
||||||
struct pso_pointer body_frame =
|
struct pso_pointer body_frame =
|
||||||
|
|
@ -301,8 +300,7 @@ struct pso_pointer lisp_try( struct pso_pointer frame_pointer,
|
||||||
* @return the root namespace.
|
* @return the root namespace.
|
||||||
*/
|
*/
|
||||||
struct pso_pointer
|
struct pso_pointer
|
||||||
lisp_oblist( struct pso4 *frame, struct pso_pointer frame_pointer,
|
lisp_oblist( struct pso4 *frame, struct pso_pointer frame_pointer) {
|
||||||
struct pso_pointer env ) {
|
|
||||||
return oblist;
|
return oblist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -750,9 +748,6 @@ struct pso_pointer lisp_apply( struct pso_pointer frame_pointer) {
|
||||||
*
|
*
|
||||||
* * (eval expression)
|
* * (eval expression)
|
||||||
*
|
*
|
||||||
* @param frame my pso4.
|
|
||||||
* @param frame_pointer a pointer to my pso4.
|
|
||||||
* @param env my environment.
|
|
||||||
* @return
|
* @return
|
||||||
* * If `expression` is a number, string, `nil`, or `t`, returns `expression`.
|
* * If `expression` is a number, string, `nil`, or `t`, returns `expression`.
|
||||||
* * If `expression` is a symbol, returns the value that expression is bound
|
* * If `expression` is a symbol, returns the value that expression is bound
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,7 @@
|
||||||
#include "ops/stack_ops.h"
|
#include "ops/stack_ops.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: dump/inspect one complete lisp expression and return nil. If
|
* Function: dump/
|
||||||
* 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)
|
||||||
* * (inspect expr write-stream)
|
* * (inspect expr write-stream)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
* Licensed under GPL version 2.0, or, at your option, any later version.
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef psse_ops_inspect
|
#ifndef psse_ops_inspect_h
|
||||||
#define psse_ops_inspect
|
#define psse_ops_inspect_h
|
||||||
|
|
||||||
#include "memory/pointer.h"
|
#include "memory/pointer.h"
|
||||||
|
|
||||||
|
|
|
||||||
25
src/c/payloads/function.c
Normal file
25
src/c/payloads/function.c
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* payloads/function.c
|
||||||
|
*
|
||||||
|
* an ordinary Lisp function - one whose arguments are pre-evaluated.
|
||||||
|
*
|
||||||
|
* (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/tags.h"
|
||||||
|
|
||||||
|
struct pso_pointer make_function(
|
||||||
|
struct pso_pointer frame_pointer, struct pso_pointer meta,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer frame_pointer)) {
|
||||||
|
struct pso_pointer result = allocate(frame_pointer, FUNCTIONTAG, 2);
|
||||||
|
struct pso2 *object = pointer_to_object(result);
|
||||||
|
|
||||||
|
object->payload.function.meta = meta;
|
||||||
|
object->payload.function.executable = executable;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -39,4 +39,8 @@ struct function_payload {
|
||||||
struct pso_pointer ( *executable ) ( struct pso_pointer frame_pointer );
|
struct pso_pointer ( *executable ) ( struct pso_pointer frame_pointer );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pso_pointer make_function(
|
||||||
|
struct pso_pointer frame_pointer, struct pso_pointer meta,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer frame_pointer));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
25
src/c/payloads/special.c
Normal file
25
src/c/payloads/special.c
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* payloads/special.c
|
||||||
|
*
|
||||||
|
* a special Lisp function - one whose arguments are **not** pre-evaluated.
|
||||||
|
*
|
||||||
|
* (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/tags.h"
|
||||||
|
|
||||||
|
struct pso_pointer make_special(
|
||||||
|
struct pso_pointer frame_pointer, struct pso_pointer meta,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer frame_pointer)) {
|
||||||
|
struct pso_pointer result = allocate(frame_pointer, SPECIALTAG, 2);
|
||||||
|
struct pso2 *object = pointer_to_object(result);
|
||||||
|
|
||||||
|
object->payload.special.meta = meta;
|
||||||
|
object->payload.special.executable = executable;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -18,8 +18,12 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A special form - one whose arguments are not pre-evaluated but passed as
|
* A special form - one whose arguments are not pre-evaluated but passed as
|
||||||
* provided.
|
* provided. Shares payload with function, q.v.
|
||||||
* \see NLAMBDATAG.
|
* \see NLAMBDATAG.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct pso_pointer make_special(
|
||||||
|
struct pso_pointer frame_pointer, struct pso_pointer meta,
|
||||||
|
struct pso_pointer (*executable)(struct pso_pointer frame_pointer));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue