as the focus ot this prototype is supposed to be building things in Lisp, I've started deliberately copying stuff that mostly works directly from the 0.0.6 branch into this branch. After all, if it's going to be replaced in Lisp, it doesn't have to be the most elegant C.
176 lines
5.6 KiB
C
176 lines
5.6 KiB
C
/**
|
|
* ops/assoc.c
|
|
*
|
|
* Post Scarcity Software Environment: assoc.
|
|
*
|
|
* Search a store for the value associated with a key.
|
|
*
|
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "debug.h"
|
|
#include "memory/node.h"
|
|
#include "memory/pointer.h"
|
|
#include "memory/pso2.h"
|
|
#include "memory/tags.h"
|
|
|
|
#include "payloads/cons.h"
|
|
#include "payloads/stack.h"
|
|
|
|
#include "ops/eq.h"
|
|
#include "ops/stack_ops.h"
|
|
#include "ops/truth.h"
|
|
|
|
/**
|
|
* @brief: fundamental search function; only knows about association lists
|
|
*
|
|
* @param key a pointer indicating the key to search for;
|
|
* @param store a pointer indicating the store to search;
|
|
* @param return_key if a binding is found for `key` in `store`, if true
|
|
* return the key found in the store, else return the value
|
|
*
|
|
* @return nil if no binding for `key` is found in `store`; otherwise, if
|
|
* `return_key` is true, return the key from the store; else
|
|
* return the binding.
|
|
*/
|
|
struct pso_pointer search( struct pso_pointer key,
|
|
struct pso_pointer store, bool return_key ) {
|
|
struct pso_pointer result = nil;
|
|
bool found = false;
|
|
|
|
#ifdef DEBUG
|
|
debug_print( L"In search; key is: ", DEBUG_BIND, 0 );
|
|
debug_print_object( key, DEBUG_BIND, 0 );
|
|
debug_println( DEBUG_BIND );
|
|
#endif
|
|
|
|
if ( consp( store ) ) {
|
|
for ( struct pso_pointer cursor = store;
|
|
consp( cursor ) && found == false; cursor = c_cdr( cursor ) ) {
|
|
struct pso_pointer pair = c_car( cursor );
|
|
#ifdef DEBUG
|
|
debug_print( L"Checking ", DEBUG_BIND, 2 );
|
|
debug_print_object( pair, DEBUG_BIND, 0 );
|
|
#endif
|
|
|
|
if ( consp( pair ) && c_equal( c_car( pair ), key ) ) {
|
|
found = true;
|
|
result = return_key ? c_car( pair ) : c_cdr( pair );
|
|
#ifdef DEBUG
|
|
debug_print( L" ...found!", DEBUG_BIND, 0 );
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
debug_println( DEBUG_BIND );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer assoc; only knows about association lists.
|
|
*
|
|
* @param key a pointer indicating the key to search for;
|
|
* @param store a pointer indicating the store to search;
|
|
*
|
|
* @return a pointer to the value of the key in the store, or nil if not found
|
|
*/
|
|
struct pso_pointer c_assoc( struct pso_pointer key, struct pso_pointer store ) {
|
|
return search( key, store, false );
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer interned; only knows about association lists.
|
|
*
|
|
* @param key a pointer indicating the key to search for;
|
|
* @param store a pointer indicating the store to search;
|
|
*
|
|
* @return a pointer to the copy of the key in the store, or nil if not found.
|
|
*/
|
|
struct pso_pointer c_interned( struct pso_pointer key,
|
|
struct pso_pointer store ) {
|
|
return search( key, store, true );
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer interned; only knows about association lists.
|
|
*
|
|
* @param key a pointer indicating the key to search for;
|
|
* @param store a pointer indicating the store to search;
|
|
*
|
|
* @return `true` if a pointer the key was found in the store..
|
|
*/
|
|
bool c_internedp( struct pso_pointer key, struct pso_pointer store ) {
|
|
return !c_nilp( search( key, store, true ) );
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer assoc; Lisp calling signature.
|
|
*
|
|
* @return a pointer to the value of the key in the store, or nil if not found
|
|
*/
|
|
struct pso_pointer assoc(
|
|
#ifndef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame,
|
|
#endif
|
|
struct pso_pointer frame_pointer ) {
|
|
#ifdef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
|
#endif
|
|
struct pso_pointer key = fetch_arg( frame, 0 );
|
|
struct pso_pointer store = or( make_frame( 2, frame_pointer,
|
|
fetch_arg( frame, 1 ),
|
|
frame->payload.
|
|
stack_frame.env ) );
|
|
|
|
return c_assoc( key, store );
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer interned; Lisp calling signature.
|
|
*
|
|
* @return a pointer to the copy of the key in the store, or nil if not found.
|
|
*/
|
|
struct pso_pointer interned(
|
|
#ifndef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame,
|
|
#endif
|
|
struct pso_pointer frame_pointer ) {
|
|
#ifdef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
|
#endif
|
|
struct pso_pointer key = fetch_arg( frame, 0 );
|
|
struct pso_pointer store = or( make_frame( 2, frame_pointer,
|
|
fetch_arg( frame, 1 ),
|
|
frame->payload.
|
|
stack_frame.env ) );
|
|
|
|
return c_interned( key, store );
|
|
}
|
|
|
|
/**
|
|
* @prief: bootstap layer interned?; Lisp calling signature.
|
|
*
|
|
* @return `t` if a pointer to a copy of `key` is found in the store, or `nil` if not found.
|
|
*/
|
|
struct pso_pointer internedp(
|
|
#ifndef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame,
|
|
#endif
|
|
struct pso_pointer frame_pointer ) {
|
|
#ifdef MANAGED_POINTER_ONLY
|
|
struct pso4 *frame = pointer_to_pso4( frame_pointer );
|
|
#endif
|
|
struct pso_pointer key = fetch_arg( frame, 0 );
|
|
struct pso_pointer store = or( make_frame( 2, frame_pointer,
|
|
fetch_arg( frame, 1 ),
|
|
frame->payload.
|
|
stack_frame.env ) );
|
|
|
|
return c_internedp( key, store ) ? t : nil;
|
|
}
|