From eee36346d65080feee7d70b8ecc7a39f83f5f3eb Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Fri, 7 Feb 2020 15:08:18 -0500 Subject: still trying to fix new idents --- cgen.c | 4 ++-- copy.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++---------- decls_cgen.c | 8 +++---- err.c | 10 ++++----- eval.c | 2 +- identifiers.c | 4 +++- main.c | 3 ++- test.toc | 17 +++++++++++---- toc.c | 2 +- types.c | 16 +++++++------- types.h | 2 +- 11 files changed, 96 insertions(+), 39 deletions(-) diff --git a/cgen.c b/cgen.c index 50389f6..e187f11 100644 --- a/cgen.c +++ b/cgen.c @@ -143,7 +143,7 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d); Instance **data = fn->instances.data; \ for (U64 i = 0; i < fn->instances.cap; ++i) { \ if (fn->instances.occupied[i]) { \ - cgen_recurse_subexprs_fn_simple((&(*data)->fn), decl_f, block_f); \ + cgen_recurse_subexprs_fn_simple(((*data)->fn), decl_f, block_f); \ } \ ++data; \ } \ @@ -2063,7 +2063,7 @@ static bool cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) { for (U64 i = 0; i < instances->cap; ++i) { if (instances->occupied[i]) { /* generate this instance */ - if (!cgen_fn(g, &is[i]->fn, is[i]->c.id, is[i]->val.tuple)) + if (!cgen_fn(g, is[i]->fn, is[i]->c.id, is[i]->val.tuple)) return false; } } diff --git a/copy.c b/copy.c index cbfcdcf..c7d8406 100644 --- a/copy.c +++ b/copy.c @@ -20,7 +20,10 @@ typedef struct { static Expression *copy_expr_(Copier *c, Expression *in); static void copy_expr(Copier *c, Expression *out, Expression *in); static void copy_decl(Copier *c, Declaration *out, Declaration *in); -static void copy_block(Copier *c, Block *out, Block *in); +enum { + COPY_BLOCK_DONT_CREATE_IDENTS = 0x01 +}; +static void copy_block(Copier *c, Block *out, Block *in, U8 flags); static void copy_type(Copier *c, Type *out, Type *in); static Type *copy_type_(Copier *c, Type *in); @@ -139,6 +142,12 @@ static Type *copy_type_(Copier *c, Type *in) { static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) { *fout = *fin; + Block *prev; + if (copy_body) { + prev = c->block; + c->block = &fout->body; + idents_create(&fout->body.idents, c->allocr, &fout->body); + } size_t i; size_t nparam_decls = arr_len(fin->params); fout->params = NULL; @@ -153,8 +162,16 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) { copy_decl(c, fout->ret_decls + i, fin->ret_decls + i); } copy_type(c, &fout->ret_type, &fin->ret_type); - if (copy_body) - copy_block(c, &fout->body, &fin->body); + if (copy_body) { + copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); + c->block = prev; + } +} + +static inline void copier_ident_translate(Copier *c, Identifier *i) { + assert(c->block); + assert(c->block->idents.scope == c->block); + *i = ident_translate_forced(*i, &c->block->idents); } static void copy_expr(Copier *c, Expression *out, Expression *in) { @@ -167,7 +184,9 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { case EXPR_LITERAL_STR: case EXPR_LITERAL_CHAR: case EXPR_LITERAL_BOOL: + break; case EXPR_IDENT: + copier_ident_translate(c, &out->ident); break; case EXPR_UNARY_OP: out->unary.of = copy_expr_(c, in->unary.of); @@ -183,20 +202,35 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { iout->cond = copy_expr_(c, iin->cond); if (iin->next_elif) iout->next_elif = copy_expr_(c, iin->next_elif); - copy_block(c, &iout->body, &iin->body); + copy_block(c, &iout->body, &iin->body, 0); } break; case EXPR_WHILE: { WhileExpr *win = &in->while_; WhileExpr *wout = &out->while_; if (win->cond) wout->cond = copy_expr_(c, win->cond); - copy_block(c, &wout->body, &win->body); + copy_block(c, &wout->body, &win->body, 0); } break; case EXPR_FOR: { ForExpr *fin = in->for_; ForExpr *fout = allocr_malloc(a, sizeof *fout); out->for_ = fout; *fout = *fin; + + Block *prev = c->block; + idents_create(&fout->body.idents, c->allocr, &fout->body); + c->block = &fout->body; + + if (fout->index) { + copier_ident_translate(c, &fout->index); + fout->index->decl_kind = IDECL_EXPR; + fout->index->expr = out; + } + if (fout->value) { + copier_ident_translate(c, &fout->value); + fout->value->decl_kind = IDECL_EXPR; + fout->value->expr = out; + } if (fin->flags & FOR_ANNOTATED_TYPE) copy_type(c, &fout->type, &fin->type); if (fin->flags & FOR_IS_RANGE) { @@ -208,7 +242,8 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { } else { fout->of = copy_expr_(c, fin->of); } - copy_block(c, &fout->body, &fin->body); + copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS); + c->block = prev; } break; case EXPR_FN: copy_fn_expr(c, out->fn = allocr_malloc(a, sizeof *out->fn), in->fn, true); @@ -241,7 +276,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { } } break; case EXPR_BLOCK: - copy_block(c, &out->block, &in->block); + copy_block(c, &out->block, &in->block, 0); break; case EXPR_TUPLE: { size_t nexprs = arr_len(in->tuple); @@ -272,7 +307,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { copy_val(a, &out->val, &in->val, &in->type); break; case EXPR_NMS: - copy_block(c, &out->nms.body, &in->nms.body); + copy_block(c, &out->nms.body, &in->nms.body, 0); break; } } @@ -286,7 +321,7 @@ static Expression *copy_expr_(Copier *c, Expression *in) { static void copy_decl(Copier *c, Declaration *out, Declaration *in) { *out = *in; assert(!(in->flags & DECL_FOUND_TYPE)); - + if (in->flags & DECL_HAS_EXPR) copy_expr(c, &out->expr, &in->expr); if (in->flags & DECL_FOUND_VAL) { @@ -294,6 +329,12 @@ static void copy_decl(Copier *c, Declaration *out, Declaration *in) { } if (in->flags & DECL_ANNOTATES_TYPE) copy_type(c, &out->type, &in->type); + arr_foreach(out->idents, Identifier, ident) { + assert(c->block); + copier_ident_translate(c, ident); + (*ident)->decl_kind = IDECL_DECL; + (*ident)->decl = out; + } } @@ -324,15 +365,19 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) { } } -static void copy_block(Copier *c, Block *out, Block *in) { +static void copy_block(Copier *c, Block *out, Block *in, U8 flags) { + Identifiers out_idents = out->idents; *out = *in; + if (flags & COPY_BLOCK_DONT_CREATE_IDENTS) + out->idents = out_idents; /* reset Identifiers */ size_t nstmts = arr_len(in->stmts); out->stmts = NULL; Block *prev = c->block; c->block = out; if (in->ret_expr) out->ret_expr = copy_expr_(c, in->ret_expr); - + if (!(flags & COPY_BLOCK_DONT_CREATE_IDENTS)) + idents_create(&out->idents, c->allocr, out); arr_set_lena(&out->stmts, nstmts, c->allocr); for (size_t i = 0; i < nstmts; ++i) { copy_stmt(c, &out->stmts[i], &in->stmts[i]); diff --git a/decls_cgen.c b/decls_cgen.c index 8e61104..6bb8754 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -57,10 +57,10 @@ static bool cgen_decls_fn_instances(CGenerator *g, FnExpr *f) { 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_single_fn_decl(g, &(*data)->fn, (*data)->c.id, (*data)->val.tuple[0].u64)) + if (cgen_should_gen_fn((*data)->fn)) { + (*data)->fn->c.name = f->c.name; + (*data)->fn->c.id = f->c.id; + if (!cgen_single_fn_decl(g, (*data)->fn, (*data)->c.id, (*data)->val.tuple[0].u64)) return false; cgen_write(g, ";"); cgen_nl(g); diff --git a/err.c b/err.c index a6ad230..e0aab89 100644 --- a/err.c +++ b/err.c @@ -112,11 +112,11 @@ static void warn_print_header_(Location where) { } -static void err_print_footer_(Location where) { +static void err_print_footer_(Location where, bool show_ctx_stack) { ErrCtx *ctx = where.file->ctx; err_fprint(ctx, "\n"); print_location_highlight(err_ctx_file(ctx), where); - if (ctx) { + if (ctx && show_ctx_stack) { arr_foreach(ctx->instance_stack, Location, inst) { err_fprint(ctx, "While generating the instance of a function\n"); print_location_highlight(err_ctx_file(ctx), *inst); @@ -132,7 +132,7 @@ static void err_vprint(Location where, const char *fmt, va_list args) { ctx->have_errored = true; err_print_header_(where); err_vfprint(ctx, fmt, args); - err_print_footer_(where); + err_print_footer_(where, true); } @@ -166,7 +166,7 @@ static void info_print(Location where, const char *fmt, ...) { va_start(args, fmt); info_print_header_(where); err_vfprint(ctx, fmt, args); - err_print_footer_(where); + err_print_footer_(where, false); va_end(args); } @@ -185,7 +185,7 @@ static void warn_print_( va_start(args, fmt); warn_print_header_(where); err_vfprint(ctx, fmt, args); - err_print_footer_(where); + err_print_footer_(where, true); va_end(args); } diff --git a/eval.c b/eval.c index 0ce6fb7..458a0cd 100644 --- a/eval.c +++ b/eval.c @@ -1458,7 +1458,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { case EXPR_CALL: { FnExpr *fn; if (e->call.instance) { - fn = &e->call.instance->fn; + fn = e->call.instance->fn; } else { Value fnv; if (!eval_expr(ev, e->call.fn, &fnv)) { diff --git a/identifiers.c b/identifiers.c index 60ab30e..7d975fe 100644 --- a/identifiers.c +++ b/identifiers.c @@ -152,7 +152,9 @@ static Identifier ident_get(Identifiers *ids, char *s) { /* translate and insert if not already there */ static inline Identifier ident_translate_forced(Identifier i, Identifiers *to_idents) { char *p = i->str; - return ident_insert(to_idents, &p); + Identifier translated = ident_insert(to_idents, &p); + assert(translated->idents == to_idents); + return translated; } /* translate but don't add it if it's not there */ diff --git a/main.c b/main.c index 67fa99b..c648cd3 100644 --- a/main.c +++ b/main.c @@ -19,14 +19,15 @@ /* TODO: the problem right now is that we're copying blocks but not updating our references to the copy - make eval_ptr_to_struct_field return a bool (just in case it successfully returns a NULL pointer) nms["foo"] make sure #export still works properly fix cgen_ident_to_str for unicode idents check for leaks --- +error about statements of expression with compile-only types (e.g. int;) allow for circular dependencies in functions returning types---this will be complicated +foo, _ := bar(); nice syntax for #including something into a namespace run stuff at compile time without assigning it to a constant #compile_only declarations diff --git a/test.toc b/test.toc index bffe02a..4811e46 100644 --- a/test.toc +++ b/test.toc @@ -1,10 +1,19 @@ + // it would be nice if Arr.data.len == Arr.len (: but this will require some C code... Arr ::= fn (t :: Type) Type { - struct { - data : t; - } + // struct { + // data : []t; + // len, cap : int; + // } + t +}; + +arr_add ::= fn(t :: Type, a : &Arr(t), x : t) { }; main ::= fn() { arr : Arr(int); -}; + for i := 1..100 { + arr_add(int, &arr, 3); + } +}; \ No newline at end of file diff --git a/toc.c b/toc.c index ce99c1d..9a5be2f 100644 --- a/toc.c +++ b/toc.c @@ -81,7 +81,6 @@ static inline bool type_is_slicechar(Type *t) { static size_t compiler_alignof(Type *t); static size_t compiler_sizeof(Type *t); #include "instance_table.c" -#include "copy.c" /* returns NULL on error */ static char *read_file_contents(Allocator *a, const char *filename, Location where) { @@ -112,6 +111,7 @@ static char *read_file_contents(Allocator *a, const char *filename, Location whe #include "identifiers.c" +#include "copy.c" #include "tokenizer.c" #include "parse.c" #include "foreign.c" diff --git a/types.c b/types.c index 49023fe..4d2391a 100644 --- a/types.c +++ b/types.c @@ -375,6 +375,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t) long idx; for (idx = nblocks - 1; idx >= 0; --idx) { Block *b = tr->blocks[idx]; + /* OPTIM: only hash once */ Identifier translated = ident_translate(i, b ? &b->idents : tr->globals); if (!translated) continue; if (translated->decl_kind != IDECL_NONE) { @@ -775,7 +776,7 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) { bool has_named_ret_vals; assert(t->kind == TYPE_FN); if (instance) { - f = &instance->fn; + f = instance->fn; } else { if (t->fn.constness) return true; /* don't type function body yet; we need to do that for every instance */ @@ -1488,7 +1489,7 @@ static bool types_expr(Typer *tr, Expression *e) { FnExpr *original_fn = NULL; Type table_index_type = {0}; Value table_index = {0}; - FnExpr fn_copy; + FnExpr *fn_copy = NULL; Copier cop = copier_create(tr->allocr, tr->block); if (fn_type->constness) { /* evaluate compile-time arguments + add an instance */ @@ -1502,9 +1503,9 @@ static bool types_expr(Typer *tr, Expression *e) { FnExpr *fn = fn_val.fn; /* fn is the instance, original_fn is not */ original_fn = fn; - - copy_fn_expr(&cop, &fn_copy, fn, false); - fn = &fn_copy; + fn_copy = typer_malloc(tr, sizeof *fn_copy); + copy_fn_expr(&cop, fn_copy, fn, true); + fn = fn_copy; /* keep track of the declaration */ Declaration *param_decl = fn->params; size_t ident_idx = 0; @@ -1649,7 +1650,7 @@ static bool types_expr(Typer *tr, Expression *e) { } } /* type params, return declarations, etc */ - if (!type_of_fn(tr, &fn_copy, &f->type, TYPE_OF_FN_IS_INSTANCE)) + if (!type_of_fn(tr, fn_copy, &f->type, TYPE_OF_FN_IS_INSTANCE)) return false; /* deal with default arguments */ @@ -1709,7 +1710,6 @@ static bool types_expr(Typer *tr, Expression *e) { arr_cleara(&table_index_type.tuple, tr->allocr); arr_cleara(&table_index.tuple, tr->allocr); } else { - copy_block(&cop, &fn_copy.body, &original_fn->body); c->instance->fn = fn_copy; /* fix parameter and return types (they were kind of problematic before, because we didn't know about the instance) */ c->instance->c.id = original_fn->instances.n; /* let's help cgen out and assign an ID to this */ @@ -1718,7 +1718,7 @@ static bool types_expr(Typer *tr, Expression *e) { /* if anything happens, make sure we let the user know that this happened while generating a fn */ ErrCtx *err_ctx = e->where.file->ctx; *(Location *)typer_arr_add(tr, &err_ctx->instance_stack) = e->where; - bool success = types_fn(tr, &c->instance->fn, &f->type, c->instance); + bool success = types_fn(tr, c->instance->fn, &f->type, c->instance); arr_remove_lasta(&err_ctx->instance_stack, tr->allocr); if (!success) return false; arr_cleara(&table_index_type.tuple, tr->allocr); diff --git a/types.h b/types.h index f7b524a..94a59c5 100644 --- a/types.h +++ b/types.h @@ -642,7 +642,7 @@ typedef struct FnExpr { typedef struct Instance { Value val; /* key into hash table */ - FnExpr fn; /* the typed function */ + FnExpr *fn; /* the typed function */ struct { U64 id; } c; -- cgit v1.2.3