aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.c2
-rw-r--r--src/ast.h3
-rw-r--r--src/compile.c30
-rw-r--r--src/parse.c14
-rw-r--r--src/stdlib/stdlib.c22
-rw-r--r--src/stdlib/stdlib.h7
-rw-r--r--src/types.c1
7 files changed, 29 insertions, 50 deletions
diff --git a/src/ast.c b/src/ast.c
index 982ef7dc..9f1bc42b 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -165,7 +165,7 @@ CORD ast_to_xml(ast_t *ast)
T(Optional, "<Optional>%r</Optional>", ast_to_xml(data.value))
T(NonOptional, "<NonOptional>%r</NonOptional>", ast_to_xml(data.value))
T(Moment, "<Moment/>")
- T(DocTest, "<DocTest>%r<output>%r</output></DocTest>", optional_tagged("expression", data.expr), xml_escape(data.output))
+ T(DocTest, "<DocTest>%r%r</DocTest>", optional_tagged("expression", data.expr), optional_tagged("expected", data.expected))
T(Use, "<Use>%r%r</Use>", optional_tagged("var", data.var), xml_escape(data.path))
T(InlineCCode, "<InlineCode>%r</InlineCode>", xml_escape(data.code))
T(Deserialize, "<Deserialize><type>%r</type>%r</Deserialize>", type_ast_to_xml(data.type), ast_to_xml(data.value))
diff --git a/src/ast.h b/src/ast.h
index c9db9061..c682726f 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -323,8 +323,7 @@ struct ast_s {
Moment_t moment;
} Moment;
struct {
- ast_t *expr;
- const char *output;
+ ast_t *expr, *expected;
bool skip_source:1;
} DocTest;
struct {
diff --git a/src/compile.c b/src/compile.c
index f4f1adeb..1ddc2c36 100644
--- a/src/compile.c
+++ b/src/compile.c
@@ -39,7 +39,7 @@ static CORD compile_string_literal(CORD literal);
CORD promote_to_optional(type_t *t, CORD code)
{
- if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t->tag == MomentType) {
+ if (t == THREAD_TYPE || t == PATH_TYPE || t == PATH_TYPE_TYPE || t == MATCH_TYPE || t->tag == MomentType) {
return code;
} else if (t->tag == IntType) {
switch (Match(t, IntType)->bits) {
@@ -878,24 +878,13 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
if (!expr_t)
code_err(test->expr, "I couldn't figure out the type of this expression");
- CORD output = CORD_EMPTY;
- if (test->output) {
- const uint8_t *raw = (const uint8_t*)CORD_to_const_char_star(test->output);
- uint8_t buf[128] = {0};
- size_t norm_len = sizeof(buf);
- uint8_t *norm = u8_normalize(UNINORM_NFC, (uint8_t*)raw, strlen((char*)raw)+1, buf, &norm_len);
- assert(norm[norm_len-1] == 0);
- output = CORD_from_char_star((char*)norm);
- if (norm && norm != buf) free(norm);
- }
-
CORD setup = CORD_EMPTY;
CORD test_code;
if (test->expr->tag == Declare) {
auto decl = Match(test->expr, Declare);
const char *varname = Match(decl->var, Var)->name;
if (streq(varname, "_"))
- return compile_statement(env, WrapAST(ast, DocTest, .expr=decl->value, .output=output, .skip_source=test->skip_source));
+ return compile_statement(env, WrapAST(ast, DocTest, .expr=decl->value, .expected=test->expected, .skip_source=test->skip_source));
CORD var = CORD_all("_$", Match(decl->var, Var)->name);
type_t *t = get_type(env, decl->value);
CORD val_code = compile_maybe_incref(env, decl->value, t);
@@ -922,7 +911,7 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
expr_t = lhs_t;
} else {
// Multi-assign or assignment to potentially non-idempotent targets
- if (output && assign->targets->next)
+ if (test->expected && assign->targets->next)
code_err(ast, "Sorry, but doctesting with '=' is not supported for multi-assignments");
test_code = "({ // Assignment\n";
@@ -969,12 +958,16 @@ static CORD _compile_statement(env_t *env, ast_t *ast)
} else {
test_code = compile(env, test->expr);
}
- if (test->output) {
+ if (test->expected) {
+ type_t *expected_type = get_type(env, test->expected);
+ if (!type_eq(expr_t, expected_type))
+ code_err(ast, "The type on the top of this test (%T) is different from the type on the bottom (%T)",
+ expr_t, expected_type);
return CORD_asprintf(
"%rtest(%r, %r, %r, %ld, %ld);",
setup, test_code,
+ compile(env, test->expected),
compile_type_info(expr_t),
- compile_string_literal(output),
(int64_t)(test->expr->start - test->expr->file->text),
(int64_t)(test->expr->end - test->expr->file->text));
} else {
@@ -1952,8 +1945,10 @@ CORD compile_int_to_type(env_t *env, ast_t *ast, type_t *target)
int64_t target_bits = (int64_t)Match(target, IntType)->bits;
switch (target_bits) {
case TYPE_IBITS64:
+ if (mpz_cmp_si(i, INT64_MIN) == 0)
+ return "I64(INT64_MIN)";
if (mpz_cmp_si(i, INT64_MAX) <= 0 && mpz_cmp_si(i, INT64_MIN) >= 0)
- return CORD_asprintf("I64(%s)", c_literal);
+ return CORD_asprintf("I64(%sL)", c_literal);
break;
case TYPE_IBITS32:
if (mpz_cmp_si(i, INT32_MAX) <= 0 && mpz_cmp_si(i, INT32_MIN) >= 0)
@@ -2204,6 +2199,7 @@ CORD compile_none(type_t *t)
if (t == THREAD_TYPE) return "NULL";
else if (t == PATH_TYPE) return "NONE_PATH";
else if (t == PATH_TYPE_TYPE) return "((OptionalPathType_t){})";
+ else if (t == MATCH_TYPE) return "NONE_MATCH";
switch (t->tag) {
case BigIntType: return "NONE_INT";
diff --git a/src/parse.c b/src/parse.c
index 9ad0db34..cc716578 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -2418,22 +2418,14 @@ PARSER(parse_doctest) {
spaces(&pos);
ast_t *expr = expect(ctx, start, &pos, parse_statement, "I couldn't parse the expression for this doctest");
whitespace(&pos);
- const char* output = NULL;
+ ast_t *expected = NULL;
if (match(&pos, "=")) {
spaces(&pos);
- const char *output_start = pos,
- *output_end = pos + strcspn(pos, "\r\n");
- if (output_end <= output_start)
- parser_err(ctx, output_start, output_end, "You're missing expected output here");
- int64_t trailing_spaces = 0;
- while (output_end - trailing_spaces - 1 > output_start && (output_end[-trailing_spaces-1] == ' ' || output_end[-trailing_spaces-1] == '\t'))
- ++trailing_spaces;
- output = GC_strndup(output_start, (size_t)((output_end - output_start) - trailing_spaces));
- pos = output_end;
+ expected = expect(ctx, start, &pos, parse_extended_expr, "I couldn't parse the expected expression here");
} else {
pos = expr->end;
}
- return NewAST(ctx->file, start, pos, DocTest, .expr=expr, .output=output);
+ return NewAST(ctx->file, start, pos, DocTest, .expr=expr, .expected=expected);
}
PARSER(parse_say) {
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c
index ae61bd0c..d2800dcd 100644
--- a/src/stdlib/stdlib.c
+++ b/src/stdlib/stdlib.c
@@ -602,29 +602,19 @@ public void end_inspect(const void *expr, const TypeInfo_t *type)
}
__attribute__((nonnull))
-public void test_value(const void *expr, const TypeInfo_t *type, const char *expected)
+public void test_value(const void *expr, const void *expected, const TypeInfo_t *type)
{
Text_t expr_text = generic_as_text(expr, USE_COLOR, type);
- Text_t type_name = generic_as_text(NULL, false, type);
-
- Text_t expected_text = Text$from_str(expected);
- Text_t expr_plain = USE_COLOR ? generic_as_text(expr, false, type) : expr_text;
- bool success = Text$equal_values(expr_plain, expected_text);
- if (!success) {
- OptionalMatch_t colon = Text$find(expected_text, Text(":"), I_small(1));
- if (colon.index.small) {
- Text_t with_type = Text$concat(expr_plain, Text(" : "), type_name);
- success = Text$equal_values(with_type, expected_text);
- }
- }
+ Text_t expected_text = generic_as_text(expected, USE_COLOR, type);
+ bool success = Text$equal_values(expr_text, expected_text);
if (!success) {
print_stack_trace(stderr, 2, 4);
fprintf(stderr,
USE_COLOR
- ? "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\nYou expected: \x1b[36;1m%s\x1b[0m\n\x1b[1m But I got:\x1b[m %k\n\n"
- : "\n==================== TEST FAILED ====================\n\nYou expected: %s\n But I got: %k\n\n",
- expected, &expr_text);
+ ? "\n\x1b[31;7m ==================== TEST FAILED ==================== \x1b[0;1m\n\nYou expected: \x1b[m%k\x1b[0m\n\x1b[1m But I got:\x1b[m %k\n\n"
+ : "\n==================== TEST FAILED ====================\n\nYou expected: %k\n But I got: %k\n\n",
+ &expected_text, &expr_text);
fflush(stderr);
raise(SIGABRT);
diff --git a/src/stdlib/stdlib.h b/src/stdlib/stdlib.h
index 1b633dff..49ec43fb 100644
--- a/src/stdlib/stdlib.h
+++ b/src/stdlib/stdlib.h
@@ -39,10 +39,11 @@ void end_inspect(const void *expr, const TypeInfo_t *type);
end_inspect(&_expr, typeinfo); \
}
__attribute__((nonnull))
-void test_value(const void *expr, const TypeInfo_t *type, const char *expected);
-#define test(expr, typeinfo, expected, start, end) {\
+void test_value(const void *expr, const void *expected, const TypeInfo_t *type);
+#define test(expr, expected, typeinfo, start, end) {\
auto _expr = expr; \
- test_value(&_expr, typeinfo, expected); \
+ auto _expected = expected; \
+ test_value(&_expr, &_expected, typeinfo); \
}
void say(Text_t text, bool newline);
diff --git a/src/types.c b/src/types.c
index 506850e8..7e5f262d 100644
--- a/src/types.c
+++ b/src/types.c
@@ -285,6 +285,7 @@ PUREFUNC bool has_heap_memory(type_t *t)
PUREFUNC bool has_stack_memory(type_t *t)
{
+ if (!t) return false;
switch (t->tag) {
case PointerType: return Match(t, PointerType)->is_stack;
case OptionalType: return has_stack_memory(Match(t, OptionalType)->type);