Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions source/metacall/include/metacall/metacall_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ METACALL_API int metacall_error_last(metacall_exception ex);
*/
METACALL_API void metacall_error_clear(void);

/**
* @brief
* Record a throwable value as the last error for the calling thread. Called
* internally by metacallfv_s when a loader returns a TYPE_THROWABLE value.
* May also be called by ports or loaders that want to set the last error
* directly. Copies @v so the caller retains ownership of the original value.
*
* @param[in] v
* Throwable value to record; must be of type TYPE_THROWABLE
*/
METACALL_API void metacall_error_set_last(void *v);

#ifdef __cplusplus
}
#endif
Expand Down
5 changes: 5 additions & 0 deletions source/metacall/source/metacall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,11 @@ void *metacallfv_s(void *func, void *args[], size_t size)

ret = function_call(f, args, size);

if (ret != NULL && type_id_throwable(value_type_id(ret)) == 0)
{
metacall_error_set_last(ret);
}

if (ret != NULL)
{
type t = signature_get_return(s);
Expand Down
35 changes: 31 additions & 4 deletions source/metacall/source/metacall_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@

#include <reflect/reflect_value_type.h>

#include <portability/portability_compiler.h>

#include <log/log.h>

/* -- Private Variables -- */

static PORTABILITY_THREAD_LOCAL value metacall_error_last_v = NULL;

/* -- Methods -- */

void *metacall_error_throw(const char *label, int64_t code, const char *stacktrace, const char *message, ...)
Expand Down Expand Up @@ -92,13 +98,34 @@ int metacall_error_from_value(void *v, metacall_exception ex)

int metacall_error_last(metacall_exception ex)
{
// TODO
(void)ex;
if (metacall_error_last_v == NULL)
{
return 1;
}

return 1;
return metacall_error_from_value(metacall_error_last_v, ex);
}

void metacall_error_clear(void)
{
// TODO
if (metacall_error_last_v != NULL)
{
value_type_destroy(metacall_error_last_v);
metacall_error_last_v = NULL;
}
}

void metacall_error_set_last(void *v)
{
if (v == NULL || type_id_throwable(value_type_id((value)v)) != 0)
{
return;
}

if (metacall_error_last_v != NULL)
{
value_type_destroy(metacall_error_last_v);
}

metacall_error_last_v = value_type_copy((value)v);
}