/** * 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/tags.h" #include "payloads/cons.h" #include "payloads/exception.h" #include "payloads/psse_string.h" #include "ops/string_ops.h" #include "ops/truth.h" /** * @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 ) { // todo: issue #21: must have stack frame passed in. struct pso_pointer result = nil; for ( struct pso_pointer cursor = sequence; !c_nilp( sequence ); cursor = c_cdr( cursor ) ) { struct pso2 *object = pointer_to_object( cursor ); switch ( get_tag_value( cursor ) ) { case CONSTV: result = make_cons( frame_pointer, c_car( cursor ), result ); break; case KEYTV: // TODO: should you be able to reverse keywords and symbols? result = make_string_like_thing( frame_pointer, object->payload.string.character, result, KEYTAG ); break; case STRINGTV: result = make_string_like_thing( frame_pointer, object->payload.string.character, result, STRINGTAG ); break; case SYMBOLTV: // TODO: should you be able to reverse keywords and symbols? result = make_string_like_thing( frame_pointer, object->payload.string.character, result, SYMBOLTAG ); break; default: result = 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; }