feat: hectic C: generic result

This commit is contained in:
2025-04-12 15:21:33 +00:00
parent db5b88388e
commit 1f25c4fcad
4 changed files with 107 additions and 52 deletions

View File

@@ -226,10 +226,27 @@ char *string_to_debug_str__(CTX_DECLARATION, const char *name, const char *strin
return arena_strdup_fmt__(CTX(arena), "%s = %p \"%s\"", name, string, string); return arena_strdup_fmt__(CTX(arena), "%s = %p \"%s\"", name, string, string);
} }
char *number_to_debug_str__(CTX_DECLARATION, const char *name, int number) { char *int_to_debug_str__(CTX_DECLARATION, const char *name, int number) {
return arena_strdup_fmt__(CTX(arena), "%s = %d", name, number); return arena_strdup_fmt__(CTX(arena), "%s = %d", name, number);
} }
char *float_to_debug_str__(CTX_DECLARATION, const char *name, double number) {
return arena_strdup_fmt__(CTX(arena), "%s = %f", name, number);
}
char *size_t_to_debug_str__(CTX_DECLARATION, const char *name, size_t number) {
return arena_strdup_fmt__(CTX(arena), "%s = %zu", name, number);
}
char *ptr_to_debug_str__(CTX_DECLARATION, const char *name, void *ptr) {
return arena_strdup_fmt__(CTX(arena), "%s = %p", name, ptr);
}
char *char_to_debug_str__(CTX_DECLARATION, const char *name, char c) {
return arena_strdup_fmt__(CTX(arena), "%s = %c", name, c);
}
/* Private function */ /* Private function */
char *debug_join_debug_strings_v(CTX_DECLARATION, int count, va_list args) { char *debug_join_debug_strings_v(CTX_DECLARATION, int count, va_list args) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "DEBUG JOIN: Joining %d strings", count); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "DEBUG JOIN: Joining %d strings", count);
@@ -1718,6 +1735,19 @@ char* logger_rules_to_string(Arena *arena) {
return buffer; return buffer;
} }
char *log_rules_to_debug_str__(CTX_DECLARATION, char *name, LogRule *self, PtrSet *visited) {
char *result = arena_alloc(arena, MEM_KiB);
STRUCT_TO_DEBUG_STR(arena, result, LogRule, name, self, visited, 6,
string_to_debug_str__(POSITION_INFO, arena, "level", log_level_to_string(self->level)),
string_to_debug_str__(POSITION_INFO, arena, "file_pattern", self->file_pattern),
string_to_debug_str__(POSITION_INFO, arena, "function_pattern", self->function_pattern),
int_to_debug_str__(POSITION_INFO, arena, "line_start", self->line_start),
int_to_debug_str__(POSITION_INFO, arena, "line_end", self->line_end),
log_rules_to_debug_str__(POSITION_INFO, arena, "next", self->next, visited)
);
return result;
}
// --------------- // ---------------
// -- Templater -- // -- Templater --
// --------------- // ---------------
@@ -1760,16 +1790,6 @@ bool template_validate_config__(POSITION_INFO_DECLARATION, const TemplateConfig
return false; return false;
} }
assert(config->Syntax.Braces.open != NULL);
assert(config->Syntax.Braces.close != NULL);
assert(config->Syntax.Section.control != NULL);
assert(config->Syntax.Section.source != NULL);
assert(config->Syntax.Section.begin != NULL);
assert(config->Syntax.Interpolate.invoke != NULL);
assert(config->Syntax.Include.invoke != NULL);
assert(config->Syntax.Execute.invoke != NULL);
assert(config->Syntax.nesting != NULL);
CHECK_CONFIG_STR(Braces.open, "Open brace"); CHECK_CONFIG_STR(Braces.open, "Open brace");
CHECK_CONFIG_STR(Braces.close, "Close brace"); CHECK_CONFIG_STR(Braces.close, "Close brace");
CHECK_CONFIG_STR(Section.control, "Section control"); CHECK_CONFIG_STR(Section.control, "Section control");
@@ -1788,7 +1808,7 @@ bool template_validate_config__(POSITION_INFO_DECLARATION, const TemplateConfig
#define TEMPLATE_ASSERT_SYNTAX(pattern, message_arg, code_arg) \ #define TEMPLATE_ASSERT_SYNTAX(pattern, message_arg, code_arg) \
if (strncmp(*s, pattern, strlen(pattern))) { \ if (strncmp(*s, pattern, strlen(pattern))) { \
raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, "PARSE: " message_arg); \ raise_message(LOG_LEVEL_EXCEPTION, POSITION_INFO, "PARSE: " message_arg); \
result->type = TEMPLATE_RESULT_ERROR; \ result->type = RESULT_ERROR; \
result->Result.error.code = code_arg; \ result->Result.error.code = code_arg; \
result->Result.error.message = message_arg; \ result->Result.error.message = message_arg; \
return result; \ return result; \
@@ -1819,10 +1839,10 @@ TemplateResult *template_parse_interpolation__(POSITION_INFO_DECLARATION, Arena
} }
size_t key_len = *s - key_start; size_t key_len = *s - key_start;
result->Result.node.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len); result->Result.some.value.interpolate.key = arena_strncpy__(POSITION_INFO, arena, key_start, key_len);
result->type = TEMPLATE_RESULT_NODE; result->type = RESULT_SOME;
result->Result.node.type = TEMPLATE_NODE_INTERPOLATE; result->Result.some.type = TEMPLATE_NODE_INTERPOLATE;
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1833,8 +1853,8 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Section");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->type = TEMPLATE_RESULT_NODE; result->type = RESULT_SOME;
result->Result.node.type = TEMPLATE_NODE_SECTION; result->Result.some.type = TEMPLATE_NODE_SECTION;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1856,7 +1876,7 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t iterator_len = *s - iterator_start; size_t iterator_len = *s - iterator_start;
result->Result.node.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len); result->Result.some.value.section.iterator = arena_strncpy__(POSITION_INFO, arena, iterator_start, iterator_len);
// Find the collection name // Find the collection name
*s = skip_whitespace(*s); *s = skip_whitespace(*s);
@@ -1871,15 +1891,15 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t collection_len = *s - collection_start; size_t collection_len = *s - collection_start;
result->Result.node.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len); result->Result.some.value.section.collection = arena_strncpy__(POSITION_INFO, arena, collection_start, collection_len);
// Parse the body // Parse the body
TemplateResult *body_result = template_parse__(POSITION_INFO, arena, s, config); TemplateResult *body_result = template_parse__(POSITION_INFO, arena, s, config);
if (body_result->type == TEMPLATE_RESULT_ERROR) { if (body_result->type == RESULT_ERROR) {
return body_result; return body_result;
} }
result->Result.node.value.section.body = &body_result->Result.node; result->Result.some.value.section.body = &body_result->Result.some;
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1889,8 +1909,8 @@ TemplateResult *template_parse_section__(POSITION_INFO_DECLARATION, Arena *arena
TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena, const char **s_ptr, const TemplateConfig *config) { TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena, const char **s_ptr, const TemplateConfig *config) {
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Include"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Include");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->type = TEMPLATE_RESULT_NODE; result->type = RESULT_SOME;
result->Result.node.type = TEMPLATE_NODE_INCLUDE; result->Result.some.type = TEMPLATE_NODE_INCLUDE;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1910,7 +1930,7 @@ TemplateResult *template_parse_include__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t include_len = *s - include_start; size_t include_len = *s - include_start;
result->Result.node.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len); result->Result.some.value.include.key = arena_strncpy__(POSITION_INFO, arena, include_start, include_len);
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -1921,8 +1941,8 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena
raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Execute"); raise_message(LOG_LEVEL_TRACE, POSITION_INFO, "PARSE: Execute");
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->type = TEMPLATE_RESULT_NODE; result->type = RESULT_SOME;
result->Result.node.type = TEMPLATE_NODE_EXECUTE; result->Result.some.type = TEMPLATE_NODE_EXECUTE;
const char **s = s_ptr; const char **s = s_ptr;
@@ -1939,7 +1959,7 @@ TemplateResult *template_parse_execute__(POSITION_INFO_DECLARATION, Arena *arena
} }
size_t code_len = *s - code_start; size_t code_len = *s - code_start;
result->Result.node.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len); result->Result.some.value.execute.code = arena_strncpy__(POSITION_INFO, arena, code_start, code_len);
*s_ptr = *s + strlen(config->Syntax.Braces.close); *s_ptr = *s + strlen(config->Syntax.Braces.close);
@@ -2002,7 +2022,7 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
TemplateResult *error_result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *error_result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
error_result->type = TEMPLATE_RESULT_ERROR; error_result->type = RESULT_ERROR;
error_result->Result.error.code = TEMPLATE_ERROR_UNKNOWN_TAG; error_result->Result.error.code = TEMPLATE_ERROR_UNKNOWN_TAG;
error_result->Result.error.message = "Unknown tag prefix"; error_result->Result.error.message = "Unknown tag prefix";
@@ -2010,11 +2030,11 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
} }
} }
if (current_result->type == TEMPLATE_RESULT_ERROR) { if (current_result->type == RESULT_ERROR) {
return current_result; return current_result;
} }
*current = current_result->Result.node; *current = current_result->Result.some;
current->next = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode)); current->next = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateNode));
current = current->next; current = current->next;
} }
@@ -2029,8 +2049,8 @@ TemplateResult *template_parse__(POSITION_INFO_DECLARATION, Arena *arena, const
} }
TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult)); TemplateResult *result = arena_alloc__(POSITION_INFO, arena, sizeof(TemplateResult));
result->type = TEMPLATE_RESULT_NODE; result->type = RESULT_SOME;
result->Result.node = *root; result->Result.some = *root;
return result; return result;
} }

