mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fixed crash bug on missing module, and on file name == keyword. Added summary to tester and corrected filename.
This commit is contained in:
committed by
Christoffer Lerno
parent
bd68380f06
commit
e3566ba838
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
3
test/test_suite/functions/missing_first_paren.c3
Normal file
3
test/test_suite/functions/missing_first_paren.c3
Normal file
@@ -0,0 +1,3 @@
|
||||
func void foo) // #error: Expected '('
|
||||
{
|
||||
}
|
||||
3
test/test_suite/module/missing_semi.c3
Normal file
3
test/test_suite/module/missing_semi.c3
Normal file
@@ -0,0 +1,3 @@
|
||||
module test // #error: Expected ';'
|
||||
|
||||
int a;
|
||||
4
test/test_suite/module/unknown_modules.c3
Normal file
4
test/test_suite/module/unknown_modules.c3
Normal file
@@ -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.
|
||||
7
test/test_suite/statements/call_missing_paren.c3
Normal file
7
test/test_suite/statements/call_missing_paren.c3
Normal file
@@ -0,0 +1,7 @@
|
||||
func void foo(int a) {}
|
||||
|
||||
public func int main()
|
||||
{
|
||||
foo(10, foo(); // #error: Expected the ending ')'
|
||||
return 0;
|
||||
}
|
||||
2
test/test_suite/statements/default_args.c3
Normal file
2
test/test_suite/statements/default_args.c3
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
typedef func void (int a = 10) as Foo; // #error: Function types may not have default arguments.
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
// #skip
|
||||
module for_test;
|
||||
|
||||
public func int main()
|
||||
{
|
||||
@@ -28,4 +29,3 @@ public func int test3()
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
5
test/test_suite/statements/if_decl.c3
Normal file
5
test/test_suite/statements/if_decl.c3
Normal file
@@ -0,0 +1,5 @@
|
||||
public func int main()
|
||||
{
|
||||
if (int a) {} // #error: Expected a declaration with initializer
|
||||
return 0;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
9
test/test_suite/types/enum_illegal_type.c3
Normal file
9
test/test_suite/types/enum_illegal_type.c3
Normal file
@@ -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
|
||||
}
|
||||
4
test/test_suite/types/enum_overflow.c3
Normal file
4
test/test_suite/types/enum_overflow.c3
Normal file
@@ -0,0 +1,4 @@
|
||||
enum EnumTestOverflow
|
||||
{
|
||||
VALUE = 0x80000000, // #error: does not fit in type 'int'
|
||||
}
|
||||
@@ -15,7 +15,6 @@ enum EnumWithErrorData2 : int (int, int bar) // #error: function parameter must
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum EnumTestErrorType3 : int
|
||||
{
|
||||
A,
|
||||
|
||||
Reference in New Issue
Block a user