From dc9cebe15132c5a15b3d0648285e9c86e40c14f6 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Sun, 5 Jan 2020 22:31:07 -0500 Subject: better package file output --- .gitignore | 2 +- cgen.c | 3 ++- err.c | 4 ++-- main.c | 16 +--------------- package.c | 14 +++++++++++++- parse.c | 3 ++- point.toc | 12 ++++++++++++ test.toc | 23 ----------------------- tokenizer.c | 2 +- types.c | 22 ++++++++++++++++------ 10 files changed, 50 insertions(+), 51 deletions(-) create mode 100644 point.toc delete mode 100644 test.toc diff --git a/.gitignore b/.gitignore index 594ef43..fae512f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ toc a.out out.c -out.top +*.top tests/**/*.c tests/**/*.bin vgcore* diff --git a/cgen.c b/cgen.c index 915d7b5..c8daec9 100644 --- a/cgen.c +++ b/cgen.c @@ -1981,7 +1981,8 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) { if (!cgen_decls_file(g, f)) return false; cgen_write(g, "/* code */\n"); - cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n\n"); + if (!f->pkg_name) + cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n\n"); arr_foreach(f->stmts, Statement, s) { if (!cgen_defs_stmt(g, s)) return false; diff --git a/err.c b/err.c index 0a519c1..a98a822 100644 --- a/err.c +++ b/err.c @@ -126,7 +126,7 @@ static void err_print_footer_(Location where) { static void err_vprint(Location where, const char *fmt, va_list args) { - if (!where.ctx->enabled) return; + if (where.ctx && !where.ctx->enabled) return; err_print_header_(where); err_vfprint(fmt, args); err_print_footer_(where); @@ -139,8 +139,8 @@ static void err_print_( #endif Location where, const char *fmt, ...) { va_list args; - if (where.ctx && !where.ctx->enabled) return; #if ERR_SHOW_SOURCE_LOCATION + if (where.ctx && !where.ctx->enabled) return; if (file) err_fprint("Generated by line %d of %s:\n", line, file); #endif diff --git a/main.c b/main.c index e7b8567..f848130 100644 --- a/main.c +++ b/main.c @@ -49,7 +49,6 @@ int main(int argc, char **argv) { in_filename = argv[1]; } const char *out_filename = "out.c"; - for (int i = 2; i < argc-1; ++i) { if (strcmp(argv[i], "-o") == 0) out_filename = argv[i+1]; @@ -122,27 +121,14 @@ int main(int argc, char **argv) { typer_create(&tr, &ev, &main_allocr); tr.exptr = &exptr; -#ifdef TOC_DEBUG - FILE *out_pkg = fopen("out.top", "wb"); - exptr_create(&exptr, out_pkg, contents); - exptr.export_locations = false; -#endif if (!block_enter(NULL, f.stmts, SCOPE_CHECK_REDECL)) /* enter global scope */ return false; - if (!types_file(&tr, &f)) { + if (!types_file(&tr, &f, contents)) { /* TODO(eventually): fix this if the error occured while exporting something */ err_fprint(TEXT_IMPORTANT("Errors occured while determining types.\n")); return EXIT_FAILURE; } -#ifdef TOC_DEBUG - if (!exptr_finish(&exptr)) { - fclose(out_pkg); - err_fprint(TEXT_IMPORTANT("Errors occured while exporting things.\n")); - return EXIT_FAILURE; - } - fclose(out_pkg); -#endif #ifdef TOC_DEBUG printf("\n\n"); fprint_parsed_file(stdout, &f); diff --git a/package.c b/package.c index 7d42928..4763843 100644 --- a/package.c +++ b/package.c @@ -99,13 +99,15 @@ static inline void export_len(Exporter *ex, size_t len) { /* writes the header */ static void exptr_start(Exporter *ex, const char *pkg_name, size_t pkg_name_len) { - const U8 toc[3] = {116, 111, 99}; /* "toc" in ASCII */ + const U8 toc[3] = {116, 111, 112}; /* "top" in ASCII */ const char *code = ex->code; ex->started = true; export_u8(ex, toc[0]); export_u8(ex, toc[1]); export_u8(ex, toc[2]); export_u32(ex, TOP_FMT_VERSION); + assert(ftell(ex->out) == 7L); + export_u32(ex, 0); /* placeholder for identifier offset in file */ export_len(ex, pkg_name_len); export_str(ex, pkg_name, pkg_name_len); bool has_code = code != NULL; @@ -555,6 +557,16 @@ static bool export_struct(Exporter *ex, StructDef *s) { /* does NOT close the file */ static bool exptr_finish(Exporter *ex) { + long ident_offset = ftell(ex->out); + fseek(ex->out, 7L, SEEK_SET); + if (ident_offset > U32_MAX) { + err_print(LOCATION_NONE, "Package file is too large."); + return false; + } + export_u32(ex, (U32)ident_offset); + fseek(ex->out, 0L, SEEK_END); + + export_len(ex, arr_len(ex->exported_idents)); arr_foreach(ex->exported_idents, Identifier, ident) { Identifier i = *ident; diff --git a/parse.c b/parse.c index ac87acc..3b85e87 100644 --- a/parse.c +++ b/parse.c @@ -1818,6 +1818,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla case DECL_END_RPAREN_COMMA: end_str = "')' or ','"; break; case DECL_END_LBRACE_COMMA: end_str = "'{' or ','"; break; } + assert(end_str); if (token_is_kw(t->token, KW_EQ)) { ++t->token; @@ -1842,7 +1843,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla expr_flags |= EXPR_CAN_END_WITH_LBRACE; Token *end = expr_find_end(p, expr_flags); if (!end || !ends_decl(end, ends_with)) { - t->token = end; + if (end) t->token = end; tokr_err(t, "Expected %s at end of declaration.", end_str); goto ret_false; } diff --git a/point.toc b/point.toc new file mode 100644 index 0000000..e37f37a --- /dev/null +++ b/point.toc @@ -0,0 +1,12 @@ +pkg "point"; + +#export Point ::= struct { + x, y: int; +}; + +#export mk_point ::= fn(x, y: int) Point { + p : Point; + p.x = x; + p.y = y; + p +}; diff --git a/test.toc b/test.toc deleted file mode 100644 index 5a69154..0000000 --- a/test.toc +++ /dev/null @@ -1,23 +0,0 @@ -pkg "foo"; - -Foo ::= struct { - x: int; -}; - -foo ::= fn() int { - 3 -}; -#export main ::= fn() { - g ::= fn() int { 3 }; - a := new (int, 3); - b := a[1:3]; - b[0] = 7; - f: Foo; - each i, j := b { - f.x += i + j; - } - each k := 10..100 { - f.x += k; - } - del(a); -}; \ No newline at end of file diff --git a/tokenizer.c b/tokenizer.c index 4c1d31a..901c2ee 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -171,8 +171,8 @@ static void tokr_err_( const char *src_file, int src_line, #endif Tokenizer *t, const char *fmt, ...) { - if (!t->token->where.ctx->enabled) return; #if ERR_SHOW_SOURCE_LOCATION + if (t->token->where.ctx && !t->token->where.ctx->enabled) return; err_fprint("At line %d of %s:\n", src_line, src_file); #endif va_list args; diff --git a/types.c b/types.c index fab4c73..50da073 100644 --- a/types.c +++ b/types.c @@ -2045,12 +2045,7 @@ static bool types_decl(Typer *tr, Declaration *d) { err_print(d->where, "Declaration marked for exporting, but no package output was specified."); success = false; } else { -#ifdef TOC_DEBUG /* TODO: remove this */ success = export_decl(tr->exptr, d); -#else - err_print(d->where, "This feature is in progress."); - success = false; -#endif } } } else { @@ -2125,8 +2120,9 @@ static void typer_create(Typer *tr, Evaluator *ev, Allocator *allocr) { *(Block **)arr_adda(&tr->blocks, allocr) = NULL; } -static bool types_file(Typer *tr, ParsedFile *f) { +static bool types_file(Typer *tr, ParsedFile *f, char *code) { bool ret = true; + FILE *pkg_fp = NULL; if (f->pkg_name) { Value pkg_name; if (!types_expr(tr, f->pkg_name)) @@ -2146,6 +2142,16 @@ static bool types_file(Typer *tr, ParsedFile *f) { err_print(f->pkg_name->where, "Package name has a negative length (" I64_FMT ")!", pkg_name_len); return false; } + char *pkg_file_name = err_malloc((size_t)pkg_name_len+5); + sprintf(pkg_file_name, "%s.top", pkg_name_str); + pkg_fp = fopen(pkg_file_name, "wb"); + if (!pkg_fp) { + err_print(f->pkg_name->where, "Could not open package output file: %s.", pkg_file_name); + free(pkg_file_name); + return false; + } + free(pkg_file_name); + exptr_create(tr->exptr, pkg_fp, code); exptr_start(tr->exptr, pkg_name_str, (size_t)pkg_name_len); } arr_foreach(f->stmts, Statement, s) { @@ -2153,6 +2159,10 @@ static bool types_file(Typer *tr, ParsedFile *f) { ret = false; } } + if (pkg_fp) { + exptr_finish(tr->exptr); + fclose(pkg_fp); + } return ret; } -- cgit v1.2.3