View File

@@ -55,6 +55,20 @@ void set_output_color_mode(ColorMode mode);
#define OPTIONAL_COLOR(color) (USE_COLOR() ? color : "") #define OPTIONAL_COLOR(color) (USE_COLOR() ? color : "")
typedef enum {
RESULT_ERROR,
RESULT_SOME,
} ResultType;
#define RESULT(name, error_type, result_type) \
typedef struct { \
ResultType type; \
union { \
error_type error; \
result_type some; \
} Result; \
} name##Result
// ------------ // ------------
// -- Errors -- // -- Errors --
// ------------ // ------------
@@ -378,14 +392,30 @@ char* logger_rules_to_string(Arena *arena);
char *string_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, const char *string); char *string_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, const char *string);
char *number_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, int number); char *int_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, int number);
char *float_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, double number);
char *size_t_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, size_t number);
char *ptr_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, void *ptr);
char *char_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *name, char c);
char *struct_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *type, const char *name, void *ptr, int count, ...); char *struct_to_debug_str__(const char *file, const char *func, int line, Arena *arena, const char *type, const char *name, void *ptr, int count, ...);
#define STRING_TO_DEBUG_STR(arena, name, string) \ #define STRING_TO_DEBUG_STR(arena, name, string) \
string_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, string) string_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, string)
#define NUMBER_TO_DEBUG_STR(arena, name, number) \ #define INT_TO_DEBUG_STR(arena, name, number) \
number_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number) int_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number)
#define FLOAT_TO_DEBUG_STR(arena, name, number) \
float_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number)
#define SIZE_T_TO_DEBUG_STR(arena, name, number) \
size_t_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, number)
#define PTR_TO_DEBUG_STR(arena, name, ptr) \
ptr_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, ptr)
#define CHAR_TO_DEBUG_STR(arena, name, c) \
char_to_debug_str__(__FILE__, __func__, __LINE__, arena, name, c)
bool debug_ptrset_contains(PtrSet *set, void *ptr); bool debug_ptrset_contains(PtrSet *set, void *ptr);
@@ -600,18 +630,7 @@ struct TemplateNode {
TemplateNode *next; // sibling nodes TemplateNode *next; // sibling nodes
}; };
typedef enum { RESULT(Template, TemplateError, TemplateNode);
TEMPLATE_RESULT_ERROR,
TEMPLATE_RESULT_NODE,
} TemplateResultType;
typedef struct {
TemplateResultType type;
union {
TemplateError error;
TemplateNode node;
} Result;
} TemplateResult;
TemplateResult *template_parse__(const char *file, const char *func, int line, Arena *arena, const char **s, const TemplateConfig *config); TemplateResult *template_parse__(const char *file, const char *func, int line, Arena *arena, const char **s, const TemplateConfig *config);

