/** * ops/assoc.c * * Post Scarcity Software Environment: assoc. * * Search a store for the value associated with a key. * * (c) 2026 Simon Brooke * Licensed under GPL version 2.0, or, at your option, any later version. */ #include #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; if ( consp( store ) ) { for ( struct pso_pointer cursor = store; consp( cursor ) && found == false; cursor = c_cdr( cursor ) ) { struct pso_pointer pair = c_car( cursor ); if ( consp( pair ) && c_equal( c_car( pair ), key ) ) { found = true; result = return_key ? c_car( pair ) : c_cdr( pair ); } } } 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; }