Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into aoc
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli committed Dec 23, 2023
2 parents 0c12304 + 23a3252 commit c5bbdab
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 8 deletions.
17 changes: 13 additions & 4 deletions self_hosted/typecheck.jou
Original file line number Diff line number Diff line change
Expand Up @@ -391,10 +391,19 @@ def handle_signature(ft: FileTypes*, astsig: AstSignature*, self_type: Type*) ->
else:
sig.return_type = type_from_ast(ft, &astsig->return_type)

# TODO: validate main() parameters
# TODO: test main() taking parameters
if self_type == NULL and strcmp(sig.name, "main") == 0 and sig.return_type != int_type:
fail(astsig->return_type.location, "the main() function must return int")
if self_type == NULL and strcmp(sig.name, "main") == 0:
# special main() function checks
if sig.return_type != int_type:
fail(astsig->return_type.location, "the main() function must return int")
if sig.nargs != 0 and not (
sig.nargs == 2
and sig.argtypes[0] == int_type
and sig.argtypes[1] == byte_type->get_pointer_type()->get_pointer_type()
):
fail(
astsig->args[0].type.location,
"if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int"
)

return sig

Expand Down
18 changes: 14 additions & 4 deletions src/typecheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,20 @@ static Signature handle_signature(FileTypes *ft, const AstSignature *astsig, con
else
sig.returntype = type_from_ast(ft, &astsig->returntype);

// TODO: validate main() parameters
// TODO: test main() taking parameters
if (!self_type && !strcmp(sig.name, "main") && sig.returntype != intType) {
fail(astsig->returntype.location, "the main() function must return int");
if (!self_type && !strcmp(sig.name, "main")) {
// special main() function checks
if (sig.returntype != intType)
fail(astsig->returntype.location, "the main() function must return int");
if (sig.nargs != 0 && !(
sig.nargs == 2
&& sig.argtypes[0] == intType
&& sig.argtypes[1] == get_pointer_type(get_pointer_type(byteType))))
{
fail(
astsig->args.ptr[0].type.location,
"if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int"
);
}
}

sig.returntype_location = astsig->returntype.location;
Expand Down
12 changes: 12 additions & 0 deletions tests/should_succeed/ascii_test.jou
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,16 @@ def main() -> int:
puts(words[i])
free(words)

s = ""
words = split_by_ascii_whitespace(s)
assert words[0] == NULL
free(words)

s = "test1 test2"
words = split_by_ascii_whitespace(s)
puts(words[0]) # Output: test1
puts(words[1]) # Output: test2
assert words[2] == NULL
free(words)

return 0
6 changes: 6 additions & 0 deletions tests/should_succeed/main_funny_arg_names.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import "stdlib/io.jou"

# Usually the args are named "argc" and "argv", but you can name them whatever you want.
def main(lol: int, wat: byte**) -> int:
printf("lol = %d\n", lol) # Output: lol = 1
return 0
3 changes: 3 additions & 0 deletions tests/wrong_type/deref_array.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def foo() -> int:
x = [1, 2, 3]
return *x # Error: the dereference operator '*' is only for pointers, not for int[3]
4 changes: 4 additions & 0 deletions tests/wrong_type/main_1_arg.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main(
argc: int # Error: if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int
) -> int:
return 0
4 changes: 4 additions & 0 deletions tests/wrong_type/main_3_args.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main(
argc: int, argv: byte**, lol: int # Error: if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int
) -> int:
return 0
4 changes: 4 additions & 0 deletions tests/wrong_type/main_argc.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main(
argc: long, argv: byte** # Error: if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int
) -> int:
return 0
4 changes: 4 additions & 0 deletions tests/wrong_type/main_argv.jou
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def main(
argc: int, argv: byte* # Error: if the main() function takes parameters, it should be defined like this: def main(argc: int, argv: byte**) -> int
) -> int:
return 0

0 comments on commit c5bbdab

Please sign in to comment.