Skip to content

Commit

Permalink
assert: Include assert message in error message if there is one
Browse files Browse the repository at this point in the history
  • Loading branch information
obiwac committed Dec 21, 2024
1 parent ec5beae commit f3b1510
Showing 1 changed file with 59 additions and 5 deletions.
64 changes: 59 additions & 5 deletions flamingo/grammar/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
#include "../val.h"

static int parse_assert(flamingo_t* flamingo, TSNode node) {
assert(ts_node_child_count(node) == 2);
size_t const child_count = ts_node_named_child_count(node);
assert(child_count == 1 || child_count == 2);

// Get test expression.

TSNode const test_node = ts_node_child_by_field_name(node, "test", 4);
char const* const type = ts_node_type(test_node);
Expand All @@ -18,6 +21,21 @@ static int parse_assert(flamingo_t* flamingo, TSNode node) {
return error(flamingo, "expected expression for test, got %s", type);
}

// Get message.

TSNode const msg_node = ts_node_child_by_field_name(node, "msg", 3);
bool const has_msg = !ts_node_is_null(msg_node);

if (has_msg) {
char const* const msg_type = ts_node_type(msg_node);

if (strcmp(msg_type, "expression") != 0) {
return error(flamingo, "expected expression for message, got %s", msg_type);
}
}

// Evaluate the test expression.

flamingo_val_t* val = NULL;

if (parse_expr(flamingo, test_node, &val, NULL) < 0) {
Expand All @@ -28,16 +46,52 @@ static int parse_assert(flamingo_t* flamingo, TSNode node) {
return error(flamingo, "expected boolean value for test, got %s", val_type_str(val));
}

// If the test succeeded, exit now.

if (val->boolean.boolean) {
val_decref(val);
return 0;
}

// Otherwise, start by getting a string for the test expression.

size_t const start = ts_node_start_byte(test_node);
size_t const end = ts_node_end_byte(test_node);

char const* const test_str = flamingo->src + start;
size_t const test_size = end - start;

if (!val->boolean.boolean) {
return error(flamingo, "assertion test '%.*s' failed", (int) test_size, test_str);
// If we have a message, evaluate it and include it in the error message.

if (has_msg) {
flamingo_val_t* msg_val = NULL;

if (parse_expr(flamingo, msg_node, &msg_val, NULL) < 0) {
val_decref(val);
return error(flamingo, "assertion test '%.*s' failed, and failed to parse message expression in doing so", (int) test_size, test_str);
}

char* msg_repr = NULL;

if (repr(flamingo, msg_val, &msg_repr) < 0) {
val_decref(val);
val_decref(msg_val);

return error(flamingo, "assertion test '%.*s' failed, and failed to represent message expression in doing so", (int) test_size, test_str);
}

val_decref(val);
val_decref(msg_val);

// Finally, actually error.

int const rv = error(flamingo, "assertion test '%.*s' failed: %s", (int) test_size, test_str, msg_repr);
free(msg_repr);

return rv;
}

val_decref(val);
return 0;
// Otherwise, just spit out something generic.

return error(flamingo, "assertion test '%.*s' failed", (int) test_size, test_str);
}

0 comments on commit f3b1510

Please sign in to comment.