diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-15 20:52:50 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-15 20:52:50 -0500 |
commit | 2ca96f5c91395771a37ad6707b2b28c60e6a8873 (patch) | |
tree | 72713439b085e59ee9a3f95dcb11eb90f550cba9 | |
parent | 757b7a618bfdd8cb5690cce1c943e6d6e1a11cb2 (diff) |
fixed several problems with packages. arr_foreach works now!
-rw-r--r-- | a.toc | 3 | ||||
-rw-r--r-- | cgen.c | 69 | ||||
-rw-r--r-- | decls_cgen.c | 65 | ||||
-rw-r--r-- | identifiers.c | 3 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | package.c | 9 | ||||
-rw-r--r-- | sdecls_cgen.c | 2 | ||||
-rw-r--r-- | test.toc | 10 | ||||
-rw-r--r-- | types.h | 6 |
9 files changed, 107 insertions, 61 deletions
@@ -19,10 +19,9 @@ pkg "a"; a.data[a.len] = x; a.len += 1; }; -/* + #export arr_foreach ::= fn(t ::=, a : Arr(t), f : fn(&t)) { each i := 0..a.len-1 { f(&a.data[i]); } }; -*/
\ No newline at end of file @@ -291,6 +291,8 @@ static void cgen_ident(CGenerator *g, Identifier i) { if (idecl && idecl->kind == IDECL_DECL && (idecl->decl->flags & DECL_EXPORT)) { assert(g->pkg_prefix); cgen_write(g, "%s__", g->pkg_prefix); + } else if (i->from_pkg) { + cgen_write(g, "%s__", i->from_pkg->c.prefix); } if (i == g->main_ident) { /* don't conflict with C's main! */ @@ -1291,7 +1293,6 @@ static bool cgen_expr(CGenerator *g, Expression *e) { case BINARY_DOT: { if (type_is_builtin(&e->binary.lhs->type, BUILTIN_PKG)) { assert(e->binary.lhs->kind == EXPR_VAL); - cgen_write(g, "%s__", e->binary.lhs->val.pkg->c.prefix); cgen_ident(g, e->binary.dot.pkg_ident); handled = true; } else { @@ -1909,34 +1910,52 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { return true; } -static bool cgen_defs_expr(CGenerator *g, Expression *e) { - if (e->kind == EXPR_FN) { - FnExpr *f = e->fn; - FnType *fn_type = &e->type.fn; - bool any_const = false; - if (fn_type->constness) { - for (size_t i = 0; i < arr_len(fn_type->types)-1; ++i) { - if (fn_type->constness[i] == CONSTNESS_YES) - any_const = true; - } +static bool cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) { + if (f->c.defined) return true; + f->c.defined = true; + FnType *fn_type = &t->fn; + bool any_const = false; + if (fn_type->constness) { + for (size_t i = 0; i < arr_len(fn_type->types)-1; ++i) { + if (fn_type->constness[i] == CONSTNESS_YES) + any_const = true; } - if (fn_type->constness) { - HashTable *instances = &f->instances; - /* generate each instance */ - Instance **is = instances->data; - for (U64 i = 0; i < instances->cap; ++i) { - if (instances->occupied[i]) { - /* generate this instance */ - if (!cgen_fn(g, &is[i]->fn, e->where, is[i]->c.id, is[i]->val.tuple)) - return false; - } + } + if (fn_type->constness) { + HashTable *instances = &f->instances; + /* generate each instance */ + Instance **is = instances->data; + for (U64 i = 0; i < instances->cap; ++i) { + if (instances->occupied[i]) { + /* generate this instance */ + if (!cgen_fn(g, &is[i]->fn, f->where, is[i]->c.id, is[i]->val.tuple)) + return false; } } - if (!any_const) { - if (!cgen_fn(g, e->fn, e->where, 0, NULL)) - return false; + } + if (!any_const) { + if (!cgen_fn(g, f, f->where, 0, NULL)) + return false; + } + return true; +} + +static bool cgen_defs_expr(CGenerator *g, Expression *e) { + if (e->kind == EXPR_FN) { + if (!cgen_defs_fn(g, e->fn, &e->type)) + return false; + } else if (e->kind == EXPR_BINARY_OP) { + if (e->binary.op == BINARY_DOT && type_is_builtin(&e->binary.lhs->type, BUILTIN_PKG) + && e->type.kind == TYPE_FN) { + Identifier ident = e->binary.dot.pkg_ident; + Declaration *d = ident_decl(ident)->decl; + FnExpr *f = (d->flags & DECL_FOUND_VAL) ? d->val.fn : d->expr.fn; + if (fn_has_any_const_params(f)) { + /* define instances */ + if (!cgen_defs_fn(g, f, &e->type)) + return false; + } } - } cgen_recurse_subexprs(g, e, cgen_defs_expr, cgen_defs_block, cgen_defs_decl); return true; diff --git a/decls_cgen.c b/decls_cgen.c index 7af527d..1545dca 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -42,7 +42,7 @@ static bool cgen_decls_type(CGenerator *g, Type *type) { return true; } -static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) { +static bool cgen_single_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; @@ -55,17 +55,16 @@ static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, return true; } -static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) { - assert(e->kind == EXPR_FN); - FnExpr *f = e->fn; - assert(e->type.fn.constness); + +static bool cgen_decls_fn_instances(CGenerator *g, FnExpr *f, Type *type) { + assert(type->fn.constness); Instance **data = f->instances.data; for (U64 i = 0; i < f->instances.cap; ++i) { if (f->instances.occupied[i]) { if (cgen_should_gen_fn(&(*data)->fn)) { (*data)->fn.c.name = f->c.name; (*data)->fn.c.id = f->c.id; - if (!cgen_fn_decl(g, &(*data)->fn, e->where, (*data)->c.id, (*data)->val.tuple[0].u64)) + if (!cgen_single_fn_decl(g, &(*data)->fn, f->where, (*data)->c.id, (*data)->val.tuple[0].u64)) return false; cgen_write(g, ";"); cgen_nl(g); @@ -76,7 +75,22 @@ static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) { return true; } +static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) { + FnType *fn_type = &t->fn; + if (f->c.declared) return true; + f->c.declared = true; + if (fn_type->constness) { + if (!cgen_decls_fn_instances(g, f, t)) + return false; + } else { + if (!cgen_single_fn_decl(g, f, f->where, 0, 0)) + return false; + } + return true; +} + static bool cgen_decls_expr(CGenerator *g, Expression *e) { + assert(e->flags & EXPR_FOUND_TYPE); cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block, cgen_decls_decl); switch (e->kind) { case EXPR_FN: { @@ -84,14 +98,8 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { f->c.name = NULL; if (!f->c.id) f->c.id = ++g->ident_counter; - FnType *fn_type = &e->type.fn; - if (fn_type->constness) { - if (!cgen_decls_fn_instances(g, e)) - return false; - } else { - if (!cgen_fn_decl(g, e->fn, e->where, 0, 0)) - return false; - } + if (!cgen_fn_decl(g, e->fn, &e->type)) + return false; } break; case EXPR_TYPE: { Type *type = &e->typeval; @@ -107,20 +115,24 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { if (lhs_type->kind == TYPE_PTR) lhs_type = lhs_type->ptr; if (e->binary.op == BINARY_DOT && type_is_builtin(lhs_type, BUILTIN_PKG)) { - assert(e->binary.lhs->kind == EXPR_VAL); Identifier ident = e->binary.dot.pkg_ident; IdentDecl *idecl = ident_decl(ident); assert(idecl); - - if (idecl->kind == IDECL_DECL && e->type.kind == TYPE_FN) { - Declaration *d = idecl->decl; + assert(idecl->kind == IDECL_DECL); + Declaration *d = idecl->decl; + if (e->type.kind == TYPE_FN) { FnExpr *f = NULL; if (d->flags & DECL_FOUND_VAL) f = d->val.fn; else if (d->expr.kind == EXPR_FN) f = d->expr.fn; if (f) { - if (e->binary.lhs->type.flags & TYPE_IS_RESOLVED) { /* no declarations for templates */ + if (fn_has_any_const_params(f)) { + /* declare the instances */ + f->c.name = ident; + if (!cgen_fn_decl(g, f, &e->type)) + return false; + } else { bool out_param = cgen_uses_ptr(&f->ret_type); /* extern function declaration */ cgen_write(g, "extern "); @@ -130,7 +142,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { if (!cgen_type_pre(g, &f->ret_type, e->where)) return false; } - cgen_write(g, " %s__", e->binary.lhs->val.pkg->c.prefix); + cgen_write(g, " "); cgen_ident(g, ident); if (!out_param) { if (!cgen_type_post(g, &f->ret_type, e->where)) @@ -140,15 +152,15 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) { return false; cgen_write(g, ";"); cgen_nl(g); - break; } + break; } } /* extern variable declaration */ cgen_write(g, "extern "); if (!cgen_type_pre(g, &e->type, e->where)) return false; - cgen_write(g, " %s__", e->binary.lhs->val.pkg->c.prefix); + cgen_write(g, " "); cgen_ident(g, ident); if (!cgen_type_post(g, &e->type, e->where)) return false; @@ -181,13 +193,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) { return false; if (cgen_fn_is_direct(g, d)) { d->expr.fn->c.name = d->idents[0]; - if (d->expr.type.fn.constness) { - if (!cgen_decls_fn_instances(g, &d->expr)) - return false; - } else { - if (!cgen_fn_decl(g, d->expr.fn, d->expr.where, 0, 0)) - return false; - } + if (!cgen_fn_decl(g, d->expr.fn, &d->expr.type)) + return false; cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl); } else { if (d->flags & DECL_HAS_EXPR) { diff --git a/identifiers.c b/identifiers.c index c5a4ec1..28989d9 100644 --- a/identifiers.c +++ b/identifiers.c @@ -169,7 +169,8 @@ static void print_ident(Identifier id) { static void fprint_ident_reduced_charset(FILE *out, Identifier id) { assert(id); if (id->anonymous) { - fprintf(out, "x___"); + /* hack to generate unique C identifiers */ + fprintf(out, "a%p__",(void *)id); return; } for (char *s = id->text; is_ident(*s); ++s) { @@ -19,6 +19,7 @@ /* TODO: packages +clean up anywhere we used FnExpr *f, Location where make sure (&Package).something works --- X ::= newtype(int); or something @@ -753,6 +753,7 @@ static bool export_expr(Exporter *ex, Expression *e) { } break; case EXPR_EACH: { EachExpr *ea = e->each; + possibly_static_assert(sizeof ea->flags == 1); export_u8(ex, ea->flags); if ((ea->flags & EACH_ANNOTATED_TYPE) || found_type) if (!export_type(ex, &ea->type, e->where)) @@ -906,7 +907,7 @@ static void import_expr(Importer *im, Expression *e) { if (found_type) { ea->range.stepval = import_optional_val(im, &ea->type); } else { - ea->range.step = import_expr_(im); + ea->range.step = import_optional_expr(im); } } else { ea->of = import_expr_(im); @@ -1034,6 +1035,8 @@ static void import_stmt(Importer *im, Statement *s) { } static bool export_block(Exporter *ex, Block *b) { + possibly_static_assert(sizeof b->flags == 1); + export_u8(ex, b->flags); export_location(ex, b->where); export_len(ex, arr_len(b->stmts)); arr_foreach(b->stmts, Statement, s) { @@ -1046,6 +1049,7 @@ static bool export_block(Exporter *ex, Block *b) { } static void import_block(Importer *im, Block *b) { + b->flags = import_u8(im); b->where = import_location(im); import_arr(im, &b->stmts); arr_foreach(b->stmts, Statement, s) { @@ -1070,7 +1074,6 @@ static bool export_fn(Exporter *ex, FnExpr *f) { arr_foreach(f->ret_decls, Declaration, ret_decl) if (!export_decl(ex, ret_decl)) return false; - /* no need to export the return type */ if (!export_block(ex, &f->body)) return false; return true; @@ -1193,11 +1196,13 @@ static bool import_footer(Importer *im) { fread(name, 1, name_len, im->in); im->ident_map[id] = ident_insert(&im->pkg->idents, &name); im->ident_map[id]->imported = true; + im->ident_map[id]->from_pkg = im->pkg; } for (i = 1; i <= im->max_ident_id; ++i) { if (!im->ident_map[i]) { im->ident_map[i] = ident_new_anonymous(&im->pkg->idents); im->ident_map[i]->imported = true; + im->ident_map[i]->from_pkg = im->pkg; } } diff --git a/sdecls_cgen.c b/sdecls_cgen.c index dcbb121..1aa8e51 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -58,6 +58,8 @@ static bool cgen_sdecls_expr(CGenerator *g, Expression *e) { if (e->kind == EXPR_FN) { /* needs to go before decls_cgen.c... */ e->fn->c.id = ++g->ident_counter; + e->fn->c.declared = false; + e->fn->c.defined = false; } if (e->kind == EXPR_TYPE) { if (!cgen_sdecls_type(g, &e->typeval)) @@ -9,8 +9,16 @@ putf ::= fn(x: float) { arr ::= pkg "a"; - +putptri ::= fn(x: &int) { + puti(*x); +}; main ::= fn() { x : arr.Arr(int); + arr.arr_add(&x, 10); + arr.arr_add(&x, 20); + arr.arr_add(&x, 80); + arr.arr_add(&x, 5430); + arr.arr_add(&x, -6546); + arr.arr_foreach(x, putptri); };
\ No newline at end of file @@ -176,6 +176,7 @@ typedef struct IdentSlot { char *text; /* actual name of the identifier */ size_t len; /* length of name */ U64 export_id; /* 0 if there's no exported identifier here, otherwise unique positive integer associated with this identifier */ + struct Package *from_pkg; struct Package *pkg; /* NULL if this is not associated with a package */ IdentDecl *decls; /* array of declarations of this identifier */ } IdentSlot; @@ -443,7 +444,7 @@ enum { BLOCK_FOUND_TYPES = 0x02, }; typedef struct Block { - U16 flags; + U8 flags; Location where; struct Statement *stmts; struct Expression *ret_expr; /* the return expression of this block, e.g. {foo(); 3} => 3 NULL for no expression. */ @@ -588,6 +589,9 @@ typedef struct FnExpr { /* if name = NULL, this is an anonymous function, and id will be the ID of the fn. */ Identifier name; IdentID id; + /* needed for imported templates atm */ + bool declared; + bool defined; } c; } FnExpr; /* an expression such as fn(x: int) int { 2 * x } */ |