/** * ops/reverse.c * * Post Scarcity Software Environment: reverse. * * Reverse a sequence. Didn'e want to do this in the substrate, but I need * if for reading atoms!. * * (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/pso.h" #include "memory/pso2.h" #include "memory/pso4.h" #include "memory/tags.h" #include "payloads/stack.h" #include "payloads/cons.h" #include "payloads/exception.h" #include "payloads/psse_string.h" #include "ops/string_ops.h" #include "ops/truth.h" #include "payloads/stack.h" /** * @brief reverse a sequence * * (reverse sequence) */ struct pso_pointer reverse( struct pso_pointer frame_pointer ) { struct pso_pointer result = nil; struct pso_pointer sequence = fetch_arg( pointer_to_pso4( frame_pointer ), 0 ); for ( struct pso_pointer cursor = sequence; !c_nilp( cursor ); cursor = c_cdr( cursor ) ) { struct pso2 *object = pointer_to_object( cursor ); switch ( get_tag_value( cursor ) ) { case CONSTV: result = push_local( frame_pointer, make_cons( frame_pointer, c_car( cursor ), result ) ); break; case KEYTV: result = push_local( frame_pointer, make_string_like_thing( frame_pointer, object->payload. string.character, result, KEYTAG ) ); break; case STRINGTV: result = push_local( frame_pointer, make_string_like_thing( frame_pointer, object->payload. string.character, result, STRINGTAG ) ); break; case SYMBOLTV: result = push_local( frame_pointer, make_string_like_thing( frame_pointer, object->payload. string.character, result, SYMBOLTAG ) ); break; default: result = push_local( frame_pointer, make_exception( make_frame ( 1, frame_pointer, make_cons ( frame_pointer, c_string_to_lisp_string ( frame_pointer, L"Invalid object in sequence" ), cursor ) ) ) ); goto exit; break; } } exit: return result; } /** * @brief reverse a sequence. * * A sequence is a list or a string-like-thing. A dotted pair is not a * sequence. * * @param sequence a pointer to a sequence. * @return a sequence like the `sequence` passed, but reversed; or `nil` if * the argument was not a sequence. */ struct pso_pointer c_reverse( struct pso_pointer frame_pointer, struct pso_pointer sequence ) { struct pso_pointer result = nil; if ( stackp( frame_pointer ) ) { result = reverse( make_frame(1, frame_pointer, sequence) ); } return result; }