diff options
| -rw-r--r-- | builtins/functions.c | 74 | ||||
| -rw-r--r-- | builtins/functions.h | 6 | ||||
| -rw-r--r-- | compile.c | 35 |
3 files changed, 64 insertions, 51 deletions
diff --git a/builtins/functions.c b/builtins/functions.c index 2b4d45d4..f668b253 100644 --- a/builtins/functions.c +++ b/builtins/functions.c @@ -151,44 +151,54 @@ public CORD builtin_last_err() return CORD_from_char_star(strerror(errno)); } -public void test(void *expr, const TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end) +static int TEST_DEPTH = 0; +static file_t *file = NULL; + +public void start_test(const char *filename, int64_t start, int64_t end) { - static file_t *file = NULL; if (filename && (file == NULL || strcmp(file->filename, filename) != 0)) file = load_file(filename); - if (filename && file) + if (filename && file) { + for (int i = 0; i < 3*TEST_DEPTH; i++) fputc(' ', stderr); CORD_fprintf(stderr, USE_COLOR ? "\x1b[33;1m>> \x1b[0m%.*s\x1b[m\n" : ">> %.*s\n", (end - start), file->text + start); + } + ++TEST_DEPTH; +} + +public void end_test(void *expr, const TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end) +{ + --TEST_DEPTH; + if (!expr) return; + + CORD expr_cord = generic_as_text(expr, USE_COLOR, type); + CORD type_name = generic_as_text(NULL, false, type); + + uint8_t buf[512] = {0}; + size_t buf_len = sizeof(buf)-1; + const char *expr_str = CORD_to_const_char_star(expr_cord); + uint8_t *normalized_str = u8_normalize(UNINORM_NFD, (uint8_t*)expr_str, strlen(expr_str), buf, &buf_len); + normalized_str[buf_len] = 0; + if (!normalized_str) errx(1, "Couldn't normalize unicode string!"); + CORD expr_normalized = CORD_from_char_star((char*)normalized_str); + if (normalized_str != buf) + free(normalized_str); + + for (int i = 0; i < 3*TEST_DEPTH; i++) fputc(' ', stderr); + CORD_fprintf(stderr, USE_COLOR ? "\x1b[2m=\x1b[0m %r \x1b[2m: %r\x1b[m\n" : "= %r : %r\n", expr_normalized, type_name); + if (expected) { + CORD expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_normalized; + bool success = Text$equal(&expr_plain, &expected); + if (!success && CORD_chr(expected, 0, ':')) { + CORD with_type = CORD_catn(3, expr_plain, " : ", type_name); + success = Text$equal(&with_type, &expected); + } - if (expr) { - CORD expr_cord = generic_as_text(expr, USE_COLOR, type); - CORD type_name = generic_as_text(NULL, false, type); - - uint8_t buf[512] = {0}; - size_t buf_len = sizeof(buf)-1; - const char *expr_str = CORD_to_const_char_star(expr_cord); - uint8_t *normalized_str = u8_normalize(UNINORM_NFD, (uint8_t*)expr_str, strlen(expr_str), buf, &buf_len); - normalized_str[buf_len] = 0; - if (!normalized_str) errx(1, "Couldn't normalize unicode string!"); - CORD expr_normalized = CORD_from_char_star((char*)normalized_str); - if (normalized_str != buf) - free(normalized_str); - - CORD_fprintf(stderr, USE_COLOR ? "\x1b[2m=\x1b[0m %r \x1b[2m: %r\x1b[m\n" : "= %r : %r\n", expr_normalized, type_name); - if (expected) { - CORD expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_normalized; - bool success = Text$equal(&expr_plain, &expected); - if (!success && CORD_chr(expected, 0, ':')) { - CORD with_type = CORD_catn(3, expr_plain, " : ", type_name); - success = Text$equal(&with_type, &expected); - } - - if (!success) { - fail_source(filename, start, end, - USE_COLOR ? "\x1b[31;1mDoctest failure:\nExpected: \x1b[32;1m%s\x1b[0m\n\x1b[31;1m But got:\x1b[m %s\n" - : "Doctest failure:\nExpected: %s\n But got: %s\n", - CORD_to_const_char_star(expected), CORD_to_const_char_star(expr_normalized)); - } + if (!success) { + fail_source(filename, start, end, + USE_COLOR ? "\x1b[31;1mDoctest failure:\nExpected: \x1b[32;1m%s\x1b[0m\n\x1b[31;1m But got:\x1b[m %s\n" + : "Doctest failure:\nExpected: %s\n But got: %s\n", + CORD_to_const_char_star(expected), CORD_to_const_char_star(expr_normalized)); } } } diff --git a/builtins/functions.h b/builtins/functions.h index ed63ec36..f1a2867e 100644 --- a/builtins/functions.h +++ b/builtins/functions.h @@ -13,7 +13,11 @@ extern const char *TOMO_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 test(void *expr, const TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end); +void start_test(const char *filename, int64_t start, int64_t end); +void end_test(void *expr, const TypeInfo *type, CORD expected, const char *filename, int64_t start, int64_t end); +#define test(expr, type, expected, filename, start, end) {\ + start_test(filename, start, end); \ + end_test(expr, type, expected, filename, start, end); } void say(CORD text); uint32_t generic_hash(const void *obj, const TypeInfo *type); @@ -247,11 +247,14 @@ CORD compile_statement(env_t *env, ast_t *ast) (int64_t)(test->expr->start - test->expr->file->text), (int64_t)(test->expr->end - test->expr->file->text)); } else { + CORD var = CORD_all("$", Match(decl->var, Var)->name); return CORD_asprintf( - "%r\n" - "test(&%r, %r, %r, %r, %ld, %ld);", - compile_statement(env, test->expr), - compile(env, decl->var), + "%r;\n" + "test(({ %s = %r; &%r;}), %r, %r, %r, %ld, %ld);\n", + compile_declaration(env, get_type(env, decl->value), var), + var, + compile(env, decl->value), + var, compile_type_info(env, get_type(env, decl->value)), compile(env, WrapAST(test->expr, TextLiteral, .cord=output)), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->expr->file->filename)), @@ -262,21 +265,21 @@ CORD compile_statement(env_t *env, ast_t *ast) auto assign = Match(test->expr, Assign); if (!assign->targets->next && assign->targets->ast->tag == Var) { // Common case: assigning to one variable: - CORD var = compile(env, assign->targets->ast); - CORD code = compile_assignment(env, assign->targets->ast, compile(env, assign->values->ast)); - CORD_appendf(&code, "test(&%r, %r, %r, %r, %ld, %ld);", - var, compile_type_info(env, get_type(env, assign->targets->ast)), + return CORD_asprintf( + "test(({ %r; &%r; }), %r, %r, %r, %ld, %ld);", + compile_assignment(env, assign->targets->ast, compile(env, assign->values->ast)), + compile(env, assign->targets->ast), + compile_type_info(env, get_type(env, assign->targets->ast)), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->output)), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->expr->file->filename)), (int64_t)(test->expr->start - test->expr->file->text), (int64_t)(test->expr->end - test->expr->file->text)); - return code; } else { // Multi-assign or assignment to potentially non-idempotent targets if (test->output && assign->targets->next) code_err(ast, "Sorry, but doctesting with '=' is not supported for multi-assignments"); - CORD code = "{ // Assignment\n"; + CORD code = "test(({ // Assignment\n"; int64_t i = 1; for (ast_list_t *target = assign->targets, *value = assign->values; target && value; target = target->next, value = value->next) { type_t *target_type = get_type(env, target->ast); @@ -290,28 +293,24 @@ CORD compile_statement(env_t *env, ast_t *ast) for (ast_list_t *target = assign->targets; target; target = target->next) code = CORD_all(code, compile_assignment(env, target->ast, CORD_asprintf("$%ld", i++))); - CORD_appendf(&code, "test(&$1, %r, %r, %r, %ld, %ld);", + CORD_appendf(&code, "&$1; }), %r, %r, %r, %ld, %ld);", compile_type_info(env, get_type(env, assign->targets->ast)), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->output)), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->expr->file->filename)), (int64_t)(test->expr->start - test->expr->file->text), (int64_t)(test->expr->end - test->expr->file->text)); - return CORD_cat(code, "\n}"); + return code; } } else if (expr_t->tag == VoidType || expr_t->tag == AbortType) { return CORD_asprintf( - "%r\n" - "test(NULL, NULL, NULL, %r, %ld, %ld);", + "test(({ %r; NULL; }), NULL, NULL, %r, %ld, %ld);", compile_statement(env, test->expr), compile(env, WrapAST(test->expr, TextLiteral, .cord=test->expr->file->filename)), (int64_t)(test->expr->start - test->expr->file->text), (int64_t)(test->expr->end - test->expr->file->text)); } else { return CORD_asprintf( - "{ // Test:\n" - "%r = %r;\n" - "test(&expr, %r, %r, %r, %ld, %ld);\n" - "}", + "test(({ %r = %r; &expr; }), %r, %r, %r, %ld, %ld);", compile_declaration(env, expr_t, "expr"), compile(env, test->expr), compile_type_info(env, expr_t), |
