92 lines
2.9 KiB
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;
|
|
}
|