View File

@@ -25,8 +25,8 @@ char *struct_to_debug_str(Arena *arena, char *name, Struct *self, PtrSet *visite
char *result = arena_alloc(arena, MEM_KiB); char *result = arena_alloc(arena, MEM_KiB);
STRUCT_TO_DEBUG_STR(arena, result, Struct, name, self, visited, 3, STRUCT_TO_DEBUG_STR(arena, result, Struct, name, self, visited, 3,
NUMBER_TO_DEBUG_STR(arena, "a", self->a), INT_TO_DEBUG_STR(arena, "a", self->a),
NUMBER_TO_DEBUG_STR(arena, "b", self->b), INT_TO_DEBUG_STR(arena, "b", self->b),
struct_to_debug_str(arena, "next", self->next, visited) struct_to_debug_str(arena, "next", self->next, visited)
); );
return result; return result;
@@ -37,8 +37,8 @@ char *struct2_to_debug_str(Arena *arena, char *name, Struct2 *self, PtrSet *visi
char *result = arena_alloc(arena, MEM_KiB); char *result = arena_alloc(arena, MEM_KiB);
STRUCT_TO_DEBUG_STR(arena, result, Struct2, name, self, visited, 5, STRUCT_TO_DEBUG_STR(arena, result, Struct2, name, self, visited, 5,
NUMBER_TO_DEBUG_STR(arena, "a", self->a), INT_TO_DEBUG_STR(arena, "a", self->a),
NUMBER_TO_DEBUG_STR(arena, "f", self->f), FLOAT_TO_DEBUG_STR(arena, "f", self->f),
STRING_TO_DEBUG_STR(arena, "c", self->c), STRING_TO_DEBUG_STR(arena, "c", self->c),
struct_to_debug_str(arena, "other", self->other, visited), struct_to_debug_str(arena, "other", self->other, visited),
struct2_to_debug_str(arena, "left", self->left, visited) struct2_to_debug_str(arena, "left", self->left, visited)
@@ -74,7 +74,7 @@ void test_struct2_to_debug_str(Arena *arena) {
char *result = struct2_to_debug_str(arena, "struct2", &test_struct2, visited); char *result = struct2_to_debug_str(arena, "struct2", &test_struct2, visited);
raise_notice("result: %s", result); raise_notice("result: %s", result);
char *check = arena_alloc(arena, MEM_KiB); char *check = arena_alloc(arena, MEM_KiB);
sprintf(check, "Struct2 struct2 = {a = 1, f = 3, c = %p \"hello\", Struct other = {a = 1, b = 2, Struct next = {cycle detected} %p} %p, Struct2 left = NULL} %p", (void*)test_struct2.c,(void*)&test_struct, (void*)&test_struct, (void*)&test_struct2); sprintf(check, "Struct2 struct2 = {a = 1, f = 3.140000, c = %p \"hello\", Struct other = {a = 1, b = 2, Struct next = {cycle detected} %p} %p, Struct2 left = NULL} %p", (void*)test_struct2.c,(void*)&test_struct, (void*)&test_struct, (void*)&test_struct2);
raise_notice("check: %s", check); raise_notice("check: %s", check);
assert(strcmp(result, check) == 0); assert(strcmp(result, check) == 0);
} }

View File

@@ -0,0 +1,16 @@
#include "hectic.h"
#include <assert.h>
int main(void) {
printf("%sRunning %s%s%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_CYAN), __FILE__, OPTIONAL_COLOR(COLOR_RESET));
init_logger();
Arena arena = arena_init(MEM_MiB);
char *rules = arena_alloc(&arena, MEM_KiB);
strcpy(rules, "trace:file:test.c:100-150");
arena_free(&arena);
printf("%sAll tests passed %s%s%s\n", OPTIONAL_COLOR(COLOR_GREEN), OPTIONAL_COLOR(COLOR_CYAN), __FILE__, OPTIONAL_COLOR(COLOR_RESET));
return 0;
}