post-scarcity/src/c/payloads/exception.c

92 lines
2.9 KiB
C

/**
* payloads/exception.c
*
* An exception; required three pointers, so use object of size class 3.
*
* (c) 2026 Simon Brooke <simon@journeyman.cc>
* Licensed under GPL version 2.0, or, at your option, any later version.
*/
#include <stdlib.h>
/*
* wide characters
*/
#include <wchar.h>
#include <wctype.h>
#include "memory/node.h"
#include "memory/pointer.h"
#include "memory/pso.h"
#include "memory/pso3.h"
#include "memory/pso4.h"
#include "memory/tags.h"
#include "payloads/exception.h"
#include "ops/stack_ops.h"
#include "ops/truth.h"
#include <stdlib.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdlib.h>
/**
* @brief allocate an exception object, and, if successful, return a pointer
* to it.
*
* (exception message meta cause)
*
* Throwing an exception while generating an exception is meaningless. If
* allocation fails utterly (i.e. out of heap, out of page space) this will
* have to return `nil`, which might give rise to hard to trace bugs. But
* otherwise it will return a pointer to a new exception.
*
* @param message expected to be a string, but anything printable is accepted.
b * @param meta metadata for this exception. Must be an assoc list, hashtable,
* or `nil`
* @param cause the exception that caused this exception to be `thrown`.
*/
struct pso_pointer make_exception( struct pso_pointer frame_pointer ) {
struct pso4 *frame = pointer_to_pso4( frame_pointer );
struct pso_pointer message = fetch_arg( frame, 0 );
struct pso_pointer previous = frame->payload.stack_frame.previous;
struct pso_pointer meta = fetch_arg( frame, 1 );
struct pso_pointer cause = fetch_arg( frame, 2 );
struct pso_pointer result = allocate( frame_pointer, EXCEPTIONTAG, 3 );
if ( !c_nilp( result ) && !exceptionp( result ) ) {
struct pso3 *object = ( struct pso3 * ) pointer_to_object( result );
object->payload.exception.message = message;
object->payload.exception.stack =
stackp( frame_pointer ) ? frame_pointer : nil;
object->payload.exception.meta = ( consp( meta )
|| hashtabp( meta ) ) ? meta : nil;
object->payload.exception.cause = exceptionp( cause ) ? cause : nil;
}
return result;
}
/**
* @brief When an exception is freed, all its pointers must be decremented.
*
* Lisp calling conventions; one expected arg, the pointer to the object to
* be destroyed.
*/
struct pso_pointer destroy_exception( struct pso_pointer fp ) {
if ( stackp( fp ) ) {
struct pso4 *frame = pointer_to_pso4( fp );
struct pso_pointer p = frame->payload.stack_frame.arg[0];
struct pso3 *object = ( struct pso3 * ) pointer_to_object( p );
dec_ref( object->payload.exception.message );
dec_ref( object->payload.exception.stack );
dec_ref( object->payload.exception.meta );
dec_ref( object->payload.exception.cause );
}
return nil;
}