From e8de27022c24d28a3912808483e0c04ed63802be Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:15:38 +0200 Subject: [PATCH 01/13] Implement it --- src/parse.c | 31 +++++++++++++++++++++++++++++++ tests/should_succeed/sscanf.jou | 3 +-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/parse.c b/src/parse.c index a821f33a..7f237081 100644 --- a/src/parse.c +++ b/src/parse.c @@ -957,6 +957,34 @@ static AstEnumDef parse_enumdef(ParserState *ps) return result; } +// Parses the "x: int" part of "x, y, z: int", leaving "y, z: int" to be parsed later. +static AstNameTypeValue parse_first_of_multiple_local_var_declares(ParserState *ps) +{ + assert(ps->tokens->type == TOKEN_NAME); + assert(is_operator(&ps->tokens[1], ",")); + + char firstname[100]; + safe_strcpy(firstname, ps->tokens->data.name); + + ps->tokens += 2; + + // Skip to last variable declaration (e.g. "z: int") and parse it to get the type + ParserState savestate = *ps; + while (ps->tokens->type == TOKEN_NAME && is_operator(&ps->tokens[1], ",")) + ps->tokens += 2; + // TODO: test how error message works + AstNameTypeValue ntv = parse_name_type_value(ps, "another variable name after ',' (example: \"foo, bar: int\")"); + *ps = savestate; + + // This syntax is only for declaring variables, not assigning + // TODO: test this + if (ntv.value) + fail_with_parse_error(ps->tokens, "only one variable can be assigned at a time"); + + safe_strcpy(ntv.name, firstname); + return ntv; +} + static AstStatement parse_statement(ParserState *ps) { AstStatement result = { .location = ps->tokens->location }; @@ -1031,6 +1059,9 @@ static AstStatement parse_statement(ParserState *ps) ps->tokens++; *result.data.forloop.incr = parse_oneline_statement(ps); result.data.forloop.body = parse_body(ps); + } else if (ps->tokens->type == TOKEN_NAME && is_operator(&ps->tokens[1], ",")) { + result.kind = AST_STMT_DECLARE_LOCAL_VAR; + result.data.vardecl = parse_first_of_multiple_local_var_declares(ps); } else { result = parse_oneline_statement(ps); eat_newline(ps); diff --git a/tests/should_succeed/sscanf.jou b/tests/should_succeed/sscanf.jou index ab8f4dc4..1bdb91c5 100644 --- a/tests/should_succeed/sscanf.jou +++ b/tests/should_succeed/sscanf.jou @@ -2,8 +2,7 @@ import "stdlib/io.jou" import "stdlib/str.jou" def calculate_sum(string: byte*) -> int: - x: int - y: int + x, y: int sscanf(string, "%d + %d", &x, &y) return x + y From fa889b1a036744bfafdca5667783e873ec227950 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:24:30 +0200 Subject: [PATCH 02/13] tests --- src/parse.c | 2 +- tests/syntax_error/double_assignment_comma_typed.jou | 2 ++ tests/syntax_error/double_assignment_comma_untyped.jou | 4 ++++ tests/syntax_error/local_var_comma.jou | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/syntax_error/double_assignment_comma_typed.jou create mode 100644 tests/syntax_error/double_assignment_comma_untyped.jou create mode 100644 tests/syntax_error/local_var_comma.jou diff --git a/src/parse.c b/src/parse.c index 7f237081..5e980ad9 100644 --- a/src/parse.c +++ b/src/parse.c @@ -979,7 +979,7 @@ static AstNameTypeValue parse_first_of_multiple_local_var_declares(ParserState * // This syntax is only for declaring variables, not assigning // TODO: test this if (ntv.value) - fail_with_parse_error(ps->tokens, "only one variable can be assigned at a time"); + fail(ps->tokens->location, "only one variable can be assigned at a time"); safe_strcpy(ntv.name, firstname); return ntv; diff --git a/tests/syntax_error/double_assignment_comma_typed.jou b/tests/syntax_error/double_assignment_comma_typed.jou new file mode 100644 index 00000000..58d7c017 --- /dev/null +++ b/tests/syntax_error/double_assignment_comma_typed.jou @@ -0,0 +1,2 @@ +def foo() -> None: + x, y: int = 7 # Error: only one variable can be assigned at a time diff --git a/tests/syntax_error/double_assignment_comma_untyped.jou b/tests/syntax_error/double_assignment_comma_untyped.jou new file mode 100644 index 00000000..eddb11cb --- /dev/null +++ b/tests/syntax_error/double_assignment_comma_untyped.jou @@ -0,0 +1,4 @@ +def foo() -> None: + # Python's unpack syntax is not supported in Jou. + # If you think it should be supported, note that it conflicts with "x, y: int" syntax (see #536). + x, y = 0 # Error: only one variable can be assigned at a time diff --git a/tests/syntax_error/local_var_comma.jou b/tests/syntax_error/local_var_comma.jou new file mode 100644 index 00000000..f91c8d68 --- /dev/null +++ b/tests/syntax_error/local_var_comma.jou @@ -0,0 +1,2 @@ +def main() -> int: + x, = 0 # Error: expected another variable name after ',' (example: "foo, bar: int"), got ':' From db956b907d56d4f7dd20f13afdb2a9ef30d4cf63 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:25:43 +0200 Subject: [PATCH 03/13] fix test --- tests/syntax_error/local_var_comma.jou | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/syntax_error/local_var_comma.jou b/tests/syntax_error/local_var_comma.jou index f91c8d68..8031af2e 100644 --- a/tests/syntax_error/local_var_comma.jou +++ b/tests/syntax_error/local_var_comma.jou @@ -1,2 +1,2 @@ def main() -> int: - x, = 0 # Error: expected another variable name after ',' (example: "foo, bar: int"), got ':' + x, = 0 # Error: expected another variable name after ',' (example: "foo, bar: int"), got '=' From 4258a198314f6622dc3105a0f526ce1fe42ea06c Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:39:30 +0200 Subject: [PATCH 04/13] finally tests pass --- src/parse.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/parse.c b/src/parse.c index 5e980ad9..642d6351 100644 --- a/src/parse.c +++ b/src/parse.c @@ -960,28 +960,36 @@ static AstEnumDef parse_enumdef(ParserState *ps) // Parses the "x: int" part of "x, y, z: int", leaving "y, z: int" to be parsed later. static AstNameTypeValue parse_first_of_multiple_local_var_declares(ParserState *ps) { + assert(ps->tokens->type == TOKEN_NAME); assert(is_operator(&ps->tokens[1], ",")); - char firstname[100]; - safe_strcpy(firstname, ps->tokens->data.name); + AstNameTypeValue ntv = { .name_location = ps->tokens->location, .value = NULL }; + safe_strcpy(ntv.name, ps->tokens->data.name); + // Take a backup of the parser where first variable name and its comma are consumed. ps->tokens += 2; - - // Skip to last variable declaration (e.g. "z: int") and parse it to get the type ParserState savestate = *ps; - while (ps->tokens->type == TOKEN_NAME && is_operator(&ps->tokens[1], ",")) - ps->tokens += 2; - // TODO: test how error message works - AstNameTypeValue ntv = parse_name_type_value(ps, "another variable name after ',' (example: \"foo, bar: int\")"); - *ps = savestate; - // This syntax is only for declaring variables, not assigning - // TODO: test this - if (ntv.value) + // Find ":" so we can parse the type that comes after it + while (ps->tokens->type == TOKEN_NAME || is_operator(&ps->tokens[1], ",")) + ps->tokens++; + + // Error for "x, y = 0" + if (is_operator(ps->tokens, "=")) + fail(ps->tokens->location, "only one variable can be assigned at a time"); + + if (!is_operator(ps->tokens, ":")) + fail_with_parse_error(ps->tokens, "':' and a type after it (example: \"foo, bar: int\")"); + ps->tokens++; + + ntv.type = parse_type(ps); + + // Error for "x, y: int = 0" + if (is_operator(ps->tokens, "=")) fail(ps->tokens->location, "only one variable can be assigned at a time"); - safe_strcpy(ntv.name, firstname); + *ps = savestate; return ntv; } From 3fe1cf17a1509f4b0ab7e92a795972449a5995a8 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:43:38 +0200 Subject: [PATCH 05/13] ok maybe it works now --- src/parse.c | 2 +- tests/syntax_error/local_var_comma.jou | 2 +- tests/syntax_error/local_vars_comma.jou | 2 ++ tests/syntax_error/local_vars_comma_assign.jou | 2 ++ tests/syntax_error/python_style_unpack.jou | 2 ++ 5 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/syntax_error/local_vars_comma.jou create mode 100644 tests/syntax_error/local_vars_comma_assign.jou create mode 100644 tests/syntax_error/python_style_unpack.jou diff --git a/src/parse.c b/src/parse.c index 642d6351..71441995 100644 --- a/src/parse.c +++ b/src/parse.c @@ -1067,7 +1067,7 @@ static AstStatement parse_statement(ParserState *ps) ps->tokens++; *result.data.forloop.incr = parse_oneline_statement(ps); result.data.forloop.body = parse_body(ps); - } else if (ps->tokens->type == TOKEN_NAME && is_operator(&ps->tokens[1], ",")) { + } else if (ps->tokens->type == TOKEN_NAME && is_operator(&ps->tokens[1], ",") && ps->tokens[2].type == TOKEN_NAME) { result.kind = AST_STMT_DECLARE_LOCAL_VAR; result.data.vardecl = parse_first_of_multiple_local_var_declares(ps); } else { diff --git a/tests/syntax_error/local_var_comma.jou b/tests/syntax_error/local_var_comma.jou index 8031af2e..f0ca76a4 100644 --- a/tests/syntax_error/local_var_comma.jou +++ b/tests/syntax_error/local_var_comma.jou @@ -1,2 +1,2 @@ def main() -> int: - x, = 0 # Error: expected another variable name after ',' (example: "foo, bar: int"), got '=' + x, = 0 # Error: not a valid statement diff --git a/tests/syntax_error/local_vars_comma.jou b/tests/syntax_error/local_vars_comma.jou new file mode 100644 index 00000000..977bad45 --- /dev/null +++ b/tests/syntax_error/local_vars_comma.jou @@ -0,0 +1,2 @@ +def main() -> int: + x, y, = 0 # Error: expected ':' and a type after it (example: "foo, bar = int"), got ',' diff --git a/tests/syntax_error/local_vars_comma_assign.jou b/tests/syntax_error/local_vars_comma_assign.jou new file mode 100644 index 00000000..6bc709fd --- /dev/null +++ b/tests/syntax_error/local_vars_comma_assign.jou @@ -0,0 +1,2 @@ +def main() -> int: + x, y, # Error: expected ':' and a type after it (example: "foo, bar = int"), got ',' diff --git a/tests/syntax_error/python_style_unpack.jou b/tests/syntax_error/python_style_unpack.jou new file mode 100644 index 00000000..f92b77d8 --- /dev/null +++ b/tests/syntax_error/python_style_unpack.jou @@ -0,0 +1,2 @@ +def main() -> int: + x, y = "hi" # Error: only one variable can be assigned at a time From d6ae6ba217a5bf4f9ceb4f1b1d2525c9814b802b Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:49:34 +0200 Subject: [PATCH 06/13] ok maybe this work --- src/parse.c | 9 +++++---- tests/syntax_error/local_vars_comma.jou | 2 +- tests/syntax_error/local_vars_comma_assign.jou | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/parse.c b/src/parse.c index 71441995..547d360d 100644 --- a/src/parse.c +++ b/src/parse.c @@ -968,12 +968,13 @@ static AstNameTypeValue parse_first_of_multiple_local_var_declares(ParserState * safe_strcpy(ntv.name, ps->tokens->data.name); // Take a backup of the parser where first variable name and its comma are consumed. - ps->tokens += 2; ParserState savestate = *ps; + savestate.tokens += 2; - // Find ":" so we can parse the type that comes after it - while (ps->tokens->type == TOKEN_NAME || is_operator(&ps->tokens[1], ",")) - ps->tokens++; + // Skip variables and commas so we can parse the type that comes after it + ps->tokens++; + while (is_operator(ps->tokens, ",") && ps->tokens[1].type == TOKEN_NAME) + ps->tokens += 2; // Error for "x, y = 0" if (is_operator(ps->tokens, "=")) diff --git a/tests/syntax_error/local_vars_comma.jou b/tests/syntax_error/local_vars_comma.jou index 977bad45..54bbf485 100644 --- a/tests/syntax_error/local_vars_comma.jou +++ b/tests/syntax_error/local_vars_comma.jou @@ -1,2 +1,2 @@ def main() -> int: - x, y, = 0 # Error: expected ':' and a type after it (example: "foo, bar = int"), got ',' + x, y, = 0 # Error: expected ':' and a type after it (example: "foo, bar: int"), got ',' diff --git a/tests/syntax_error/local_vars_comma_assign.jou b/tests/syntax_error/local_vars_comma_assign.jou index 6bc709fd..77d976de 100644 --- a/tests/syntax_error/local_vars_comma_assign.jou +++ b/tests/syntax_error/local_vars_comma_assign.jou @@ -1,2 +1,2 @@ def main() -> int: - x, y, # Error: expected ':' and a type after it (example: "foo, bar = int"), got ',' + x, y, # Error: expected ':' and a type after it (example: "foo, bar: int"), got ',' From b61b334e19169bc506529f0a40c34d05118bcff0 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 00:56:09 +0200 Subject: [PATCH 07/13] tiny tidy --- src/parse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/parse.c b/src/parse.c index 547d360d..08e15a6c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -960,7 +960,6 @@ static AstEnumDef parse_enumdef(ParserState *ps) // Parses the "x: int" part of "x, y, z: int", leaving "y, z: int" to be parsed later. static AstNameTypeValue parse_first_of_multiple_local_var_declares(ParserState *ps) { - assert(ps->tokens->type == TOKEN_NAME); assert(is_operator(&ps->tokens[1], ",")); From 349a1ecc9e833690a8033b30b364a9d35051b357 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 01:08:45 +0200 Subject: [PATCH 08/13] compare_compilers.sh --fix --- self_hosted/parses_wrong.txt | 6 ++++++ self_hosted/runs_wrong.txt | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/self_hosted/parses_wrong.txt b/self_hosted/parses_wrong.txt index f3dcefd8..61600e5c 100644 --- a/self_hosted/parses_wrong.txt +++ b/self_hosted/parses_wrong.txt @@ -2,3 +2,9 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou +tests/should_succeed/sscanf.jou +tests/syntax_error/double_assignment_comma_typed.jou +tests/syntax_error/double_assignment_comma_untyped.jou +tests/syntax_error/local_vars_comma_assign.jou +tests/syntax_error/local_vars_comma.jou +tests/syntax_error/python_style_unpack.jou diff --git a/self_hosted/runs_wrong.txt b/self_hosted/runs_wrong.txt index 429a878e..f211f104 100644 --- a/self_hosted/runs_wrong.txt +++ b/self_hosted/runs_wrong.txt @@ -16,3 +16,9 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou +tests/should_succeed/sscanf.jou +tests/syntax_error/double_assignment_comma_typed.jou +tests/syntax_error/double_assignment_comma_untyped.jou +tests/syntax_error/local_vars_comma_assign.jou +tests/syntax_error/local_vars_comma.jou +tests/syntax_error/python_style_unpack.jou From a4a2889c3f436da052a08ccf2696bb8f417af35c Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 01:22:16 +0200 Subject: [PATCH 09/13] mostly port to self-hosted --- self_hosted/parser.jou | 40 ++++++++++++++++++++++++++++++++++++ self_hosted/parses_wrong.txt | 3 --- self_hosted/runs_wrong.txt | 3 --- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/self_hosted/parser.jou b/self_hosted/parser.jou index f9eadf5c..f736bb03 100644 --- a/self_hosted/parser.jou +++ b/self_hosted/parser.jou @@ -842,6 +842,35 @@ class Parser: body = self->parse_body(), } + # Parses the "x: int" part of "x, y, z: int", leaving "y, z: int" to be parsed later. + def parse_first_of_multiple_local_var_declares(self) -> AstNameTypeValue: + assert self->tokens->kind == TokenKind::Name + + ntv = AstNameTypeValue{ + name = self->tokens->short_string, + name_location = self->tokens->location, + } + + # Take a backup of the parser where first variable name and its comma are consumed. + save_state = *self + save_state.tokens = &save_state.tokens[2] + + # Skip variables and commas so we can parse the type that comes after it + self->tokens++ + while self->tokens->is_operator(",") and self->tokens[1].kind == TokenKind::Name: + self->tokens = &self->tokens[2] + + # TODO: more error handling + + if not self->tokens->is_operator(":"): + self->tokens->fail_expected_got("':' and a type after it (example: \"foo, bar: int\")") + self->tokens++ + + ntv.type = self->parse_type() + + *self = save_state + return ntv + def parse_statement(self) -> AstStatement: if self->tokens->is_keyword("import"): fail(self->tokens->location, "imports must be in the beginning of the file") @@ -924,6 +953,17 @@ class Parser: while_loop = self->parse_while_loop(), } + if ( + self->tokens[0].kind == TokenKind::Name + and self->tokens[1].is_operator(",") + and self->tokens[2].kind == TokenKind::Name + ): + return AstStatement{ + location = self->tokens->location, + kind = AstStatementKind::DeclareLocalVar, + var_declaration = self->parse_first_of_multiple_local_var_declares(), + } + result = self->parse_oneline_statement() self->eat_newline() return result diff --git a/self_hosted/parses_wrong.txt b/self_hosted/parses_wrong.txt index 61600e5c..05762ff6 100644 --- a/self_hosted/parses_wrong.txt +++ b/self_hosted/parses_wrong.txt @@ -2,9 +2,6 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou -tests/should_succeed/sscanf.jou tests/syntax_error/double_assignment_comma_typed.jou tests/syntax_error/double_assignment_comma_untyped.jou -tests/syntax_error/local_vars_comma_assign.jou -tests/syntax_error/local_vars_comma.jou tests/syntax_error/python_style_unpack.jou diff --git a/self_hosted/runs_wrong.txt b/self_hosted/runs_wrong.txt index f211f104..4e80e4f7 100644 --- a/self_hosted/runs_wrong.txt +++ b/self_hosted/runs_wrong.txt @@ -16,9 +16,6 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou -tests/should_succeed/sscanf.jou tests/syntax_error/double_assignment_comma_typed.jou tests/syntax_error/double_assignment_comma_untyped.jou -tests/syntax_error/local_vars_comma_assign.jou -tests/syntax_error/local_vars_comma.jou tests/syntax_error/python_style_unpack.jou From 78742f46d79f3a845bd944b8a54602e7c3793f95 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 01:24:51 +0200 Subject: [PATCH 10/13] moar fix --- self_hosted/parser.jou | 11 ++++++++++- self_hosted/parses_wrong.txt | 3 --- self_hosted/runs_wrong.txt | 3 --- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/self_hosted/parser.jou b/self_hosted/parser.jou index f736bb03..e164cf79 100644 --- a/self_hosted/parser.jou +++ b/self_hosted/parser.jou @@ -860,7 +860,12 @@ class Parser: while self->tokens->is_operator(",") and self->tokens[1].kind == TokenKind::Name: self->tokens = &self->tokens[2] - # TODO: more error handling + # Error for "x, y = 0" + if self->tokens->is_operator("="): + fail(self->tokens->location, "only one variable can be assigned at a time") + + if self->tokens->is_operator("="): + fail(self->tokens->location, "only one variable can be assigned at a time") if not self->tokens->is_operator(":"): self->tokens->fail_expected_got("':' and a type after it (example: \"foo, bar: int\")") @@ -868,6 +873,10 @@ class Parser: ntv.type = self->parse_type() + # Error for "x, y: int = 0" + if self->tokens->is_operator("="): + fail(self->tokens->location, "only one variable can be assigned at a time") + *self = save_state return ntv diff --git a/self_hosted/parses_wrong.txt b/self_hosted/parses_wrong.txt index 05762ff6..f3dcefd8 100644 --- a/self_hosted/parses_wrong.txt +++ b/self_hosted/parses_wrong.txt @@ -2,6 +2,3 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou -tests/syntax_error/double_assignment_comma_typed.jou -tests/syntax_error/double_assignment_comma_untyped.jou -tests/syntax_error/python_style_unpack.jou diff --git a/self_hosted/runs_wrong.txt b/self_hosted/runs_wrong.txt index 4e80e4f7..429a878e 100644 --- a/self_hosted/runs_wrong.txt +++ b/self_hosted/runs_wrong.txt @@ -16,6 +16,3 @@ tests/syntax_error/assign_to_None.jou tests/syntax_error/None_as_value.jou tests/should_succeed/method_by_value.jou tests/wrong_type/self_annotation.jou -tests/syntax_error/double_assignment_comma_typed.jou -tests/syntax_error/double_assignment_comma_untyped.jou -tests/syntax_error/python_style_unpack.jou From 173b5aba49a0d677f5366ed4736693472706381a Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 01:43:18 +0200 Subject: [PATCH 11/13] use it in tutorial --- doc/tutorial.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index f8395567..88edd8f3 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -308,13 +308,16 @@ def get_point(x: int*, y: int*) -> None: *y = 456 def main() -> int: - x: int - y: int + x, y: int get_point(&x, &y) printf("The point is (%d,%d)\n", x, y) # Output: The point is (123,456) return 0 ``` +Here `x, y: int` creates two local `int` variables without assigning values to them. +This means setting aside two 4-byte sections of the computer's memory. +We then tell the `get_point()` function to write into that memory. + Instead of pointers, you could also use an `int[2]` array to return the two values: ```python @@ -361,15 +364,14 @@ def get_point(x: int*, y: int*) -> None: *y = 456 def main() -> int: - x: int - y: int + x, y: int get_point(&x, &y) printf("The point is (%d,%d)\n", x, y) # Output: The point is (123,456) return 0 ``` -Here `x: int` creates a variable of type `int` without assigning a value to it. -If you try to use the value of `x` before it is set, +Here `x, y: int` creates two variables of type `int` without assigning values to them. +If you try to use the value of `x` or `y` before they are set, you will most likely get a compiler warning together with a random garbage value when the program runs. For example, if I delete the `get_point(&x, &y)` line, I get: From e36303cbafa0f39d40d926395cf269f5f47e5ef1 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 01:43:26 +0200 Subject: [PATCH 12/13] use it in aoc solutions --- examples/aoc2023/day03/part2.jou | 3 +-- examples/aoc2023/day05/part1.jou | 4 +--- examples/aoc2023/day05/part2.jou | 4 +--- examples/aoc2023/day24/part1.jou | 7 +------ examples/aoc2023/day24/part2.jou | 7 +------ examples/aoc2024/day01/part1.jou | 3 +-- examples/aoc2024/day13/part1.jou | 8 +------- examples/aoc2024/day13/part2.jou | 8 +------- examples/aoc2024/day14/part1.jou | 5 +---- examples/aoc2024/day14/part2.jou | 5 +---- examples/aoc2024/day18/part2.jou | 3 +-- 11 files changed, 11 insertions(+), 46 deletions(-) diff --git a/examples/aoc2023/day03/part2.jou b/examples/aoc2023/day03/part2.jou index c4853a2d..5fca6581 100644 --- a/examples/aoc2023/day03/part2.jou +++ b/examples/aoc2023/day03/part2.jou @@ -55,8 +55,7 @@ def find_adjacent_numbers(input: byte*, p: byte*) -> int[10]: for dx = -1; dx <= 1; dx++: neighbor = &p[dx + line_size*dy] if input <= neighbor and neighbor < &input[strlen(input)] and is_ascii_digit(*neighbor): - start: byte* - end: byte* + start, end: byte* find_whole_number(input, neighbor, &start, &end) if start != last_start or end != last_end: last_start = start diff --git a/examples/aoc2023/day05/part1.jou b/examples/aoc2023/day05/part1.jou index 89e5a592..b94fac06 100644 --- a/examples/aoc2023/day05/part1.jou +++ b/examples/aoc2023/day05/part1.jou @@ -9,9 +9,7 @@ class Map: ntriples: int def add_triple(self, s: byte*) -> None: - a: long - b: long - c: long + a, b, c: long assert sscanf(s, "%lld %lld %lld", &a, &b, &c) == 3 assert self->ntriples < sizeof(self->triples)/sizeof(self->triples[0]) diff --git a/examples/aoc2023/day05/part2.jou b/examples/aoc2023/day05/part2.jou index 746e30b8..ddde242c 100644 --- a/examples/aoc2023/day05/part2.jou +++ b/examples/aoc2023/day05/part2.jou @@ -42,9 +42,7 @@ class Map: ntriples: int def add_triple(self, s: byte*) -> None: - a: long - b: long - c: long + a, b, c: long assert sscanf(s, "%lld %lld %lld", &a, &b, &c) == 3 assert self->ntriples < sizeof(self->triples)/sizeof(self->triples[0]) diff --git a/examples/aoc2023/day24/part1.jou b/examples/aoc2023/day24/part1.jou index 2ad745b9..2db4f62b 100644 --- a/examples/aoc2023/day24/part1.jou +++ b/examples/aoc2023/day24/part1.jou @@ -164,12 +164,7 @@ def main() -> int: r: Ray - x: long - y: long - z: long - dx: long - dy: long - dz: long + x, y, z, dx, dy, dz: long while fscanf(f, "%lld, %lld, %lld @ %lld, %lld, %lld\n", &x, &y, &z, &dx, &dy, &dz) == 6: assert nrays < sizeof(rays)/sizeof(rays[0]) rays[nrays++] = Ray{start = [x,y], dir = [dx,dy]} diff --git a/examples/aoc2023/day24/part2.jou b/examples/aoc2023/day24/part2.jou index bbd41d4c..8fb596cc 100644 --- a/examples/aoc2023/day24/part2.jou +++ b/examples/aoc2023/day24/part2.jou @@ -174,12 +174,7 @@ def read_input(N: int) -> MovingPoint*: result: MovingPoint* = malloc(N * sizeof(result[0])) for i = 0; i < N; i++: - x: long - y: long - z: long - dx: long - dy: long - dz: long + x, y, z, dx, dy, dz: long assert fscanf(f, "%lld, %lld, %lld @ %lld, %lld, %lld\n", &x, &y, &z, &dx, &dy, &dz) == 6 result[i] = MovingPoint{start = [x,y,z], speed = [dx,dy,dz]} diff --git a/examples/aoc2024/day01/part1.jou b/examples/aoc2024/day01/part1.jou index cd6ff781..c2c1725f 100644 --- a/examples/aoc2024/day01/part1.jou +++ b/examples/aoc2024/day01/part1.jou @@ -19,8 +19,7 @@ def main() -> int: f = fopen("sampleinput.txt", "r") assert f != NULL - left_column: int[2000] - right_column: int[2000] + left_column, right_column: int[2000] n = 0 while fscanf(f, "%d %d", &left_column[n], &right_column[n]) == 2: n++ diff --git a/examples/aoc2024/day13/part1.jou b/examples/aoc2024/day13/part1.jou index 2f0c7806..d6c3328b 100644 --- a/examples/aoc2024/day13/part1.jou +++ b/examples/aoc2024/day13/part1.jou @@ -33,13 +33,7 @@ def main() -> int: assert f != NULL total_price = 0 - - ax: int - ay: int - bx: int - by: int - px: int - py: int + ax, ay, bx, by, cx, cy: int while True: ret = fscanf(f, "Button A: X+%d, Y+%d\n", &ax, &ay) diff --git a/examples/aoc2024/day13/part2.jou b/examples/aoc2024/day13/part2.jou index 3c226524..c6296007 100644 --- a/examples/aoc2024/day13/part2.jou +++ b/examples/aoc2024/day13/part2.jou @@ -181,13 +181,7 @@ def main() -> int: assert f != NULL total_price = 0L - - ax: long - ay: long - bx: long - by: long - px: long - py: long + ax, ay, bx, by, cx, cy: long while True: ret = fscanf(f, "Button A: X+%lld, Y+%lld\n", &ax, &ay) diff --git a/examples/aoc2024/day14/part1.jou b/examples/aoc2024/day14/part1.jou index 3371edea..2eb21087 100644 --- a/examples/aoc2024/day14/part1.jou +++ b/examples/aoc2024/day14/part1.jou @@ -52,10 +52,7 @@ def main() -> int: qcounts: int[5] = [0, 0, 0, 0, 0] - px: int - py: int - vx: int - vy: int + px, py, vx, vy: int while fscanf(f, "p=%d,%d v=%d,%d\n", &px, &py, &vx, &vy) == 4: x = (px + 100*vx) % width y = (py + 100*vy) % height diff --git a/examples/aoc2024/day14/part2.jou b/examples/aoc2024/day14/part2.jou index 787bbc28..318bdccb 100644 --- a/examples/aoc2024/day14/part2.jou +++ b/examples/aoc2024/day14/part2.jou @@ -40,10 +40,7 @@ def main() -> int: assert robots != NULL nrobots = 0 - px: int - py: int - vx: int - vy: int + px, py, vx, vy: int while fscanf(f, "p=%d,%d v=%d,%d\n", &px, &py, &vx, &vy) == 4: assert nrobots < max_robots robots[nrobots++] = Robot{ diff --git a/examples/aoc2024/day18/part2.jou b/examples/aoc2024/day18/part2.jou index cfcf88f6..b8b6539d 100644 --- a/examples/aoc2024/day18/part2.jou +++ b/examples/aoc2024/day18/part2.jou @@ -32,8 +32,7 @@ def main() -> int: assert f != NULL memset(&grid, '.', sizeof(grid)) - x_in: int - y_in: int + x_in, y_in: int while fscanf(f, "%d,%d\n", &x_in, &y_in) == 2: assert 0 <= x_in and x_in < size assert 0 <= y_in and y_in < size From 0ed339515d8065d84e4959b937feae8e7b7edd36 Mon Sep 17 00:00:00 2001 From: Akuli Date: Tue, 31 Dec 2024 02:01:10 +0200 Subject: [PATCH 13/13] fix --- examples/aoc2024/day13/part1.jou | 2 +- examples/aoc2024/day13/part2.jou | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/aoc2024/day13/part1.jou b/examples/aoc2024/day13/part1.jou index d6c3328b..896fe8ba 100644 --- a/examples/aoc2024/day13/part1.jou +++ b/examples/aoc2024/day13/part1.jou @@ -33,7 +33,7 @@ def main() -> int: assert f != NULL total_price = 0 - ax, ay, bx, by, cx, cy: int + ax, ay, bx, by, px, py: int while True: ret = fscanf(f, "Button A: X+%d, Y+%d\n", &ax, &ay) diff --git a/examples/aoc2024/day13/part2.jou b/examples/aoc2024/day13/part2.jou index c6296007..bf8c67ed 100644 --- a/examples/aoc2024/day13/part2.jou +++ b/examples/aoc2024/day13/part2.jou @@ -181,7 +181,7 @@ def main() -> int: assert f != NULL total_price = 0L - ax, ay, bx, by, cx, cy: long + ax, ay, bx, by, px, py: long while True: ret = fscanf(f, "Button A: X+%lld, Y+%lld\n", &ax, &ay)