From 334ed804f2ead7f8f99ad87a9abe113c4f2c2706 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sun, 3 Dec 2023 18:36:13 +0200 Subject: [PATCH 1/2] add tests for stdlib/ascii.jou (#407) --- self_hosted/runs_wrong.txt | 1 + src/print.c | 2 +- stdlib/ascii.jou | 8 ++----- tests/should_succeed/ascii_test.jou | 35 +++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 tests/should_succeed/ascii_test.jou diff --git a/self_hosted/runs_wrong.txt b/self_hosted/runs_wrong.txt index b44b692f..e64ada59 100644 --- a/self_hosted/runs_wrong.txt +++ b/self_hosted/runs_wrong.txt @@ -43,3 +43,4 @@ tests/wrong_type/assert.jou tests/wrong_type/cannot_be_indexed.jou tests/wrong_type/index.jou stdlib/ascii.jou +tests/should_succeed/ascii_test.jou diff --git a/src/print.c b/src/print.c index fab4d3a5..60f495ec 100644 --- a/src/print.c +++ b/src/print.c @@ -19,7 +19,7 @@ static void print_string(const char *s, int len) else if (s[i] == '\n') printf("\\n"); else - printf("\\x%02x", s[i]); // TODO: \x is not yet recognized by the tokenizer + printf("\\x%02x", (unsigned char)s[i]); // TODO: \x is not yet recognized by the tokenizer } putchar('"'); } diff --git a/stdlib/ascii.jou b/stdlib/ascii.jou index 5dedfca1..07b44493 100644 --- a/stdlib/ascii.jou +++ b/stdlib/ascii.jou @@ -2,7 +2,6 @@ import "stdlib/str.jou" import "stdlib/mem.jou" # Test if a string is ASCII only. -# TODO: test def is_ascii(s: byte*) -> bool: for p = s; *p != '\0'; p++: if *p >= 128: @@ -10,19 +9,16 @@ def is_ascii(s: byte*) -> bool: return True # Check for '0', '1', ..., '9'. -# TODO: test def is_ascii_digit(b: byte) -> bool: return '0' <= b and b <= '9' # Checks if the given byte is an ASCII punctuation character, such as '*' or '_' or '"'. -# TODO: test def is_ascii_punctuation(b: byte) -> bool: - return strchr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", b) != NULL + return b != '\0' and strchr("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", b) != NULL # Checks if the given byte is an ASCII whitespace character, such as ' ' or '\n'. -# TODO: test def is_ascii_whitespace(b: byte) -> bool: - return strchr("\t\n\x0b\x0c\r\x1c\x1d\x1e\x1f ", b) != NULL + return b != '\0' and strchr("\t\n\x0b\x0c\r\x1c\x1d\x1e\x1f ", b) != NULL # Removes ASCII whitespace from both ends of a string in-place. # Similar to .strip() in Python or .trim() in JavaScript. diff --git a/tests/should_succeed/ascii_test.jou b/tests/should_succeed/ascii_test.jou new file mode 100644 index 00000000..a6c4f84c --- /dev/null +++ b/tests/should_succeed/ascii_test.jou @@ -0,0 +1,35 @@ +import "stdlib/ascii.jou" +import "stdlib/str.jou" + +def main() -> int: + assert is_ascii("hello") + assert is_ascii("hello world test!!! @$!") + assert is_ascii("") + assert not is_ascii("örkkimörkki") + + assert is_ascii_digit('0') + assert is_ascii_digit('7') + assert is_ascii_digit('9') + assert not is_ascii_digit('x') + assert not is_ascii_digit('\0') + + assert is_ascii_punctuation('!') + assert is_ascii_punctuation('_') + assert not is_ascii_punctuation('a') + assert not is_ascii_punctuation('2') + assert not is_ascii_punctuation('\0') + + assert is_ascii_whitespace(' ') + assert is_ascii_whitespace('\t') + assert is_ascii_whitespace('\r') + assert is_ascii_whitespace('\n') + assert not is_ascii_whitespace('a') + assert not is_ascii_whitespace('.') + assert not is_ascii_whitespace('\0') + + s: byte[100] + strcpy(s, " hello world \r\n \t ") + trim_ascii_whitespace(s) + assert strcmp(s, "hello world") == 0 + + return 0 From 2c7f2f82dfbb319410071680f689a181e84b4794 Mon Sep 17 00:00:00 2001 From: Akuli Date: Sun, 3 Dec 2023 18:38:42 +0200 Subject: [PATCH 2/2] Add error message for foo().bar() (#402) --- self_hosted/typecheck.jou | 6 ++++++ src/typecheck.c | 8 ++++++++ tests/other_errors/func_then_method.jou | 11 +++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/other_errors/func_then_method.jou diff --git a/self_hosted/typecheck.jou b/self_hosted/typecheck.jou index 546b6e1a..ac27970f 100644 --- a/self_hosted/typecheck.jou +++ b/self_hosted/typecheck.jou @@ -833,6 +833,12 @@ class Stage3TypeChecker: ) fail(call->location, message) + if call->method_call_self != NULL and not call->uses_arrow_operator: + snprintf( + message, sizeof message, + "cannot take address of %%s, needed for calling the %s() method", call->name) + ensure_can_take_address(call->method_call_self, message) + signature_string = signature->to_string(False, False) expected = signature->nargs diff --git a/src/typecheck.c b/src/typecheck.c index 2d326972..684317b9 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -1028,6 +1028,14 @@ static ExpressionTypes *typecheck_expression(FileTypes *ft, const AstExpression case AST_EXPR_CALL_METHOD: temptype = typecheck_expression_not_void(ft, expr->data.methodcall.obj)->type; result = typecheck_function_or_method_call(ft, &expr->data.methodcall.call, temptype, expr->location); + + char tmp[500]; + snprintf( + tmp, sizeof tmp, + "cannot take address of %%s, needed for calling the %s() method", + expr->data.methodcall.call.calledname); + ensure_can_take_address(expr->data.methodcall.obj, tmp); + if (!result) return NULL; break; diff --git a/tests/other_errors/func_then_method.jou b/tests/other_errors/func_then_method.jou new file mode 100644 index 00000000..6e8ba735 --- /dev/null +++ b/tests/other_errors/func_then_method.jou @@ -0,0 +1,11 @@ +import "stdlib/io.jou" + +class Foo: + def do_stuff(self) -> void: + printf("Doing stuff!\n") + +def make_foo() -> Foo: + return Foo{} + +def bar() -> void: + make_foo().do_stuff() # Error: cannot take address of a function call, needed for calling the do_stuff() method