tlibc/include/tlibc/errors.h
2025-07-21 17:57:28 +03:00

62 lines
1.5 KiB
C
Executable File

#pragma once
#include "std.h"
#include "string/str.h"
#include "collections/List.h"
typedef struct ErrorCallPos {
i32 line;
str file;
str func;
} ErrorCallPos;
#define ErrorCallPos_here() (ErrorCallPos){\
.line = __LINE__,\
.file = str_construct((char*)(void*)__FILE__, sizeof(__FILE__), true),\
.func = str_construct((char*)(void*)__func__, sizeof(__func__), true)\
}
typedef struct Error {
str msg;
bool is_msg_on_heap;
/* List<ErrorCallPos> */
List call_stack;
} Error;
Error* Error_create(const char* msg, bool is_msg_on_heap, ErrorCallPos);
void Error_destroy(Error* e);
void Error_addCallPos(Error* e, ErrorCallPos p);
str Error_toStr(Error* e);
void Error_printAndExit(Error* e) __attribute__ ((__noreturn__));
typedef struct Result_ {
Error* error;
union {
u64 v_u64;
i64 v_i64;
f32 v_f32;
f64 v_f64;
void* v_ptr;
};
} Result_;
#define Result(T) Result_
#define RESULT_ERROR(MSG, IS_MSG_ON_HEAP) (Result_){ .error = Error_create(MSG, IS_MSG_ON_HEAP, ErrorCallPos_here()) }
#define RESULT_VOID (Result_){ .error = NULL }
#define RESULT_VALUE(TYPE, V) (Result_){ .error = NULL, .v_##TYPE = V }
#define try(VAR, RSLT_CALL, DEFER_CODE) \
Result_ VAR = RSLT_CALL;\
if(VAR.error){\
Error_addCallPos(VAR.error, ErrorCallPos_here());\
DEFER_CODE;\
return VAR;\
};
#define try_fatal(VAR, RSLT_CALL, DEFER_CODE) \
Result_ VAR = RSLT_CALL;\
if(VAR.error){\
DEFER_CODE;\
Error_printAndExit(VAR.error);\
};