summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--allocator.c27
-rw-r--r--arr.c7
-rw-r--r--copy.c171
-rw-r--r--eval.c56
-rw-r--r--instance_table.c18
-rw-r--r--test.toc13
-rw-r--r--toc.c1
-rw-r--r--types.c150
-rw-r--r--types.h33
9 files changed, 304 insertions, 172 deletions
diff --git a/allocator.c b/allocator.c
index e49ea3e..4394201 100644
--- a/allocator.c
+++ b/allocator.c
@@ -39,41 +39,36 @@ static void *allocr_malloc(Allocator *a, size_t bytes) {
static void *allocr_calloc(Allocator *a, size_t n, size_t sz) {
#if NO_ALLOCATOR
- (void)a;
- return err_calloc(n, sz);
-#else
+ a = NULL;
+#endif
+ if (a == NULL) return err_calloc(n, sz);
/* OPTIM: use calloc */
size_t bytes = n * sz;
void *data = allocr_malloc(a, bytes);
memset(data, 0, bytes);
return data;
-#endif
}
/* OPTIM */
static void *allocr_realloc(Allocator *a, void *data, size_t old_size, size_t new_size) {
#if NO_ALLOCATOR
- (void)a;
- (void)old_size;
- return err_realloc(data, new_size);
-#else
+ a = NULL;
+#endif
+ if (a == NULL) return err_realloc(data, new_size);
void *ret = allocr_malloc(a, new_size);
memcpy(ret, data, old_size);
return ret;
-#endif
}
static void allocr_free(Allocator *a, void *data, size_t size) {
#if NO_ALLOCATOR
- (void)a;
- (void)size;
- free(data);
-#else
+ a = NULL;
+#endif
+ if (a == NULL) {
+ free(data);
+ }
/* OPTIM */
- (void)a;
(void)size;
- (void)data;
-#endif
}
static void allocr_free_all(Allocator *a) {
diff --git a/arr.c b/arr.c
index f214fe4..4991cc4 100644
--- a/arr.c
+++ b/arr.c
@@ -106,6 +106,12 @@ static void arr_remove_last_(void **arr, size_t item_sz) {
arr_hdr(*arr)->len--; (void)item_sz;
}
+static void arr_copya_(void **out, void *in, size_t item_sz, Allocator *a) {
+ size_t len = arr_len(in);
+ arr_resva_(out, len, item_sz, a);
+ memcpy(*out, in, len * item_sz);
+}
+
#ifdef __GNUC__
#define typeof __typeof__
#endif
@@ -139,6 +145,7 @@ You shouldn't rely on this, though, e.g. by doing
#define arr_last(arr) arr_last_((void *)(arr), sizeof *(arr))
#define arr_foreach(arr, type, var) for (type *var = arr_len(arr) ? arr : NULL, *var##_foreach_end = arr_last(arr); var; var == var##_foreach_end ? var = NULL : var++)
#define arr_remove_last(arr) arr_remove_last_((void **)(arr), sizeof **(arr))
+#define arr_copya(out, in, a) do { assert(sizeof *(in) == sizeof **(out)); arr_copya_((void **)(out), (in), sizeof **(out), (a)); } while(0)
#ifdef TOC_DEBUG
static void arr_test(void) {
diff --git a/copy.c b/copy.c
new file mode 100644
index 0000000..f36ebfb
--- /dev/null
+++ b/copy.c
@@ -0,0 +1,171 @@
+/* these copy functions MUST be used before typing!!!! (except for copy_val) */
+
+static void copy_expr(Allocator *a, Expression *out, Expression *in);
+static void copy_block(Allocator *a, Block *out, Block *in);
+
+static void copy_val(Allocator *allocr, Value *out, Value *in, Type *t) {
+ switch (t->kind) {
+ case TYPE_BUILTIN:
+ case TYPE_FN:
+ case TYPE_PTR:
+ case TYPE_SLICE:
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ case TYPE_TYPE:
+ *out = *in;
+ break;
+ case TYPE_ARR: {
+ size_t bytes = t->arr.n * compiler_sizeof(t->arr.of);
+ out->arr = allocr_malloc(allocr, bytes);
+ memcpy(out->arr, in->arr, bytes);
+ } break;
+ case TYPE_TUPLE: {
+ size_t bytes = arr_len(t->tuple) * sizeof(*out->tuple);
+ out->tuple = allocr_malloc(allocr, bytes);
+ memcpy(out->tuple, in->tuple, bytes);
+ } break;
+ case TYPE_STRUCT: {
+ size_t bytes = compiler_sizeof(t);
+ out->struc = allocr_malloc(allocr, bytes);
+ memcpy(out->struc, in->struc, bytes);
+ } break;
+ case TYPE_USER:
+ copy_val(allocr, out, in, type_user_underlying(t));
+ break;
+ }
+}
+
+static void copy_type(Allocator *a, Type *out, Type *in) {
+ assert(!(in->flags & TYPE_IS_RESOLVED));
+ *out = *in;
+ switch (in->kind) {
+ case TYPE_BUILTIN:
+ case TYPE_TYPE:
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ case TYPE_USER:
+ break;
+ case TYPE_FN: {
+ size_t ntypes = arr_len(in->fn.types);
+ out->fn.types = NULL;
+ arr_set_lena(&out->fn.types, ntypes, a);
+ for (size_t i = 0; i < ntypes; i++) {
+ copy_type(a, &out->fn.types[i], &in->fn.types[i]);
+ }
+ } break;
+ case TYPE_TUPLE: {
+ size_t ntypes = arr_len(in->tuple);
+ arr_set_lena(&out->tuple, ntypes, a);
+ for (size_t i = 0; i < ntypes; i++) {
+ copy_type(a, &out->tuple[i], &in->tuple[i]);
+ }
+ } break;
+ case TYPE_ARR:
+ out->arr.n_expr = allocr_malloc(a, sizeof *out->arr.n_expr);
+ copy_expr(a, out->arr.n_expr, in->arr.n_expr);
+ out->arr.of = allocr_malloc(a, sizeof *out->arr.of);
+ copy_type(a, out->arr.of, in->arr.of);
+ break;
+ case TYPE_PTR:
+ out->ptr = allocr_malloc(a, sizeof *out->ptr);
+ copy_type(a, out->ptr, in->ptr);
+ break;
+ case TYPE_SLICE:
+ out->ptr = allocr_malloc(a, sizeof *out->slice);
+ copy_type(a, out->slice, in->slice);
+ break;
+ case TYPE_STRUCT:
+ out->struc.fields = NULL;
+ size_t nfields = arr_len(in->struc.fields);
+ arr_set_lena(&out->struc.fields, nfields, a);
+ for (size_t i = 0; i < nfields; i++) {
+ Field *fout = &out->struc.fields[i];
+ Field *fin = &in->struc.fields[i];
+ *fout = *fin;
+ copy_type(a, fout->type, fin->type);
+ }
+ break;
+ }
+}
+
+static void copy_expr(Allocator *a, Expression *out, Expression *in) {
+ *out = *in;
+ switch (in->kind) {
+ case EXPR_LITERAL_FLOAT:
+ case EXPR_LITERAL_INT:
+ case EXPR_LITERAL_STR:
+ case EXPR_LITERAL_CHAR:
+ case EXPR_LITERAL_BOOL:
+ case EXPR_IDENT:
+ break;
+ case EXPR_UNARY_OP:
+ copy_expr(a, out->unary.of = allocr_malloc(a, sizeof *out->unary.of), in->unary.of);
+ break;
+ case EXPR_BINARY_OP:
+ copy_expr(a, out->binary.lhs = allocr_malloc(a, sizeof *out->binary.lhs), in->binary.lhs);
+ copy_expr(a, out->binary.rhs = allocr_malloc(a, sizeof *out->binary.rhs), in->binary.rhs);
+ break;
+ case EXPR_IF: {
+ IfExpr *iin = &in->if_;
+ IfExpr *iout = &out->if_;
+ if (iin->cond)
+ copy_expr(a, iout->cond = allocr_malloc(a, sizeof *iout->cond), iin->cond);
+ if (iin->next_elif)
+ copy_expr(a, iout->next_elif = allocr_malloc(a, sizeof *iout->next_elif), iin->next_elif);
+ copy_block(a, &iout->body, &iin->body);
+ } break;
+ case EXPR_WHILE: {
+ WhileExpr *win = &in->while_;
+ WhileExpr *wout = &out->while_;
+ if (win->cond)
+ copy_expr(a, wout->cond = allocr_malloc(a, sizeof *wout->cond), win->cond);
+ copy_block(a, &wout->body, &win->body);
+ } break;
+ case EXPR_EACH: {
+ EachExpr *ein = &in->each;
+ EachExpr *eout = &out->each;
+ copy_type(a, &eout->type, &ein->type);
+ if (ein->flags & EACH_IS_RANGE) {
+ copy_expr(a, eout->range.from = allocr_malloc(a, sizeof *eout->range.from), ein->range.from);
+ if (ein->range.to)
+ copy_expr(a, eout->range.to = allocr_malloc(a, sizeof *eout->range.to), ein->range.to);
+ if (ein->range.step)
+ copy_expr(a, eout->range.step = allocr_malloc(a, sizeof *eout->range.step), ein->range.step);
+ } else {
+ copy_expr(a, eout->of = allocr_malloc(a, sizeof *eout->of), ein->of);
+ }
+ copy_block(a, &eout->body, &ein->body);
+ } break;
+ }
+}
+
+static void copy_stmt(Allocator *a, Statement *out, Statement *in) {
+ *out = *in;
+ assert(!(in->decl.flags & DECL_FOUND_TYPE));
+ switch (in->kind) {
+ case STMT_RET:
+ if (in->flags & RET_HAS_EXPR)
+ copy_expr(a, &out->ret.expr, &in->ret.expr);
+ break;
+ case STMT_EXPR:
+ copy_expr(a, &out->expr, &in->expr);
+ break;
+ case STMT_DECL:
+ copy_expr(a, &out->decl.expr, &in->decl.expr);
+ if (in->decl.flags & DECL_FOUND_VAL) {
+ copy_val(a, &out->decl.val, &in->decl.val, &in->decl.type);
+ }
+ if (in->decl.flags & DECL_ANNOTATES_TYPE)
+ copy_type(a, &out->decl.type, &in->decl.type);
+ break;
+ }
+}
+
+static void copy_block(Allocator *a, Block *out, Block *in) {
+ *out = *in;
+ size_t nstmts = arr_len(in->stmts);
+ arr_set_lena(&out->stmts, nstmts, a);
+ for (size_t i = 0; i < nstmts; i++) {
+ copy_stmt(a, &out->stmts[i], &in->stmts[i]);
+ }
+}
diff --git a/eval.c b/eval.c
index 023f858..9619ad7 100644
--- a/eval.c
+++ b/eval.c
@@ -348,50 +348,6 @@ static void fprint_val(FILE *f, Value v, Type *t) {
}
}
-/*
-allocr can be NULL
-*/
-static void val_copy(Allocator *allocr, Value *dest, Value *src, Type *t) {
- switch (t->kind) {
- case TYPE_BUILTIN:
- case TYPE_FN:
- case TYPE_PTR:
- case TYPE_SLICE:
- case TYPE_VOID:
- case TYPE_UNKNOWN:
- case TYPE_TYPE:
- *dest = *src;
- break;
- case TYPE_ARR: {
- size_t bytes = t->arr.n * compiler_sizeof(t->arr.of);
- if (allocr)
- dest->arr = allocr_malloc(allocr, bytes);
- else
- dest->arr = err_malloc(bytes);
- memcpy(dest->arr, src->arr, bytes);
- } break;
- case TYPE_TUPLE: {
- size_t bytes = arr_len(t->tuple) * sizeof(*dest->tuple);
- if (allocr)
- dest->tuple = allocr_malloc(allocr, bytes);
- else
- dest->tuple = err_malloc(bytes);
- memcpy(dest->tuple, src->tuple, bytes);
- } break;
- case TYPE_STRUCT: {
- size_t bytes = compiler_sizeof(t);
- if (allocr)
- dest->struc = allocr_malloc(allocr, bytes);
- else
- dest->struc = err_malloc(bytes);
- memcpy(dest->struc, src->struc, bytes);
- } break;
- case TYPE_USER:
- val_copy(allocr, dest, src, type_user_underlying(t));
- break;
- }
-}
-
static void *val_ptr_to_free(Value *v, Type *t) {
switch (t->kind) {
case TYPE_BUILTIN:
@@ -1468,7 +1424,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
arr_foreach(p->idents, Identifier, i) {
Type *type = p->type.kind == TYPE_TUPLE ? &p->type.tuple[idx++] : &p->type;
IdentDecl *id = ident_decl(*i);
- val_copy(NULL, &id->val, &args[arg], type);
+ copy_val(NULL, &id->val, &args[arg], type);
id->flags |= IDECL_HAS_VAL;
arg++;
}
@@ -1480,7 +1436,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
IdentDecl *id = ident_decl(*i);
if (d->flags & DECL_HAS_EXPR) {
assert(d->expr.kind == EXPR_VAL);
- val_copy(NULL, &id->val, &d->expr.val, type);
+ copy_val(NULL, &id->val, &d->expr.val, type);
id->flags |= IDECL_HAS_VAL;
} else {
id->flags |= IDECL_HAS_VAL;
@@ -1507,7 +1463,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
return false;
Value *element = arr_add(&tuple);
Type *type = decl_type_at_index(d, i);
- val_copy(NULL, element, &this_one, type);
+ copy_val(NULL, element, &this_one, type);
void *to_free = val_ptr_to_free(element, type);
if (to_free)
*(void **)arr_add(&ev->to_free) = to_free;
@@ -1608,7 +1564,7 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
Type *type = decl_type_at_index(d, index);
if (!is_const) {
if (has_expr) {
- val_copy(NULL, &id->val, &val, type);
+ copy_val(NULL, &id->val, &val, type);
} else {
id->val = val_zero(type);
}
@@ -1634,7 +1590,7 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) {
Value r;
if (!eval_expr(ev, &stmt->ret.expr, &r))
return false;
- val_copy(NULL, &ev->ret_val, &r, &stmt->ret.expr.type);
+ copy_val(NULL, &ev->ret_val, &r, &stmt->ret.expr.type);
} break;
}
return true;
@@ -1655,7 +1611,7 @@ static bool eval_block(Evaluator *ev, Block *b, Type *t, Value *v) {
if (!eval_expr(ev, b->ret_expr, &r))
return false;
/* make a copy so that r's data isn't freed when we exit the block */
- val_copy(NULL, v, &r, &b->ret_expr->type);
+ copy_val(NULL, v, &r, &b->ret_expr->type);
void *free_ptr = val_ptr_to_free(v, t);
if (free_ptr)
*(void **)arr_add(&prev_to_free) = free_ptr;
diff --git a/instance_table.c b/instance_table.c
index 5da4a77..948e4e5 100644
--- a/instance_table.c
+++ b/instance_table.c
@@ -225,10 +225,8 @@ static Instance *instance_table_adda(Allocator *a, HashTable *h, Value v, Type *
bool *already_exists) {
if (h->n * 2 >= h->cap) {
U64 new_cap = h->cap * 2 + 3;
- Instance **new_data = a ? allocr_malloc(a, (size_t)new_cap * sizeof *new_data)
- : malloc((size_t)new_cap * sizeof *new_data);
- bool *new_occupied = a ? allocr_calloc(a, (size_t)new_cap, sizeof *new_occupied)
- : calloc((size_t)new_cap, sizeof *new_occupied);
+ Instance **new_data = allocr_malloc(a, (size_t)new_cap * sizeof *new_data);
+ bool *new_occupied = allocr_calloc(a, (size_t)new_cap, sizeof *new_occupied);
Instance **old_data = h->data;
bool *old_occupied = h->occupied;
for (U64 i = 0; i < h->cap; i++) {
@@ -246,13 +244,8 @@ static Instance *instance_table_adda(Allocator *a, HashTable *h, Value v, Type *
}
h->data = new_data;
h->occupied = new_occupied;
- if (a) {
- allocr_free(a, old_occupied, h->cap * sizeof *old_occupied);
- allocr_free(a, old_data, h->cap * sizeof *old_data);
- } else {
- free(old_occupied);
- free(old_data);
- }
+ allocr_free(a, old_occupied, h->cap * sizeof *old_occupied);
+ allocr_free(a, old_data, h->cap * sizeof *old_data);
h->cap = new_cap;
}
Instance **data = h->data;
@@ -271,8 +264,7 @@ static Instance *instance_table_adda(Allocator *a, HashTable *h, Value v, Type *
if (already_exists) {
/* create, because it doesn't exist */
*already_exists = false;
- data[index] = a ? allocr_malloc(a, sizeof *data[index])
- : malloc(sizeof *data[index]);
+ data[index] = allocr_malloc(a, sizeof *data[index]);
data[index]->val = v;
h->occupied[index] = true;
h->n++;
diff --git a/test.toc b/test.toc
index d82f31e..3906c48 100644
--- a/test.toc
+++ b/test.toc
@@ -8,14 +8,11 @@ puti @= fn(x: int) {
// };
+stuff @= fn(t @ Type) int {
+ 4327834 as t as int
+};
-main @= fn() {
- a, b := f(10, 20);
- c, d := f(10, 10+10);
- puti(a); puti(b);
- puti(c); puti(d);
-f @= fn(a: int, x @ int) (int, int) {
- x * a, x + a
-};
+main @= fn() {
+ puti(stuff(int));
};
diff --git a/toc.c b/toc.c
index 7c634c6..8a9bf5b 100644
--- a/toc.c
+++ b/toc.c
@@ -36,6 +36,7 @@ static Type *type_inner(Type *t) {
#include "blockarr.c"
#include "str.c"
#include "instance_table.c"
+#include "copy.c"
#include "identifiers.c"
#include "tokenizer.c"
diff --git a/types.c b/types.c
index 295b53e..8b5750c 100644
--- a/types.c
+++ b/types.c
@@ -181,9 +181,7 @@ static bool expr_must_lval(Expression *e) {
return false;
}
-static bool type_of_fn(Typer *tr, Expression *e, Type *t) {
- assert(e->kind == EXPR_FN);
- FnExpr *f = &e->fn;
+static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t) {
t->kind = TYPE_FN;
t->fn.types = NULL;
t->fn.constness = NULL; /* OPTIM: constant doesn't need to be a dynamic array */
@@ -216,13 +214,13 @@ static bool type_of_fn(Typer *tr, Expression *e, Type *t) {
}
}
}
- if (!type_resolve(tr, &f->ret_type, e->where))
+ if (!type_resolve(tr, &f->ret_type, where))
return false;
*ret_type = f->ret_type;
size_t idx = 0;
arr_foreach(f->params, Declaration, decl) {
if (!types_decl(tr, decl)) return false;
- if (!type_resolve(tr, &decl->type, e->where))
+ if (!type_resolve(tr, &decl->type, where))
return false;
U32 is_at_all_const = decl->flags & (DECL_IS_CONST | DECL_SEMI_CONST);
if (is_at_all_const) {
@@ -318,7 +316,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
} else {
if ((d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_FN)) {
/* allow using a function before declaring it */
- if (!type_of_fn(tr, &d->expr, t)) return false;
+ if (!type_of_fn(tr, &d->expr.fn, d->expr.where, t)) return false;
return true;
} else {
if (location_after(d->where, where)) {
@@ -591,78 +589,88 @@ static bool arg_is_const(Expression *arg, Constness constness) {
}
+static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where) {
+ FnExpr *prev_fn = tr->fn;
+ bool success = true;
+ {
+ HashTable z = {0};
+ f->instances = z;
+ }
+
+ assert(t->kind == TYPE_FN);
+
+ /* don't type function body yet; we need to do that for every instance */
+ if (t->fn.constness)
+ return true;
+
+ tr->fn = f;
+ if (!fn_enter(f, SCOPE_CHECK_REDECL)) {
+ success = false;
+ goto ret;
+ }
+ bool block_success = true;
+ block_success = types_block(tr, &f->body);
+ fn_exit(f);
+ if (!block_success) {
+ success = false;
+ goto ret;
+ }
+ Expression *ret_expr = f->body.ret_expr;
+ Type *ret_type = t->fn.types;
+ bool has_named_ret_vals = f->ret_decls != NULL;
+ if (ret_expr) {
+ if (!types_expr(tr, ret_expr)) {
+ success = false;
+ goto ret;
+ }
+ if (!type_eq(ret_type, &ret_expr->type)) {
+ char *got = type_to_str(&ret_expr->type);
+ char *expected = type_to_str(ret_type);
+ err_print(ret_expr->where, "Returning type %s, but function returns type %s.", got, expected);
+ info_print(where, "Function declaration is here.");
+ free(got); free(expected);
+ success = false;
+ goto ret;
+ }
+ } else if (ret_type->kind != TYPE_VOID && !has_named_ret_vals) {
+ Statement *stmts = f->body.stmts;
+ if (arr_len(stmts)) {
+ Statement *last_stmt = (Statement *)stmts + (arr_len(stmts) - 1);
+ if (last_stmt->kind == STMT_RET) {
+ /*
+ last statement is a return, so it doesn't matter that the function has no return value
+ ideally this would handle if foo { return 5; } else { return 6; }
+ */
+ success = true;
+ goto ret;
+ }
+ }
+ /* TODO: this should really be at the closing brace, and not the function declaration */
+ char *expected = type_to_str(ret_type);
+ err_print(f->body.end, "No return value in function which returns %s.", expected);
+ free(expected);
+ info_print(where, "Function was declared here:");
+ success = false;
+ goto ret;
+ }
+ ret:
+ tr->fn = prev_fn;
+ return success;
+}
+
static bool types_expr(Typer *tr, Expression *e) {
if (e->flags & EXPR_FOUND_TYPE) return true;
Type *t = &e->type;
t->flags = 0;
t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */
e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */
- bool success = true;
switch (e->kind) {
- case EXPR_FN: {
- {
- HashTable z = {0};
- e->fn.instances = z;
- }
- FnExpr *prev_fn = tr->fn;
- FnExpr *f = &e->fn;
- if (!type_of_fn(tr, e, t)) {
- success = false;
- goto fn_ret;
- }
- tr->fn = f;
- if (!fn_enter(f, SCOPE_CHECK_REDECL))
+ case EXPR_FN:
+ if (!type_of_fn(tr, &e->fn, e->where, &e->type))
+ return false;
+ if (!types_fn(tr, &e->fn, &e->type, e->where))
return false;
- bool block_success = true;
- block_success = types_block(tr, &e->fn.body);
- fn_exit(f);
- if (!block_success) {
- success = false;
- goto fn_ret;
- }
- Expression *ret_expr = f->body.ret_expr;
- assert(t->kind == TYPE_FN);
- Type *ret_type = t->fn.types;
- bool has_named_ret_vals = f->ret_decls != NULL;
- if (ret_expr) {
- if (!types_expr(tr, ret_expr)) {
- success = false;
- goto fn_ret;
- }
- if (!type_eq(ret_type, &ret_expr->type)) {
- char *got = type_to_str(&ret_expr->type);
- char *expected = type_to_str(ret_type);
- err_print(ret_expr->where, "Returning type %s, but function returns type %s.", got, expected);
- info_print(e->where, "Function declaration is here.");
- free(got); free(expected);
- success = false;
- goto fn_ret;
- }
- } else if (ret_type->kind != TYPE_VOID && !has_named_ret_vals) {
- Statement *stmts = e->fn.body.stmts;
- if (arr_len(stmts)) {
- Statement *last_stmt = (Statement *)stmts + (arr_len(stmts) - 1);
- if (last_stmt->kind == STMT_RET) {
- /*
- last statement is a return, so it doesn't matter that the function has no return value
- ideally this would handle if foo { return 5; } else { return 6; }
- */
- success = true;
- goto fn_ret;
- }
- }
- /* TODO: this should really be at the closing brace, and not the function declaration */
- char *expected = type_to_str(ret_type);
- err_print(f->body.end, "No return value in function which returns %s.", expected);
- free(expected);
- info_print(e->where, "Function was declared here:");
- success = false;
- goto fn_ret;
- }
- fn_ret:
- tr->fn = prev_fn;
- if (!success) return false;
- } break;
+ break;
case EXPR_LITERAL_INT:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_I64;
@@ -1597,7 +1605,7 @@ static bool types_decl(Typer *tr, Declaration *d) {
success = false;
goto ret;
}
- val_copy(tr->allocr, &d->val, &val, &d->type);
+ copy_val(tr->allocr, &d->val, &val, &d->type);
d->flags |= DECL_FOUND_VAL;
}
}
diff --git a/types.h b/types.h
index 3f398b8..91cda39 100644
--- a/types.h
+++ b/types.h
@@ -1,3 +1,5 @@
+/* NOTE: make sure you edit copy.c when you make a change to expression-related types or type-related types in this file! */
+
typedef int64_t Integer;
typedef uint64_t UInteger;
typedef long double Floating; /* OPTIM: Switch to double, but make sure floating-point literals are right */
@@ -336,8 +338,8 @@ typedef struct Type {
struct {
struct Type *of;
union {
- U64 n; /* after typing */
- struct Expression *n_expr; /* before typing */
+ U64 n; /* after resolving */
+ struct Expression *n_expr; /* before resolving */
};
} arr;
struct Type *ptr;
@@ -431,19 +433,12 @@ typedef enum {
} BinaryOp;
typedef struct {
- Value val;
- struct {
- U64 id;
- } c;
-} Instance;
-
-typedef struct {
struct Expression *fn;
union {
struct Argument *args;
struct Expression *arg_exprs;
};
- Instance *instance; /* NULL = ordinary function, no compile time args */
+ struct Instance *instance; /* NULL = ordinary function, no compile time args */
struct {
IdentID id;
} c;
@@ -481,11 +476,12 @@ typedef struct EachExpr {
Block body;
union {
struct {
- struct Expression *from;
- struct Expression *to;
+ struct Expression *from; /* can't be null */
+ struct Expression *to; /* can be null */
union {
- struct Expression *step;
- Value *stepval;
+ /* (either) can be null */
+ struct Expression *step; /* before typing */
+ Value *stepval; /* after typing */
};
} range;
struct Expression *of;
@@ -515,6 +511,15 @@ typedef struct FnExpr {
} c;
} FnExpr; /* an expression such as fn(x: int) int { 2 * x } */
+typedef struct Instance {
+ Value val;
+ /* this holds the typed function */
+ FnExpr fn;
+ struct {
+ U64 id;
+ } c;
+} Instance;
+
typedef struct {
Type type;
struct Expression *expr;