From e3566ba83827e77bd127672176f66a3b936ee2bb Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 25 Jul 2020 12:50:02 +0200 Subject: [PATCH] Fixed crash bug on missing module, and on file name == keyword. Added summary to tester and corrected filename. --- src/compiler/context.c | 5 ++-- src/compiler/diagnostics.c | 3 +++ src/compiler/parser.c | 16 ++++++------ test/src/tester.py | 26 +++++++++++++------ .../functions/missing_first_paren.c3 | 3 +++ test/test_suite/module/missing_semi.c3 | 3 +++ test/test_suite/module/unknown_modules.c3 | 4 +++ .../statements/call_missing_paren.c3 | 7 +++++ test/test_suite/statements/default_args.c3 | 2 ++ test/test_suite/statements/for.c3 | 4 +-- test/test_suite/statements/if_decl.c3 | 5 ++++ test/test_suite/types/enum_errors.c3 | 17 ------------ test/test_suite/types/enum_illegal_type.c3 | 9 +++++++ test/test_suite/types/enum_overflow.c3 | 4 +++ test/test_suite/types/enum_parse_errors.c3 | 1 - 15 files changed, 71 insertions(+), 38 deletions(-) create mode 100644 test/test_suite/functions/missing_first_paren.c3 create mode 100644 test/test_suite/module/missing_semi.c3 create mode 100644 test/test_suite/module/unknown_modules.c3 create mode 100644 test/test_suite/statements/call_missing_paren.c3 create mode 100644 test/test_suite/statements/default_args.c3 create mode 100644 test/test_suite/statements/if_decl.c3 create mode 100644 test/test_suite/types/enum_illegal_type.c3 create mode 100644 test/test_suite/types/enum_overflow.c3 diff --git a/src/compiler/context.c b/src/compiler/context.c index b6ce6e75e..dac4e4352 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -39,7 +39,7 @@ bool context_set_module_from_filename(Context *context) int len = filename_to_module(context->file->full_path, buffer); if (!len) { - sema_error(context, "The filename '%s' could not be converted to a valid module name, try using an explicit module name."); + sema_error(context, "The filename '%s' could not be converted to a valid module name, try using an explicit module name.", context->file->full_path); return false; } @@ -48,7 +48,7 @@ bool context_set_module_from_filename(Context *context) if (type != TOKEN_IDENT) { sema_error(context, "Generating a filename from the file '%s' resulted in a name that is a reserved keyword, " - "try using an explicit module name."); + "try using an explicit module name.", context->file->full_path); return false; } Path *path = CALLOCS(Path); @@ -165,6 +165,7 @@ bool context_add_import(Context *context, Path *path, Token token, Token alias) } Decl *import = decl_calloc(); + import->span = path->span; import->decl_kind = DECL_IMPORT; import->visibility = VISIBLE_LOCAL; import->import.path = path; diff --git a/src/compiler/diagnostics.c b/src/compiler/diagnostics.c index 75b0af83a..3919950da 100644 --- a/src/compiler/diagnostics.c +++ b/src/compiler/diagnostics.c @@ -189,6 +189,7 @@ void sema_error_at_prev_end(Token token, const char *message, ...) void sema_error(Context *context, const char *message, ...) { + diagnostics.errors++; File *file = lexer_current_file(&context->lexer); va_list list; va_start(list, message); @@ -196,6 +197,8 @@ void sema_error(Context *context, const char *message, ...) evprintf(message, list); eprintf("\n"); va_end(list); + + } diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 30a17ccd6..69275b1be 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -1753,19 +1753,18 @@ static inline bool parse_optional_module_params(Context *context, TokenId **toke * : MODULE path ';' * | MODULE path '(' module_params ')' ';' */ -static inline void parse_module(Context *context) +static inline bool parse_module(Context *context) { if (!try_consume(context, TOKEN_MODULE)) { - context_set_module_from_filename(context); - return; + return context_set_module_from_filename(context); } if (!TOKEN_IS(TOKEN_IDENT)) { SEMA_TOKEN_ERROR(context->tok, "Module statement should be followed by the name of the module to import."); - return; + return false; } Path *path = parse_module_path(context); @@ -1779,7 +1778,7 @@ static inline void parse_module(Context *context) path->span = INVALID_RANGE; context_set_module(context, path, NULL); recover_top_level(context); - return; + return false; } // Is this a generic module? @@ -1788,10 +1787,11 @@ static inline void parse_module(Context *context) { context_set_module(context, path, generic_parameters); recover_top_level(context); - return; + return true; } context_set_module(context, path, generic_parameters); - TRY_CONSUME_EOS_OR(); + TRY_CONSUME_EOS_OR(false); + return true; } /** @@ -1906,7 +1906,7 @@ static inline void parse_current(Context *context) { // Prime everything advance(context); advance(context); - parse_module(context); + if (!parse_module(context)) return; parse_imports(context); while (!TOKEN_IS(TOKEN_EOF)) { diff --git a/test/src/tester.py b/test/src/tester.py index e2028ffc4..44201a6c8 100644 --- a/test/src/tester.py +++ b/test/src/tester.py @@ -2,21 +2,26 @@ import os, sys, shutil, subprocess TEST_DIR = '/tmp/c3test/' + class Config: run_skipped = False cwd = "." numtests = 0 + numsuccess = 0 + numskipped = 0 class File: def __init__(self, filepath): with open(filepath) as reader: self.content = reader.read().splitlines() - self.filename = filepath + self.filepath = filepath + self.filename = os.path.basename(filepath) class Issues: def __init__(self, conf, file, single): + self.conf = conf self.file = file self.single = single self.line = 0 @@ -30,10 +35,10 @@ class Issues: self.errors = {} self.warnings = {} if single: - self.current_file = conf.cwd + "/" + file.filename + self.current_file = conf.cwd + "/" + file.filepath def exit_error(self, message): - print('Error in file ' + self.file.filename + ': ' + message) + print('Error in file ' + self.file.filepath + ': ' + message) exit(-1) def set_failed(self): @@ -41,7 +46,6 @@ class Issues: self.has_errors = True def check_line(self, type, file, line, message): - if file == 'test.c3': file = self.file.filename map = {} if type == 'Error': map = self.errors @@ -92,13 +96,15 @@ class Issues: if "// #" in line: self.parse_trailing_directive(line) self.line += 1 - with open(TEST_DIR + 'test.c3', mode='w') as f: + target_file = TEST_DIR + self.file.filename + with open(target_file, mode='w') as f: f.write("\n".join(self.file.content)) f.write("\n") - print("- " + self.file.filename + ":", end="") - self.compile("--test compile " + TEST_DIR + 'test.c3') + print("- " + self.file.filepath + ":", end="") + self.compile("--test compile " + target_file) if not self.has_errors: + self.conf.numsuccess += 1 print(" Passed.") def parse_header_directive(self, line): @@ -143,7 +149,10 @@ class Issues: def parse(self): if len(self.file.content) == 0: self.exit_error("File was empty") is_skip = self.file.content[0].startswith("// #skip") - if is_skip != self.skip: return + if is_skip != self.skip: + print("- " + self.file.filepath + ": *SKIPPED*") + self.conf.numskipped += 1 + return if is_skip: self.line += 1 if self.single: @@ -201,5 +210,6 @@ def main(): handle_dir(filepath, conf) else: usage() + print("Found %d tests: %d / %d passed (%d skipped)." % (conf.numtests, conf.numsuccess, conf.numtests - conf.numskipped, conf.numskipped)) main() diff --git a/test/test_suite/functions/missing_first_paren.c3 b/test/test_suite/functions/missing_first_paren.c3 new file mode 100644 index 000000000..fdd38d7d6 --- /dev/null +++ b/test/test_suite/functions/missing_first_paren.c3 @@ -0,0 +1,3 @@ +func void foo) // #error: Expected '(' +{ +} diff --git a/test/test_suite/module/missing_semi.c3 b/test/test_suite/module/missing_semi.c3 new file mode 100644 index 000000000..ce8ae0942 --- /dev/null +++ b/test/test_suite/module/missing_semi.c3 @@ -0,0 +1,3 @@ +module test // #error: Expected ';' + +int a; \ No newline at end of file diff --git a/test/test_suite/module/unknown_modules.c3 b/test/test_suite/module/unknown_modules.c3 new file mode 100644 index 000000000..42c12d96c --- /dev/null +++ b/test/test_suite/module/unknown_modules.c3 @@ -0,0 +1,4 @@ +module test; + +import foo; // #error: No module named 'foo' could be found. +import bar; // #error: No module named 'bar' could be found. \ No newline at end of file diff --git a/test/test_suite/statements/call_missing_paren.c3 b/test/test_suite/statements/call_missing_paren.c3 new file mode 100644 index 000000000..4c42fd326 --- /dev/null +++ b/test/test_suite/statements/call_missing_paren.c3 @@ -0,0 +1,7 @@ +func void foo(int a) {} + +public func int main() +{ + foo(10, foo(); // #error: Expected the ending ')' + return 0; +} \ No newline at end of file diff --git a/test/test_suite/statements/default_args.c3 b/test/test_suite/statements/default_args.c3 new file mode 100644 index 000000000..885e2d44c --- /dev/null +++ b/test/test_suite/statements/default_args.c3 @@ -0,0 +1,2 @@ + +typedef func void (int a = 10) as Foo; // #error: Function types may not have default arguments. diff --git a/test/test_suite/statements/for.c3 b/test/test_suite/statements/for.c3 index 00d8fe10a..f3458752c 100644 --- a/test/test_suite/statements/for.c3 +++ b/test/test_suite/statements/for.c3 @@ -1,4 +1,5 @@ -/* +// #skip +module for_test; public func int main() { @@ -28,4 +29,3 @@ public func int test3() } return 0; } -*/ \ No newline at end of file diff --git a/test/test_suite/statements/if_decl.c3 b/test/test_suite/statements/if_decl.c3 new file mode 100644 index 000000000..8e3e9a0ae --- /dev/null +++ b/test/test_suite/statements/if_decl.c3 @@ -0,0 +1,5 @@ +public func int main() +{ + if (int a) {} // #error: Expected a declaration with initializer + return 0; +} diff --git a/test/test_suite/types/enum_errors.c3 b/test/test_suite/types/enum_errors.c3 index 8ac1b89bb..5c08c05de 100644 --- a/test/test_suite/types/enum_errors.c3 +++ b/test/test_suite/types/enum_errors.c3 @@ -1,21 +1,4 @@ - -enum EnumTestOverflow -{ - VALUE = 0x80000000, // #error: does not fit in type 'int' -} - -enum EnumTestErrorType : float // #error: must be an integer type not 'float' -{ - VALUE_BOOM -} - - -enum EnumWithErrorType2 : int* // #error: must be an integer type not 'int*' -{ - TEST -} - enum EnumTestErrorType3 : int { A = FOO // #error: Identifier 'FOO' could not be found diff --git a/test/test_suite/types/enum_illegal_type.c3 b/test/test_suite/types/enum_illegal_type.c3 new file mode 100644 index 000000000..0c2a2610a --- /dev/null +++ b/test/test_suite/types/enum_illegal_type.c3 @@ -0,0 +1,9 @@ +enum EnumTestErrorType : float // #error: must be an integer type not 'float' +{ + VALUE_BOOM +} + +enum EnumWithErrorType2 : int* // #error: must be an integer type not 'int*' +{ + TEST +} \ No newline at end of file diff --git a/test/test_suite/types/enum_overflow.c3 b/test/test_suite/types/enum_overflow.c3 new file mode 100644 index 000000000..d6a085cc4 --- /dev/null +++ b/test/test_suite/types/enum_overflow.c3 @@ -0,0 +1,4 @@ +enum EnumTestOverflow +{ + VALUE = 0x80000000, // #error: does not fit in type 'int' +} \ No newline at end of file diff --git a/test/test_suite/types/enum_parse_errors.c3 b/test/test_suite/types/enum_parse_errors.c3 index c46dc3e8f..3a5a45fed 100644 --- a/test/test_suite/types/enum_parse_errors.c3 +++ b/test/test_suite/types/enum_parse_errors.c3 @@ -15,7 +15,6 @@ enum EnumWithErrorData2 : int (int, int bar) // #error: function parameter must } - enum EnumTestErrorType3 : int { A,