From 81840d518d8b170128e5867274c91dda0db3e4f6 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Mon, 6 Jan 2020 14:08:13 -0500 Subject: improved naming of exported functions in C --- .gitignore | 1 + cgen.c | 16 +++++++++++++--- decls_cgen.c | 45 +++++++++++++++++++++++++++------------------ package.c | 2 ++ point.toc | 4 ++++ types.c | 18 ++++++++++++------ types.h | 2 ++ 7 files changed, 61 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index bf94226..a7b3e40 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ tests/**/*.bin vgcore* TAGS tags +*.o diff --git a/cgen.c b/cgen.c index cdeeec5..e2996de 100644 --- a/cgen.c +++ b/cgen.c @@ -12,6 +12,7 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e g->indent_lvl = 0; g->idents = ids; g->allocr = allocr; + g->exptr = ev->typer->exptr; } static bool cgen_stmt(CGenerator *g, Statement *s); @@ -467,10 +468,18 @@ static bool cgen_should_gen_fn(FnExpr *f) { } } +static void cgen_full_fn_name(CGenerator *g, FnExpr *f, U64 instance) { + cgen_fn_name(g, f); + if (instance) { + cgen_fn_instance_number(g, instance); + } +} + /* unless f has const/semi-const args, instance and which_are_const can be set to 0 */ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) { bool out_param = cgen_uses_ptr(&f->ret_type); bool any_params = false; + char *pkg_name = g->evalr->typer->pkg_name; assert(cgen_should_gen_fn(f)); if (!f->export.id) /* local to this translation unit */ cgen_write(g, "static "); @@ -480,10 +489,11 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where, U64 instanc if (!cgen_type_pre(g, &f->ret_type, where)) return false; cgen_write(g, " "); } - cgen_fn_name(g, f); - if (instance) { - cgen_fn_instance_number(g, instance); + if (f->export.id) { + assert(pkg_name); + cgen_write(g, "%s__", pkg_name); } + cgen_full_fn_name(g, f, instance); if (!out_param) { if (!cgen_type_post(g, &f->ret_type, where)) return false; } diff --git a/decls_cgen.c b/decls_cgen.c index 61840a6..94e65df 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -7,6 +7,28 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s); static bool cgen_decls_block(CGenerator *g, Block *b); static bool cgen_decls_decl(CGenerator *g, Declaration *d); +static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) { + if (cgen_should_gen_fn(f)) { + if (!fn_enter(f, 0)) + return false; + if (!cgen_fn_header(g, f, where, instance, which_are_const)) + return false; + cgen_write(g, ";"); + cgen_nl(g); + fn_exit(f); + char *pkg_name = g->evalr->typer->pkg_name; + if (pkg_name && f->export.id) { + /* allow use of function without referring to package in this file */ + cgen_write(g, "#define "); + cgen_full_fn_name(g, f, instance); + cgen_write(g, " %s__", pkg_name); + cgen_full_fn_name(g, f, instance); + cgen_nl(g); + } + } + return true; +} + static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) { assert(e->kind == EXPR_FN); FnExpr *f = e->fn; @@ -17,8 +39,7 @@ static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) { if (cgen_should_gen_fn(&(*data)->fn)) { (*data)->fn.c.name = f->c.name; (*data)->fn.c.id = f->c.id; - - if (!cgen_fn_header(g, &(*data)->fn, e->where, (*data)->c.id, (*data)->val.tuple[0].u64)) + if (!cgen_fn_decl(g, &(*data)->fn, e->where, (*data)->c.id, (*data)->val.tuple[0].u64)) return false; cgen_write(g, ";"); cgen_nl(g); @@ -42,14 +63,8 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { if (!cgen_decls_fn_instances(g, e)) return false; } else { - if (cgen_should_gen_fn(e->fn)) { - fn_enter(e->fn, 0); - if (!cgen_fn_header(g, e->fn, e->where, 0, 0)) - return false; - cgen_write(g, ";"); - cgen_nl(g); - fn_exit(e->fn); - } + if (!cgen_fn_decl(g, e->fn, e->where, 0, 0)) + return false; } } break; case EXPR_TYPE: { @@ -108,14 +123,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) { if (!cgen_decls_fn_instances(g, &d->expr)) return false; } else { - if (cgen_should_gen_fn(d->expr.fn)) { - fn_enter(d->expr.fn, 0); - if (!cgen_fn_header(g, d->expr.fn, d->where, 0, 0)) - return false; - cgen_write(g, ";"); - cgen_nl(g); - fn_exit(d->expr.fn); - } + if (!cgen_fn_decl(g, d->expr.fn, d->expr.where, 0, 0)) + return false; } cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl); } else { diff --git a/package.c b/package.c index bef9a76..f1844b5 100644 --- a/package.c +++ b/package.c @@ -110,6 +110,7 @@ static void exptr_start(Exporter *ex, const char *pkg_name, size_t pkg_name_len) export_u64(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; export_bool(ex, has_code); if (has_code) { @@ -558,6 +559,7 @@ 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); export_u64(ex, (U64)ident_offset); fseek(ex->out, 0L, SEEK_END); diff --git a/point.toc b/point.toc index ede3c7c..27f58f0 100644 --- a/point.toc +++ b/point.toc @@ -8,3 +8,7 @@ pkg "point"; p.x = x; p.y = y; }; + +mk_point2 ::= fn(x, y:int) p: Point { + p = mk_point(x*x, y*y); +}; \ No newline at end of file diff --git a/types.c b/types.c index 50da073..a0c3c1a 100644 --- a/types.c +++ b/types.c @@ -2116,6 +2116,7 @@ static void typer_create(Typer *tr, Evaluator *ev, Allocator *allocr) { tr->exptr = NULL; /* by default, don't set an exporter */ tr->in_decls = NULL; tr->in_expr_decls = NULL; + tr->pkg_name = NULL; tr->allocr = allocr; *(Block **)arr_adda(&tr->blocks, allocr) = NULL; } @@ -2137,13 +2138,18 @@ static bool types_file(Typer *tr, ParsedFile *f, char *code) { return false; Slice pkg_name_slice = pkg_name.slice; char *pkg_name_str = pkg_name_slice.data; - I64 pkg_name_len = pkg_name_slice.n; - if (pkg_name_len < 0) { - err_print(f->pkg_name->where, "Package name has a negative length (" I64_FMT ")!", pkg_name_len); + if (pkg_name_slice.n < 0) { + err_print(f->pkg_name->where, "Package name has a negative length (" I64_FMT ")!", pkg_name_slice.n); return false; } - char *pkg_file_name = err_malloc((size_t)pkg_name_len+5); - sprintf(pkg_file_name, "%s.top", pkg_name_str); + size_t pkg_name_len = (size_t)pkg_name_slice.n; + + char *pkg_name_cstr = typer_malloc(tr, pkg_name_len+1); + memcpy(pkg_name_cstr, pkg_name_str, pkg_name_len); + pkg_name_cstr[pkg_name_len] = 0; + tr->pkg_name = pkg_name_cstr; + char *pkg_file_name = err_malloc(pkg_name_len+5); + sprintf(pkg_file_name, "%s.top", pkg_name_cstr); 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); @@ -2152,7 +2158,7 @@ static bool types_file(Typer *tr, ParsedFile *f, char *code) { } free(pkg_file_name); exptr_create(tr->exptr, pkg_fp, code); - exptr_start(tr->exptr, pkg_name_str, (size_t)pkg_name_len); + exptr_start(tr->exptr, pkg_name_str, pkg_name_len); } arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { diff --git a/types.h b/types.h index a612368..8979475 100644 --- a/types.h +++ b/types.h @@ -755,6 +755,7 @@ typedef struct Typer { Block *block; Block **blocks; /* dyn array of all the block's we're in ([0] = NULL for global scope) */ FnExpr *fn; /* the function we're currently parsing. */ + char *pkg_name; } Typer; @@ -779,6 +780,7 @@ typedef struct CGenerator { Block *block; FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */ Evaluator *evalr; + Exporter *exptr; Identifier main_ident; Identifiers *idents; } CGenerator; -- cgit v1.2.3