summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-07 15:08:18 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-07 15:08:18 -0500
commiteee36346d65080feee7d70b8ecc7a39f83f5f3eb (patch)
tree3c5616d3cddf9e56b0221f7c4b44ca2fe7289f0c
parent1894485db067d5d79a32a90da07bd5f0aad433d7 (diff)
still trying to fix new idents
-rw-r--r--cgen.c4
-rw-r--r--copy.c67
-rw-r--r--decls_cgen.c8
-rw-r--r--err.c10
-rw-r--r--eval.c2
-rw-r--r--identifiers.c4
-rw-r--r--main.c3
-rw-r--r--test.toc17
-rw-r--r--toc.c2
-rw-r--r--types.c16
-rw-r--r--types.h2
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;