From 5dabbe87ed4e86fa0306fd9ef11e7a7fee2a6ddb Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 8 May 2020 14:38:22 -0400 Subject: got double include to REALLY work --- foreign64.c | 19 ++++-- main.c | 3 +- misc.c | 4 ++ std/io.toc | 14 ++++- test.toc | 9 --- tests/.gitignore | 2 +- tests/std/io.toc | 9 +++ tests/test.bat | 4 +- tests/test.c | 177 ------------------------------------------------------ tests/test.sh | 2 +- tests/tests.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ types.c | 40 +++++++------ 12 files changed, 246 insertions(+), 216 deletions(-) delete mode 100644 tests/test.c create mode 100644 tests/tests.c diff --git a/foreign64.c b/foreign64.c index d00d5d2..0a0fc40 100644 --- a/foreign64.c +++ b/foreign64.c @@ -7,10 +7,17 @@ #error "What's going on? The 64-bit #foreign file was included, but size_t isn't 64 bits!" #endif +#ifdef __cplusplus +#define external extern "C" +#else +#define external extern +#endif + #ifdef _WIN64 -extern U64 win64_call(FnPtr fn, U64 *args, I64 nargs); -extern float win64_callf(FnPtr fn, U64 *args, I64 nargs); -extern double win64_calld(FnPtr fn, U64 *args, I64 nargs); + +external U64 win64_call(FnPtr fn, U64 *args, I64 nargs); +external float win64_callf(FnPtr fn, U64 *args, I64 nargs); +external double win64_calld(FnPtr fn, U64 *args, I64 nargs); static inline U64 foreign_calli(FnPtr fn, U64 *args, I64 nargs, bool *is_float) { (void)is_float; @@ -27,9 +34,9 @@ static inline double foreign_calld(FnPtr fn, U64 *args, I64 nargs, bool *is_floa return win64_calld(fn, args, nargs); } #else -extern U64 systemv64_call(FnPtr fn, U64 *args, I64 nargs, bool *is_float); -extern float systemv64_callf(FnPtr fn, U64 *args, I64 nargs, bool *is_float); -extern double systemv64_calld(FnPtr fn, U64 *args, I64 nargs, bool *is_float); +external U64 systemv64_call(FnPtr fn, U64 *args, I64 nargs, bool *is_float); +external float systemv64_callf(FnPtr fn, U64 *args, I64 nargs, bool *is_float); +external double systemv64_calld(FnPtr fn, U64 *args, I64 nargs, bool *is_float); static inline U64 foreign_calli(FnPtr fn, U64 *args, I64 nargs, bool *is_float) { return systemv64_call(fn, args, nargs, is_float); } diff --git a/main.c b/main.c index 74aada4..a584916 100644 --- a/main.c +++ b/main.c @@ -8,10 +8,11 @@ /* @TODO: -do #include "std/base.toc", base; in std/io.toc and std/mem.toc does our use before declare thing work with #include? +allow using constant before declaring it, and do DECL_FINDING_TYPE, for circular dependencies #no_warn start making a standard library... (printf; stringbuilder would be nice to have) +if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared) improve type_to_str: Foo ::= struct(t::Type) {} type_to_str(Foo(int)) diff --git a/misc.c b/misc.c index 056c84d..0a8ee86 100644 --- a/misc.c +++ b/misc.c @@ -62,6 +62,10 @@ static char *cstr(const char *str, size_t len) { return ret; } +static inline char *str_to_cstr(String s) { + return cstr(s.str, s.len); +} + static bool str_eq_cstr(String s, const char *str) { return strncmp(s.str, str, s.len) == 0; } diff --git a/std/io.toc b/std/io.toc index 9fa7e08..4f05be5 100644 --- a/std/io.toc +++ b/std/io.toc @@ -6,13 +6,14 @@ putchar ::= #foreign("putchar", base.libc) fn(#C int) #C int; toc_putchar ::= fn(x: char) { putchar(x as #C int); } +printf ::= #foreign("printf", base.libc) fn (#C &"const char", #C ..) #C int; /* unfortunately, we can't use fwrite because MSVC doesn't like it when you use a file handle that's not from the DLL. (i.e. you can't pass your stdout to the imported version of fwrite) */ - +/* writes ::= fn(x: []char) { for c := x { toc_putchar(c); @@ -50,4 +51,15 @@ puti ::= fn(x: int) { writei(x); toc_putchar('\n'); } +*/ +/* +writef ::= fn(x: float) { + fmt := "%f\0"; + printf(&fmt[0], x); +} +putf ::= fn(x: float) { + writef(x); + toc_putchar('\n'); +} +*/ diff --git a/test.toc b/test.toc index 57063b1..4a91877 100644 --- a/test.toc +++ b/test.toc @@ -1,10 +1 @@ #include "std/io.toc", io; -#include "std/io.toc", io; - -foo ::= #foreign("abort", "libc.so.6") fn(); - -main ::= fn() { - io.puts("hi"); - foo(); -} -main(); diff --git a/tests/.gitignore b/tests/.gitignore index 33ccc5b..9c57a91 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,5 +2,5 @@ got out.c a.out *.exe -test +tests *.core diff --git a/tests/std/io.toc b/tests/std/io.toc index 9fa7e08..2b9e999 100644 --- a/tests/std/io.toc +++ b/tests/std/io.toc @@ -51,3 +51,12 @@ puti ::= fn(x: int) { toc_putchar('\n'); } +printf ::= #foreign("printf", base.libc) fn (#C &"const char", #C ..) #C int; +writef ::= fn(x: float) { + fmt := "%f\0"; + printf(&fmt[0], x); +} +putf ::= fn(x: float) { + writef(x); + toc_putchar('\n'); +} diff --git a/tests/test.bat b/tests/test.bat index b8156ad..1acfe32 100644 --- a/tests/test.bat +++ b/tests/test.bat @@ -1,5 +1,5 @@ @echo off pushd "%~dp0" -cl /nologo test.c -test +cl /nologo tests.c +tests.exe popd diff --git a/tests/test.c b/tests/test.c deleted file mode 100644 index 0593c9d..0000000 --- a/tests/test.c +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include -#include -#ifdef __unix__ -#include -#define unix 1 -#endif - -static const char *tests[] = { - "bf", - "control_flow", - "types", - "include", - "arrs_slices", - "ptr_arithmetic", - "defer", -#ifndef __OpenBSD__ - "sizeof", /* OpenBSD's GCC doesn't support _Alignof */ -#endif - "new", - "arr", - "arr2", - "arr3", - "params", - "nms", - "varargs", - "printf", - "use", - "misc" -}; - -#define ntests ((int)(sizeof tests / sizeof *tests)) - -#ifdef _WIN32 -#define windows 1 -#include -#else -#define windows 0 -#endif - -#if windows -static const char *compilers[] = { - "cl /WX /nologo legacy_stdio_definitions.lib" -}; -#else -static const char *compilers[] = { - "gcc -O0 -g -Wno-parentheses-equality -Wno-builtin-declaration-mismatch -std=c99", - "clang -O3 -s -Wno-parentheses-equality -Wno-builtin-requires-header -Wno-format-security -std=c99" -#ifdef __linux__ /* couldn't get TCC to build on BSD */ - , - "tcc" -#endif -}; -#endif -#define ncompilers ((int)(sizeof compilers / sizeof *compilers)) - -static char *str_dup(const char *s) { - size_t bufsz = strlen(s)+1; - char *ret = malloc(bufsz); - memcpy(ret, s, bufsz); - return ret; -} - - -int main(int argc, char **argv) { - int i, c; - char command[256]; - int color = 0; - int valgrind = 0; -#if unix - color = isatty(1); - #ifdef __linux__ /* valgrind is complaining a lot on BSD, but i think it's wrong */ - valgrind = 1; - #endif -#endif - char const *failed; - if (color) { - failed = "\x1b[91mFAILED\x1b[0m"; - } else { - failed = "FAILED"; - } - for (i = 0; i < ntests; ++i) { - const char *test = tests[i]; - printf("Running test %s... ", test); - fflush(stdout); - if (windows) { - sprintf(command, "..\\toc %s.toc", test); - } else if (valgrind) { - sprintf(command, "valgrind -q --error-exitcode=1 ../toc %s.toc", test); - } else { - sprintf(command, "../toc %s.toc", test); - } - if (system(command)) { - fprintf(stderr, "%s (while compiling toc).\n", failed); - return EXIT_FAILURE; - } - for (c = 0; c < ncompilers; ++c) { - const char *compiler = str_dup(compilers[c]); - char *p = strchr(compiler, ' '); - if (p) *p = 0; - printf("on %s... ", compiler); - if (p) *p = ' '; - fflush(stdout); - if (windows) { - sprintf(command, "%s out.c", compiler); - } else { - sprintf(command, "%s out.c", compiler); - } - if (system(command)) { - fprintf(stderr, "%s (while compiling C).\n", failed); - return EXIT_FAILURE; - } - { - int ret; - if (windows) - ret = system("out > got"); - else - ret = system("./a.out > got"); - if (ret != 0) { - fprintf(stderr, "%s (while running).\n", failed); - return EXIT_FAILURE; - } - } - - { - char filename[32]; - sprintf(filename, "%s_expected", test); - char *expected = NULL, *got = NULL; - FILE *expected_f = fopen(filename, "rb"); - if (!expected_f) { - fprintf(stderr, "%s (couldn't open %s).\n", failed, filename); - return EXIT_FAILURE; - } - fseek(expected_f, 0L, SEEK_END); - size_t expected_size = (size_t)ftell(expected_f); - fseek(expected_f, 0L, SEEK_SET); - expected = malloc(expected_size); - fread(expected, 1, expected_size, expected_f); - fclose(expected_f); - FILE *got_f = fopen("got", "rb"); - if (!got_f) { - fprintf(stderr, "%s (couldn't open got).\n", failed); - return EXIT_FAILURE; - } - fseek(got_f, 0L, SEEK_END); - size_t got_size = (size_t)ftell(got_f); - fseek(got_f, 0L, SEEK_SET); - got = malloc(got_size); - fread(got, 1, got_size, got_f); - fclose(got_f); - if (expected_size != got_size) { - fprintf(stderr, "%s (mismatch between expected/got file sizes).\n", failed); - return EXIT_FAILURE; - } - if (memcmp(expected, got, expected_size) != 0) { - fprintf(stderr, "%s (mismatch between expected/got file contents).\n", failed); - return EXIT_FAILURE; - } - free(expected); free(got); - } - if (windows) - remove("out.exe"); - } - if (windows) { - } else { - remove("a.out"); - } - remove("out.c"); - remove("got"); - if (color) { - printf("\x1b[92msuccess!\x1b[0m\n"); - } else { - printf("success!\n"); - } - } - return 0; -} diff --git a/tests/test.sh b/tests/test.sh index ce7b294..779fafe 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,4 +1,4 @@ #!/bin/sh cd $(dirname $0) -cc test.c -o test -Wall -Wconversion -Wshadow -Werror && ./test +cc tests.c -o tests -Wall -Wconversion -Wshadow -Werror && ./tests || exit 1 cd - >/dev/null diff --git a/tests/tests.c b/tests/tests.c new file mode 100644 index 0000000..57f611e --- /dev/null +++ b/tests/tests.c @@ -0,0 +1,179 @@ +#include +#include +#include +#ifdef __unix__ +#include +#define unix 1 +#endif + +static const char *tests[] = { + "bf", + "control_flow", + "types", + "include", + "arrs_slices", + "ptr_arithmetic", + "defer", +#ifndef __OpenBSD__ + "sizeof", /* OpenBSD's GCC doesn't support _Alignof */ +#endif + "new", + "arr", + "arr2", + "arr3", + "params", + "nms", + "varargs", + "printf", + "use", + "misc" +}; + +#define ntests ((int)(sizeof tests / sizeof *tests)) + +#ifdef _WIN32 +#define windows 1 +#include +#else +#define windows 0 +#endif + +#if windows +static const char *compilers[] = { + "cl /WX /nologo legacy_stdio_definitions.lib" +}; +#else +static const char *compilers[] = { + "gcc -O0 -g -Wno-parentheses-equality -Wno-builtin-declaration-mismatch -std=c99", + "clang -O3 -s -Wno-parentheses-equality -Wno-builtin-requires-header -Wno-format-security -std=c99" +#ifdef __linux__ /* couldn't get TCC to build on BSD */ + , + "tcc" +#endif +}; +#endif +#define ncompilers ((int)(sizeof compilers / sizeof *compilers)) + +static char *str_dup(const char *s) { + size_t bufsz = strlen(s)+1; + char *ret = malloc(bufsz); + memcpy(ret, s, bufsz); + return ret; +} + + +int main(int argc, char **argv) { + int i, c; + char command[256]; + int color = 0; + int valgrind = 0; +#if unix + color = isatty(1); + #ifdef __linux__ /* valgrind is complaining a lot on BSD, but i think it's wrong */ + valgrind = 1; + #endif +#endif + char const *failed; + if (color) { + failed = "\x1b[91mFAILED\x1b[0m"; + } else { + failed = "FAILED"; + } + for (i = 0; i < ntests; ++i) { + const char *test = tests[i]; + printf("Running test %s... ", test); + fflush(stdout); + if (windows) { + sprintf(command, "..\\toc %s.toc", test); + } else if (valgrind) { + sprintf(command, "valgrind -q --error-exitcode=1 ../toc %s.toc", test); + } else { + sprintf(command, "../toc %s.toc", test); + } + if (system(command)) { + fprintf(stderr, "%s (while compiling toc).\n", failed); + return EXIT_FAILURE; + } + for (c = 0; c < ncompilers; ++c) { + const char *compiler = str_dup(compilers[c]); + if (strcmp(test, "sizeof") == 0 && strncmp(compiler, "tcc", 3) == 0) + continue; /* i think some versions of tcc have _Alignof but some don't */ + char *p = strchr(compiler, ' '); + if (p) *p = 0; + printf("on %s... ", compiler); + if (p) *p = ' '; + fflush(stdout); + if (windows) { + sprintf(command, "%s out.c", compiler); + } else { + sprintf(command, "%s out.c", compiler); + } + if (system(command)) { + fprintf(stderr, "%s (while compiling C).\n", failed); + return EXIT_FAILURE; + } + { + int ret; + if (windows) + ret = system("out > got"); + else + ret = system("./a.out > got"); + if (ret != 0) { + fprintf(stderr, "%s (while running).\n", failed); + return EXIT_FAILURE; + } + } + + { + char filename[32]; + sprintf(filename, "%s_expected", test); + char *expected = NULL, *got = NULL; + FILE *expected_f = fopen(filename, "rb"); + if (!expected_f) { + fprintf(stderr, "%s (couldn't open %s).\n", failed, filename); + return EXIT_FAILURE; + } + fseek(expected_f, 0L, SEEK_END); + size_t expected_size = (size_t)ftell(expected_f); + fseek(expected_f, 0L, SEEK_SET); + expected = malloc(expected_size); + fread(expected, 1, expected_size, expected_f); + fclose(expected_f); + FILE *got_f = fopen("got", "rb"); + if (!got_f) { + fprintf(stderr, "%s (couldn't open got).\n", failed); + return EXIT_FAILURE; + } + fseek(got_f, 0L, SEEK_END); + size_t got_size = (size_t)ftell(got_f); + fseek(got_f, 0L, SEEK_SET); + got = malloc(got_size); + fread(got, 1, got_size, got_f); + fclose(got_f); + if (expected_size != got_size) { + fprintf(stderr, "%s (mismatch between expected/got file sizes).\n", failed); + return EXIT_FAILURE; + } + if (memcmp(expected, got, expected_size) != 0) { + fprintf(stderr, "%s (mismatch between expected/got file contents).\n", failed); + return EXIT_FAILURE; + } + free(expected); free(got); + } + if (windows) + remove("out.exe"); + } + if (windows) { + } else { + remove("a.out"); + } + remove("out.c"); + remove("got"); + if (color) { + printf("\x1b[92msuccess!\x1b[0m\n"); + } else { + printf("success!\n"); + } + } + return 0; +} diff --git a/types.c b/types.c index 7e4b56c..e657799 100644 --- a/types.c +++ b/types.c @@ -3728,8 +3728,8 @@ static Status types_stmt(Typer *tr, Statement *s) { char *filename = eval_expr_as_cstr(tr, &inc->filename, "import filename"); if (!filename) return false; + Namespace *prev_nms = tr->nms; IncludedFile *inc_f = NULL; - Namespace *inc_nms = NULL; /* non-NULL if this is an include to nms */ if (inc->nms) { inc_nms = typer_calloc(tr, 1, sizeof *inc_nms); @@ -3738,6 +3738,9 @@ static Status types_stmt(Typer *tr, Statement *s) { body->where = s->where; idents_create(&body->idents, tr->allocr, body); body->parent = tr->block; + /* go inside namespace and block (it'll help to be there later on) */ + tr->nms = inc_nms; + typer_block_enter(tr, &inc_nms->body); } s->kind = STMT_INLINE_BLOCK; @@ -3750,7 +3753,7 @@ static Status types_stmt(Typer *tr, Statement *s) { s->inline_block = NULL; /* nothing needed here */ /* just set ident declarations */ if (!include_stmts_link_to_nms(tr, inc_f->main_nms, inc_f->stmts)) - return false; + goto inc_fail; goto nms_transform; } inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len); @@ -3760,7 +3763,7 @@ static Status types_stmt(Typer *tr, Statement *s) { char *contents = read_file_contents(tr->allocr, filename, s->where); if (!contents) { tr->had_include_err = true; - return false; + goto inc_fail; } Tokenizer tokr; @@ -3771,38 +3774,34 @@ static Status types_stmt(Typer *tr, Statement *s) { file->ctx = tr->err_ctx; if (!tokenize_file(&tokr, file)) - return false; + goto inc_fail; Parser parser; parser_create(&parser, tr->globals, &tokr, tr->allocr); - parser.block = inc_nms ? &inc_nms->body : tr->block; + parser.block = tr->block; ParsedFile parsed_file; if (!parse_file(&parser, &parsed_file)) { - return false; + goto inc_fail; } Statement *stmts_inc = parsed_file.stmts; if (inc_f) { inc_f->stmts = stmts_inc; } s->inline_block = stmts_inc; - Namespace *prev_nms = tr->nms; - Block *prev_block = tr->block; - if (inc_nms) { - tr->nms = inc_nms; - tr->block = &inc_nms->body; - } arr_foreach(stmts_inc, Statement, s_incd) { if (!types_stmt(tr, s_incd)) { - return false; + goto inc_fail; } } if (inc_nms) { - tr->nms = prev_nms; - tr->block = prev_block; inc_nms->body.stmts = stmts_inc; } } - nms_transform: + nms_transform: if (inc_nms) { + /* go back to parent namespace/block because that's where the declaration is gonna be */ + tr->nms = prev_nms; + typer_block_exit(tr); + inc_nms->inc_file = inc_f; /* turn #include "foo", bar into bar ::= nms { ... } */ s->kind = STMT_DECL; @@ -3826,7 +3825,7 @@ static Status types_stmt(Typer *tr, Statement *s) { err_print(s->where, "Redeclaration of identifier %s.", istr); info_print(ident_decl_location(i), "Previous declaration was here."); free(istr); - return false; + goto inc_fail; } } i->decl = d; @@ -3838,7 +3837,12 @@ static Status types_stmt(Typer *tr, Statement *s) { d->val.nms = inc_nms; d->where = d->expr.where = s->where; } - } break; + break; + inc_fail: + tr->nms = prev_nms; + typer_block_exit(tr); + return false; + } case STMT_MESSAGE: { Message *m = s->message; char *text = eval_expr_as_cstr(tr, &m->text, "message"); -- cgit v1.2.3