diff --git a/builtins/array.h b/builtins/array.h index 84edcb4..65b7028 100644 --- a/builtins/array.h +++ b/builtins/array.h @@ -8,11 +8,12 @@ #include "types.h" // Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1 -#define $Array_get(type, x, i) ({ const array_t *$arr = x; int64_t $index = (int64_t)(i); \ - int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \ - if (__builtin_expect($off < 0 || $off >= $arr->length, 0)) \ - fail("Invalid array index: %ld (array has length %ld)\n", $index, $arr->length); \ - *(type*)($arr->data + $arr->stride * $off);}) +#define $Array_get(type, x, i, filename, start, end) ({ \ + const array_t *$arr = x; int64_t $index = (int64_t)(i); \ + int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \ + if (__builtin_expect($off < 0 || $off >= $arr->length, 0)) \ + fail_source(filename, start, end, "Invalid array index: %r (array has length %ld)\n", Int64__as_str(&$index, USE_COLOR, NULL), $arr->length); \ + *(type*)($arr->data + $arr->stride * $off);}) #define $Array_get_unchecked(type, x, i) ({ const array_t *$arr = x; int64_t $index = (int64_t)(i); \ int64_t $off = $index + ($index < 0) * ($arr->length + 1) - 1; \ *(type*)($arr->data + $arr->stride * $off);}) diff --git a/builtins/functions.c b/builtins/functions.c index 4ca91d3..b7e816c 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -22,15 +22,32 @@ public const char *SSS_HASH_VECTOR = "sss hash vector -------------------------- public void fail(CORD fmt, ...) { - va_list args; - va_start(args, fmt); if (USE_COLOR) fputs("\x1b[31;7m FAIL: \x1b[m ", stderr); else fputs("FAIL: ", stderr); + va_list args; + va_start(args, fmt); CORD_vfprintf(stderr, fmt, args); va_end(args); raise(SIGABRT); } +public void fail_source(const char *filename, int64_t start, int64_t end, CORD fmt, ...) +{ + if (USE_COLOR) fputs("\n\x1b[31;7m FAIL: \x1b[m ", stderr); + else fputs("\nFAIL: ", stderr); + + va_list args; + va_start(args, fmt); + CORD_vfprintf(stderr, fmt, args); + va_end(args); + + file_t *file = filename ? load_file(filename) : NULL; + if (filename && file) + fprint_span(stderr, file, file->text+start, file->text+end, "\x1b[31;1m", 2, USE_COLOR); + + raise(SIGABRT); +} + public uint32_t generic_hash(const void *obj, const TypeInfo *type) { switch (type->tag) { @@ -123,7 +140,7 @@ static inline char *without_colors(const char *str) return buf; } -public void __doctest(void *expr, TypeInfo *type, CORD expected, const char *filename, int start, int end) +public void __doctest(void *expr, TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end) { static file_t *file = NULL; if (filename && (file == NULL || strcmp(file->filename, filename) != 0)) @@ -145,10 +162,10 @@ public void __doctest(void *expr, TypeInfo *type, CORD expected, const char *fil } if (!success) { - if (filename && file) - fprint_span(stderr, file, file->text+start, file->text+end, "\x1b[31;1m", 2, USE_COLOR); - fail(USE_COLOR ? "\x1b[31;1mDoctest failure:\nExpected: \x1b[32;7m%s\x1b[0m\n\x1b[31;1m But got: \x1b[31;7m%s\x1b[0m\n" : "Doctest failure:\nExpected: %s\n But got: %s\n", - expected, expr_str); + fail_source(filename, start, end, + USE_COLOR ? "\x1b[31;1mDoctest failure:\nExpected: \x1b[32;7m%s\x1b[0m\n\x1b[31;1m But got: \x1b[31;7m%s\x1b[0m\n" + : "Doctest failure:\nExpected: %s\n But got: %s\n", + expected, expr_str); } } } diff --git a/builtins/functions.h b/builtins/functions.h index bb8b563..6342c47 100644 --- a/builtins/functions.h +++ b/builtins/functions.h @@ -9,8 +9,9 @@ extern const char *SSS_HASH_VECTOR; void fail(CORD fmt, ...); +void fail_source(const char *filename, int64_t start, int64_t end, CORD fmt, ...); CORD builtin_last_err(); -void __doctest(void *expr, TypeInfo *type, CORD expected, const char *filename, int start, int end); +public void __doctest(void *expr, TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end); uint32_t generic_hash(const void *obj, const TypeInfo *type); int32_t generic_compare(const void *x, const void *y, const TypeInfo *type); diff --git a/builtins/table.h b/builtins/table.h index 69d0aad..d11a876 100644 --- a/builtins/table.h +++ b/builtins/table.h @@ -18,10 +18,11 @@ $table.fallback = fb; \ $table.default_value = def; \ $table; }) -#define $Table_get(table_expr, key_t, val_t, key_expr, info_expr) ({ \ +#define $Table_get(table_expr, key_t, val_t, key_expr, info_expr, filename, start, end) ({ \ const table_t *$t = table_expr; key_t $k = key_expr; const TypeInfo* $info = info_expr; \ const val_t *$v = Table_get($t, &$k, $info); \ - if (__builtin_expect($v == NULL, 0)) fail("The key %r is not in this table\n", generic_as_str(&$k, USE_COLOR, $info->TableInfo.key)); \ + if (__builtin_expect($v == NULL, 0)) \ + fail_source(filename, start, end, "The key %r is not in this table\n", generic_as_str(&$k, USE_COLOR, $info->TableInfo.key)); \ *$v; }) diff --git a/compile.c b/compile.c index 6b38a9b..a0e613a 100644 --- a/compile.c +++ b/compile.c @@ -771,8 +771,14 @@ CORD compile(env_t *env, ast_t *ast) type_t *item_type = Match(container_t, ArrayType)->item_type; CORD arr = compile_to_pointer_depth(env, indexing->indexed, 1); CORD index = compile(env, indexing->index); - return CORD_all(indexing->unchecked ? "$Array_get_unchecked" : "$Array_get(", - compile_type(item_type), ", ", arr, ", ", index, ")"); + file_t *f = indexing->index->file; + if (indexing->unchecked) + return CORD_all("$Array_get_unchecked", compile_type(item_type), ", ", arr, ", ", index, ")"); + else + return CORD_all("$Array_get(", compile_type(item_type), ", ", arr, ", ", index, ", ", + Str__quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ", + CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)), + ")"); } case TableType: { type_t *key_t = Match(container_t, TableType)->key_type; @@ -781,8 +787,12 @@ CORD compile(env_t *env, ast_t *ast) code_err(indexing->index, "This value has type %T, but this table can only be index with keys of type %T", index_t, key_t); CORD table = compile_to_pointer_depth(env, indexing->indexed, 1); CORD key = compile(env, indexing->index); + file_t *f = indexing->index->file; return CORD_all("$Table_get(", table, ", ", compile_type(key_t), ", ", compile_type(value_t), ", ", - key, ", ", compile_type_info(env, container_t), ")"); + key, ", ", compile_type_info(env, container_t), ", ", + Str__quoted(f->filename, false), ", ", CORD_asprintf("%ld", (int64_t)(indexing->index->start - f->text)), ", ", + CORD_asprintf("%ld", (int64_t)(indexing->index->end - f->text)), + ")"); } default: code_err(ast, "Indexing is not supported for type: %T", container_t); }