summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c99
-rw-r--r--decls_cgen.c24
-rw-r--r--eval.c30
-rw-r--r--main.c25
-rw-r--r--parse.c28
-rw-r--r--sdecls_cgen.c46
-rw-r--r--test.toc12
-rw-r--r--toc.c36
-rw-r--r--tokenizer.c2
-rw-r--r--types.c113
-rw-r--r--types.h6
11 files changed, 223 insertions, 198 deletions
diff --git a/cgen.c b/cgen.c
index ed9a836..69a4dba 100644
--- a/cgen.c
+++ b/cgen.c
@@ -3,11 +3,10 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev, Allocator *allocr) {
+static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Allocator *allocr) {
g->outc = out;
g->ident_counter = 0;
g->main_ident = ident_get(ids, "main");
- g->evalr = ev;
g->will_indent = true;
g->indent_lvl = 0;
g->globals = ids;
@@ -16,25 +15,25 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e
*(char *)arr_adda(&g->nms_prefix, g->allocr) = '\0';
}
-static bool cgen_stmt(CGenerator *g, Statement *s);
+static Status cgen_stmt(CGenerator *g, Statement *s);
enum {
CGEN_BLOCK_NOBRACES = 0x01 /* should it use braces? */
};
-static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, uint16_t flags);
-static bool cgen_expr_pre(CGenerator *g, Expression *e);
-static bool cgen_expr(CGenerator *g, Expression *e);
-static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
+static Status cgen_block(CGenerator *g, Block *b, const char *ret_name, uint16_t flags);
+static Status cgen_expr_pre(CGenerator *g, Expression *e);
+static Status cgen_expr(CGenerator *g, Expression *e);
+static Status cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
const char *to_str);
-static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to);
-static bool cgen_type_pre(CGenerator *g, Type *t, Location where);
-static bool cgen_type_post(CGenerator *g, Type *t, Location where);
-static bool cgen_decl(CGenerator *g, Declaration *d);
-static bool cgen_ret(CGenerator *g, Expression *ret);
-static bool cgen_val(CGenerator *g, Value v, Type *t, Location where);
-static bool cgen_val_pre(CGenerator *g, Value v, Type *t, Location where);
-static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
-static bool cgen_defs_block(CGenerator *g, Block *b);
-static bool cgen_defs_decl(CGenerator *g, Declaration *d);
+static Status cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to);
+static Status cgen_type_pre(CGenerator *g, Type *t, Location where);
+static Status cgen_type_post(CGenerator *g, Type *t, Location where);
+static Status cgen_decl(CGenerator *g, Declaration *d);
+static Status cgen_ret(CGenerator *g, Expression *ret);
+static Status cgen_val(CGenerator *g, Value v, Type *t, Location where);
+static Status cgen_val_pre(CGenerator *g, Value v, Type *t, Location where);
+static Status cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
+static Status cgen_defs_block(CGenerator *g, Block *b);
+static Status cgen_defs_decl(CGenerator *g, Declaration *d);
#define cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f) \
FnExpr *prev_fn = g->f##n; \
@@ -351,7 +350,7 @@ static void cgen_struct_name(CGenerator *g, StructDef *sdef) {
}
}
-static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
+static Status cgen_type_pre(CGenerator *g, Type *t, Location where) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
@@ -411,7 +410,7 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
return true;
}
-static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
+static Status cgen_type_post(CGenerator *g, Type *t, Location where) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_PTR:
@@ -513,7 +512,7 @@ static void cgen_full_fn_name(CGenerator *g, FnExpr *f, U64 instance) {
}
}
-static bool cgen_fn_args(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
+static Status cgen_fn_args(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
(void)instance; /* not needed atm */
bool out_param = cgen_uses_ptr(&f->ret_type);
bool any_params = false;
@@ -598,7 +597,7 @@ static inline bool cgen_arg(CGenerator *g, Expression *arg) {
}
/* 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, U64 instance, U64 which_are_const) {
+static Status cgen_fn_header(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
bool out_param = cgen_uses_ptr(&f->ret_type);
assert(cgen_should_gen_fn(f));
if (!(f->flags & FN_EXPR_EXPORT))
@@ -624,7 +623,7 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, U64 instance, U64 which_are
Also, set_str and/or to_str should be NULL
this DOES NOT call cgen_expr_pre for set_expr or to_expr
*/
-static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
+static Status cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
const char *to_str) {
Type *type;
Location where;
@@ -701,7 +700,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
}
/* one of exprs, idents, and prefix should be NULL. does NOT call cgen_expr_pre for to/exprs */
-static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
+static Status cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
switch (to->kind) {
case EXPR_VAL:
assert(0); /* never needed at the moment */
@@ -853,7 +852,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
return true;
}
-static bool cgen_expr_pre(CGenerator *g, Expression *e) {
+static Status cgen_expr_pre(CGenerator *g, Expression *e) {
IdentID id = 0;
char ret_name[CGEN_IDENT_ID_STR_SIZE+20];
switch (e->kind) {
@@ -1319,7 +1318,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
return true;
}
-static bool cgen_expr(CGenerator *g, Expression *e) {
+static Status cgen_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_LITERAL_FLOAT:
cgen_write(g, "%.16Lf", (long double)e->floatl); /* TODO(eventually): better precision? */
@@ -1453,7 +1452,8 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
if (struct_type->kind == TYPE_PTR) struct_type = struct_type->ptr;
if (struct_type->kind == TYPE_STRUCT) {
cgen_write(g, "(");
- cgen_expr(g, e->binary.lhs);
+ if (!cgen_expr(g, e->binary.lhs))
+ return false;
bool is_ptr = e->binary.lhs->type.kind == TYPE_PTR;
cgen_write(g, is_ptr ? "->" :".");
cgen_ident_simple(g, e->binary.dot.field->name);
@@ -1640,8 +1640,10 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
return false;
} else {
cgen_write(g, "((");
- cgen_type_pre(g, to, e->where);
- cgen_type_post(g, to, e->where);
+ if (!cgen_type_pre(g, to, e->where))
+ return false;
+ if (!cgen_type_post(g, to, e->where))
+ return false;
cgen_write(g, ")(");
if (!cgen_expr(g, e->cast.expr))
return false;
@@ -1680,7 +1682,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
functions always call with NULL as ret_name, even if they use out params, for now
at least.
*/
-static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) {
+static Status cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) {
if (!(flags & CGEN_BLOCK_NOBRACES)) {
cgen_write(g, "{");
cgen_nl(g);
@@ -1732,7 +1734,7 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
}
/* pass 0 for instance and NULL for compile_time_args if there are no compile time arguments. */
-static bool cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_args) {
+static Status cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_args) {
/* see also cgen_defs_expr */
FnExpr *prev_fn = g->fn;
U64 which_are_const = compile_time_args ? compile_time_args->u64 : 0;
@@ -1800,7 +1802,7 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, U64 instance, Value *compile_time_
return true;
}
-static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
+static Status cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_SLICE: {
@@ -1843,7 +1845,7 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
}
/* generate a value from a pointer */
-static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
+static Status cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_TUPLE:
@@ -1871,7 +1873,8 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
arr_foreach(t->struc->fields, Field, f) {
if (f != t->struc->fields)
cgen_write(g, ", ");
- cgen_val_ptr(g, (char *)v + f->offset, &f->type, where);
+ if (!cgen_val_ptr(g, (char *)v + f->offset, &f->type, where))
+ return false;
}
cgen_write(g, "}");
break;
@@ -1879,8 +1882,9 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
cgen_fn_name(g, *(FnExpr **)v);
break;
case TYPE_PTR:
- err_print(where, "Cannot bring compile time pointer to runtime.");
- return false;
+ /* see: You can't have a constant pointer. */
+ assert(0);
+ break;
case TYPE_BUILTIN:
switch (t->builtin) {
case BUILTIN_I8: cgen_write(g, I8_FMT, *(I8 *)v); break;
@@ -1905,16 +1909,16 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
return true;
}
-static bool cgen_val_pre(CGenerator *g, Value v, Type *t, Location where) {
+static Status cgen_val_pre(CGenerator *g, Value v, Type *t, Location where) {
return cgen_val_ptr_pre(g, val_get_ptr(&v, t), t, where);
}
/* generates a value fit for use as an initializer */
-static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) {
+static Status cgen_val(CGenerator *g, Value v, Type *t, Location where) {
return cgen_val_ptr(g, val_get_ptr(&v, t), t, where);
}
-static bool cgen_decl(CGenerator *g, Declaration *d) {
+static Status cgen_decl(CGenerator *g, Declaration *d) {
if (d->flags & DECL_FOREIGN)
return true; /* already dealt with */
if (g->block == NULL && g->fn == NULL)
@@ -2012,7 +2016,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
return true;
}
-static bool cgen_ret(CGenerator *g, Expression *ret) {
+static Status cgen_ret(CGenerator *g, Expression *ret) {
FnExpr *f = g->fn;
if (f->ret_decls) {
assert(!ret);
@@ -2080,7 +2084,7 @@ static bool cgen_ret(CGenerator *g, Expression *ret) {
}
-static bool cgen_stmt(CGenerator *g, Statement *s) {
+static Status cgen_stmt(CGenerator *g, Statement *s) {
/*
TODO(eventually): optionally this:
cgen_write(g, "/\* %s:%d *\/", s->where.ctx->filename, s->where.line);
@@ -2111,7 +2115,7 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
return true;
}
-static bool cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) {
+static Status cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) {
FnType *fn_type = &t->fn;
bool any_const = false;
if (fn_type->constness) {
@@ -2137,7 +2141,7 @@ static bool cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) {
return true;
}
-static bool cgen_defs_expr(CGenerator *g, Expression *e) {
+static Status cgen_defs_expr(CGenerator *g, Expression *e) {
if (e->kind == EXPR_FN) {
if (!cgen_defs_fn(g, e->fn, &e->type))
return false;
@@ -2146,7 +2150,7 @@ static bool cgen_defs_expr(CGenerator *g, Expression *e) {
return true;
}
-static bool cgen_defs_decl(CGenerator *g, Declaration *d) {
+static Status cgen_defs_decl(CGenerator *g, Declaration *d) {
if (d->flags & DECL_FOREIGN) {
return true; /* dealt with by decls_cgen */
}
@@ -2158,7 +2162,7 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d) {
}
-static bool cgen_defs_stmt(CGenerator *g, Statement *s) {
+static Status cgen_defs_stmt(CGenerator *g, Statement *s) {
switch (s->kind) {
case STMT_DECL:
if (!cgen_defs_decl(g, s->decl))
@@ -2182,7 +2186,7 @@ static bool cgen_defs_stmt(CGenerator *g, Statement *s) {
return true;
}
-static bool cgen_defs_block(CGenerator *g, Block *b) {
+static Status cgen_defs_block(CGenerator *g, Block *b) {
/*
NOTE: since we exit as soon as there's an error for cgen, we don't need to make sure we
set g->block to the previous block if there's an error
@@ -2201,7 +2205,7 @@ static bool cgen_defs_block(CGenerator *g, Block *b) {
return true;
}
-static bool cgen_file(CGenerator *g, ParsedFile *f) {
+static Status cgen_file(CGenerator *g, ParsedFile *f) {
g->block = NULL;
g->nms = NULL;
g->fn = NULL;
@@ -2230,8 +2234,7 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
"static void _free(void *data) { extern void free(void *data); free(data); }\n" /* don't introduce free to global namespace */
"static void *_ecalloc(size_t n, size_t sz) { extern void *calloc(size_t n, size_t size); extern void abort(void); extern int printf(const char *fmt, ...); void *ret = calloc(n, sz); if (n && sz && !ret) { printf(\"Out of memory.\\n\"); abort(); } return ret; }\n\n\n");
- if (!cgen_sdecls_file(g, f))
- return false;
+ cgen_sdecls_file(g, f);
if (!cgen_decls_file(g, f))
return false;
cgen_write(g, "/* code */\n");
diff --git a/decls_cgen.c b/decls_cgen.c
index 2c6fc63..9776547 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -3,11 +3,11 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-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 Status cgen_decls_stmt(CGenerator *g, Statement *s);
+static Status cgen_decls_block(CGenerator *g, Block *b);
+static Status cgen_decls_decl(CGenerator *g, Declaration *d);
-static bool cgen_decls_type(CGenerator *g, Type *type) {
+static Status cgen_decls_type(CGenerator *g, Type *type) {
if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */
return true;
if (type->kind == TYPE_STRUCT) {
@@ -37,7 +37,7 @@ static bool cgen_decls_type(CGenerator *g, Type *type) {
return true;
}
-static bool cgen_single_fn_decl(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
+static Status cgen_single_fn_decl(CGenerator *g, FnExpr *f, U64 instance, U64 which_are_const) {
if (cgen_should_gen_fn(f)) {
if (!cgen_fn_header(g, f, instance, which_are_const))
return false;
@@ -48,7 +48,7 @@ static bool cgen_single_fn_decl(CGenerator *g, FnExpr *f, U64 instance, U64 whic
}
-static bool cgen_decls_fn_instances(CGenerator *g, FnExpr *f) {
+static Status 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]) {
@@ -66,7 +66,7 @@ static bool cgen_decls_fn_instances(CGenerator *g, FnExpr *f) {
return true;
}
-static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
+static Status cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
FnType *fn_type = &t->fn;
if (fn_type->constness) {
if (!cgen_decls_fn_instances(g, f))
@@ -78,7 +78,7 @@ static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
return true;
}
-static bool cgen_decls_expr(CGenerator *g, Expression *e) {
+static Status 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) {
@@ -111,7 +111,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
return true;
}
-static bool cgen_decls_block(CGenerator *g, Block *b) {
+static Status cgen_decls_block(CGenerator *g, Block *b) {
Block *prev_block = g->block;
g->block = b;
arr_foreach(b->stmts, Statement, s)
@@ -123,7 +123,7 @@ static bool cgen_decls_block(CGenerator *g, Block *b) {
return true;
}
-static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
+static Status cgen_decls_decl(CGenerator *g, Declaration *d) {
if (d->flags & DECL_FOREIGN) {
cgen_write(g, "extern ");
if ((d->flags & DECL_IS_CONST) && (d->type.kind == TYPE_FN) && arr_len(d->idents) == 1) {
@@ -218,7 +218,7 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
return true;
}
-static bool cgen_decls_stmt(CGenerator *g, Statement *s) {
+static Status cgen_decls_stmt(CGenerator *g, Statement *s) {
switch (s->kind) {
case STMT_DECL:
if (!cgen_decls_decl(g, s->decl))
@@ -242,7 +242,7 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) {
return true;
}
-static bool cgen_decls_file(CGenerator *g, ParsedFile *f) {
+static Status cgen_decls_file(CGenerator *g, ParsedFile *f) {
cgen_write(g, "/* declarations */\n");
arr_foreach(f->stmts, Statement, s) {
if (!cgen_decls_stmt(g, s))
diff --git a/eval.c b/eval.c
index 4162776..eba5556 100644
--- a/eval.c
+++ b/eval.c
@@ -4,11 +4,11 @@
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static bool types_block(Typer *tr, Block *b);
-static bool types_decl(Typer *tr, Declaration *d);
-static bool type_resolve(Typer *tr, Type *t, Location where);
-static bool eval_block(Evaluator *ev, Block *b, Value *v);
-static bool eval_expr(Evaluator *ev, Expression *e, Value *v);
+static Status types_block(Typer *tr, Block *b);
+static Status types_decl(Typer *tr, Declaration *d);
+static Status type_resolve(Typer *tr, Type *t, Location where);
+static Status eval_block(Evaluator *ev, Block *b, Value *v);
+static Status eval_expr(Evaluator *ev, Expression *e, Value *v);
static Value get_builtin_val(BuiltinVal val);
static void evalr_create(Evaluator *ev, Typer *tr, Allocator *allocr) {
@@ -567,7 +567,7 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
}
}
-static bool eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_type, void **ptr, Type **type) {
+static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_type, void **ptr, Type **type) {
switch (arr_type->kind) {
case TYPE_ARR: {
U64 arr_sz = (U64)arr_type->arr.n;
@@ -592,7 +592,7 @@ static bool eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr_t
return true;
}
-static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Type **type) {
+static Status eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Type **type) {
Value arr;
if (!eval_expr(ev, e->binary.lhs, &arr)) return false;
Value index;
@@ -679,7 +679,7 @@ static inline bool eval_address_of_ident(Identifier i, Location where, Type *typ
return true;
}
-static bool eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void **p) {
+static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void **p) {
Type *struct_type = &dot_expr->binary.lhs->type;
bool is_ptr = struct_type->kind == TYPE_PTR;
if (is_ptr) {
@@ -711,7 +711,7 @@ static bool eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void *
return true;
}
-static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) {
+static Status eval_address_of(Evaluator *ev, Expression *e, void **ptr) {
switch (e->kind) {
case EXPR_IDENT: {
if (!eval_address_of_ident(e->ident, e->where, &e->type, ptr))
@@ -755,7 +755,7 @@ static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) {
return true;
}
-static bool eval_set(Evaluator *ev, Expression *set, Value *to) {
+static Status eval_set(Evaluator *ev, Expression *set, Value *to) {
switch (set->kind) {
case EXPR_IDENT: {
Identifier i = set->ident;
@@ -996,7 +996,7 @@ static bool val_is_nonnegative(Value *v, Type *t) {
return val_to_i64(v, t->builtin) >= 0;
}
-static bool eval_ident(Evaluator *ev, Identifier ident, Value *v, Location where) {
+static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location where) {
if (ident->decl_kind == IDECL_NONE) {
char *s = ident_to_str(ident);
err_print(where, "Undeclared identifier: %s.", s);
@@ -1068,7 +1068,7 @@ static void decl_remove_val(Declaration *d) {
arr_remove_last(&d->val_stack);
}
-static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
+static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
#define eval_unary_op_one(low, up, op) \
case BUILTIN_##up: \
@@ -1572,7 +1572,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
return true;
}
-static bool eval_decl(Evaluator *ev, Declaration *d) {
+static Status eval_decl(Evaluator *ev, Declaration *d) {
unsigned has_expr = d->flags & DECL_HAS_EXPR;
unsigned is_const = d->flags & DECL_IS_CONST;
Value val = {0};
@@ -1620,7 +1620,7 @@ static bool eval_decl(Evaluator *ev, Declaration *d) {
return true;
}
-static bool eval_stmt(Evaluator *ev, Statement *stmt) {
+static Status eval_stmt(Evaluator *ev, Statement *stmt) {
switch (stmt->kind) {
case STMT_DECL:
if (!eval_decl(ev, stmt->decl)) return false;
@@ -1656,7 +1656,7 @@ static void eval_exit_stmts(Statement *stmts) {
}
}
-static bool eval_block(Evaluator *ev, Block *b, Value *v) {
+static Status eval_block(Evaluator *ev, Block *b, Value *v) {
Block *prev = ev->typer->block;
ev->typer->block = b;
bool success = true;
diff --git a/main.c b/main.c
index 262f6c4..d63b95b 100644
--- a/main.c
+++ b/main.c
@@ -4,25 +4,14 @@
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-/*
- NOTE:
- Structure of the toc compiler:
- tokenizer => parser => typing (types.c) => cgen
- (lexing)
-
- toc tries to continue even after the first error.
- It will not continue during cgen, but it will during tokenization,
- parsing, and typing. If one stage fails, the following ones do not
- start.
-*/
+/* see toc.c for development information */
/*
TODO:
-make sure we're checking for redecls with #include
-
+try to make cgen not have return values anymore
nice syntax for #including something into a namespace
run stuff at compile time without assigning it to a constant
-the problem of #foreign stuff currently requiring that source and target have the same sizeof(int), etc. -- we may need #C_int, etc.
+better #foreign system- something like f := #foreign fn (int,float, #C int);
---
constants in structs
#if
@@ -123,6 +112,7 @@ int main(int argc, char **argv) {
tokr_create(&t, &err_ctx, &main_allocr);
if (!tokenize_file(&t, &file)) {
err_text_important(&err_ctx, "Errors occured during preprocessing.\n");
+ allocr_free_all(&main_allocr);
return EXIT_FAILURE;
}
@@ -140,6 +130,7 @@ int main(int argc, char **argv) {
ParsedFile f;
if (!parse_file(&p, &f)) {
err_text_important(&err_ctx, "Errors occured during parsing.\n");
+ allocr_free_all(&main_allocr);
return EXIT_FAILURE;
}
/* fprint_parsed_file(stdout, &f); */
@@ -154,6 +145,7 @@ int main(int argc, char **argv) {
if (!types_file(&tr, &f)) {
/* TODO(eventually): fix this if the error occured while exporting something */
err_text_important(&err_ctx, "Errors occured while determining types.\n");
+ allocr_free_all(&main_allocr);
return EXIT_FAILURE;
}
#ifdef TOC_DEBUG
@@ -164,13 +156,16 @@ int main(int argc, char **argv) {
if (!out) {
err_text_important(&err_ctx, "Could not open output file: ");
err_fprint(&err_ctx, "%s\n", out_filename);
+ allocr_free_all(&main_allocr);
return EXIT_FAILURE;
}
CGenerator g;
- cgen_create(&g, out, &globals, &ev, &main_allocr);
+ cgen_create(&g, out, &globals, &main_allocr);
if (!cgen_file(&g, &f)) {
fclose(out);
err_text_important(&err_ctx, "Errors occured while generating C code.\n");
+ allocr_free_all(&main_allocr);
+ fclose(out);
return EXIT_FAILURE;
}
diff --git a/parse.c b/parse.c
index 8a23ac0..1861996 100644
--- a/parse.c
+++ b/parse.c
@@ -3,16 +3,16 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static bool parse_expr(Parser *p, Expression *e, Token *end);
-static bool parse_stmt(Parser *p, Statement *s, bool *was_a_statement);
+static Status parse_expr(Parser *p, Expression *e, Token *end);
+static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement);
enum {
PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR = 0x01,
PARSE_DECL_ALLOW_SEMI_CONST = 0x02,
PARSE_DECL_ALLOW_INFER = 0x04,
PARSE_DECL_ALLOW_EXPORT = 0x08
};
-static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_t flags);
-static bool parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end);
+static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_t flags);
+static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end);
static bool is_decl(Tokenizer *t);
static inline bool ends_decl(Token *t, DeclEndKind ends_with);
@@ -421,7 +421,7 @@ static Token *expr_find_end(Parser *p, ExprEndFlags flags) {
}
/* parses, e.g. "(3, 5, foo)" */
-static bool parse_args(Parser *p, Argument **args) {
+static Status parse_args(Parser *p, Argument **args) {
Tokenizer *t = p->tokr;
Token *start = t->token;
assert(token_is_kw(start, KW_LPAREN));
@@ -460,7 +460,7 @@ static bool parse_args(Parser *p, Argument **args) {
return true;
}
-static bool parse_type(Parser *p, Type *type) {
+static Status parse_type(Parser *p, Type *type) {
Tokenizer *t = p->tokr;
type->where = parser_mk_loc(p);
type->where.start = t->token;
@@ -835,7 +835,7 @@ static bool parser_is_definitely_type(Parser *p, Token **end) {
enum {
PARSE_BLOCK_DONT_CREATE_IDENTS = 0x01
};
-static bool parse_block(Parser *p, Block *b, U8 flags) {
+static Status parse_block(Parser *p, Block *b, U8 flags) {
Tokenizer *t = p->tokr;
Block *prev_block = p->block;
b->flags = 0;
@@ -886,7 +886,7 @@ static bool parse_block(Parser *p, Block *b, U8 flags) {
}
/* does NOT handle empty declaration lists */
-static bool parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end) {
+static Status parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end) {
Tokenizer *t = p->tokr;
bool ret = true;
bool first = true;
@@ -920,7 +920,7 @@ static bool parse_decl_list(Parser *p, Declaration **decls, DeclEndKind decl_end
return ret;
}
-static bool parse_fn_expr(Parser *p, FnExpr *f) {
+static Status parse_fn_expr(Parser *p, FnExpr *f) {
Tokenizer *t = p->tokr;
f->ret_decls = NULL;
{
@@ -1043,7 +1043,7 @@ static Identifier parser_ident_insert(Parser *p, char *str) {
return i;
}
-static bool check_ident_redecl(Parser *p, Identifier i) {
+static Status check_ident_redecl(Parser *p, Identifier i) {
Tokenizer *t = p->tokr;
if (i->idents == &p->block->idents) {
if (i->decl_kind != IDECL_NONE) {
@@ -1057,7 +1057,7 @@ static bool check_ident_redecl(Parser *p, Identifier i) {
return true;
}
-static bool parse_expr(Parser *p, Expression *e, Token *end) {
+static Status parse_expr(Parser *p, Expression *e, Token *end) {
Tokenizer *t = p->tokr;
#if 0
@@ -1928,7 +1928,7 @@ static inline bool ends_decl(Token *t, DeclEndKind ends_with) {
}
}
-static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 flags) {
+static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 flags) {
Tokenizer *t = p->tokr;
d->where = parser_mk_loc(p);
d->where.start = t->token;
@@ -2126,7 +2126,7 @@ static bool is_decl(Tokenizer *t) {
}
/* sets *was_a_statement to false if s was not filled, but the token was advanced */
-static bool parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
+static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
Tokenizer *t = p->tokr;
if (t->token->kind == TOKEN_EOF) {
tokr_err(t, "Expected statement.");
@@ -2223,7 +2223,7 @@ static void parser_create(Parser *p, Identifiers *globals, Tokenizer *t, Allocat
p->allocr = allocr;
}
-static bool parse_file(Parser *p, ParsedFile *f) {
+static Status parse_file(Parser *p, ParsedFile *f) {
Tokenizer *t = p->tokr;
f->stmts = NULL;
p->file = t->file;
diff --git a/sdecls_cgen.c b/sdecls_cgen.c
index a146eb2..6900b78 100644
--- a/sdecls_cgen.c
+++ b/sdecls_cgen.c
@@ -3,7 +3,7 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static bool cgen_sdecls_stmt(CGenerator *g, Statement *s);
+static void cgen_sdecls_stmt(CGenerator *g, Statement *s);
static bool cgen_sdecls_decl(CGenerator *g, Declaration *d);
static bool cgen_sdecls_expr(CGenerator *g, Expression *e);
@@ -33,19 +33,20 @@ static bool cgen_sdecls_type(CGenerator *g, Type *type) {
return true;
}
+/* ALWAYS RETURNS TRUE. just returns a bool for cgen_recurse_subexprs to work. */
static bool cgen_sdecls_block(CGenerator *g, Block *b) {
Block *prev_block = g->block;
g->block = b;
arr_foreach(b->stmts, Statement, s)
- if (!cgen_sdecls_stmt(g, s))
- return false;
- if (b->ret_expr && !cgen_sdecls_expr(g, b->ret_expr))
- return false;
+ cgen_sdecls_stmt(g, s);
+ if (b->ret_expr)
+ cgen_sdecls_expr(g, b->ret_expr);
g->block = prev_block;
return true;
}
+/* ALWAYS RETURNS TRUE. just returns a bool for cgen_recurse_subexprs to work. */
static bool cgen_sdecls_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_CAST:
@@ -56,8 +57,7 @@ static bool cgen_sdecls_expr(CGenerator *g, Expression *e) {
e->fn->c.id = ++g->ident_counter;
break;
case EXPR_TYPE:
- if (!cgen_sdecls_type(g, &e->typeval))
- return false;
+ cgen_sdecls_type(g, &e->typeval);
break;
case EXPR_NMS:
e->nms.c.id = 0;
@@ -66,15 +66,16 @@ static bool cgen_sdecls_expr(CGenerator *g, Expression *e) {
}
cgen_recurse_subexprs(g, e, cgen_sdecls_expr, cgen_sdecls_block, cgen_sdecls_decl);
return true;
-
}
+
+/* ALWAYS RETURNS TRUE. just returns a bool for cgen_recurse_subexprs to work. */
static bool cgen_sdecls_decl(CGenerator *g, Declaration *d) {
if (d->flags & DECL_FOREIGN) {
/* handled by cgen_decls */
return true;
}
- cgen_sdecls_type(g, &d->type);
+ cgen_sdecls_type(g, &d->type);
if (cgen_fn_is_direct(g, d)) {
d->expr.fn->c.name = d->idents[0];
}
@@ -82,13 +83,11 @@ static bool cgen_sdecls_decl(CGenerator *g, Declaration *d) {
Type *type = decl_type_at_index(d, idx);
Value *val = decl_val_at_index(d, idx);
if (type_is_builtin(type, BUILTIN_TYPE)) {
- if (!cgen_sdecls_type(g, val->type))
- return false;
+ cgen_sdecls_type(g, val->type);
}
}
if (d->flags & DECL_HAS_EXPR) {
- if (!cgen_sdecls_expr(g, &d->expr))
- return false;
+ cgen_sdecls_expr(g, &d->expr);
if (d->flags & DECL_EXPORT) {
if (d->expr.kind == EXPR_FN)
d->expr.fn->flags |= FN_EXPR_EXPORT;
@@ -97,34 +96,27 @@ static bool cgen_sdecls_decl(CGenerator *g, Declaration *d) {
return true;
}
-static bool cgen_sdecls_stmt(CGenerator *g, Statement *s) {
+static void cgen_sdecls_stmt(CGenerator *g, Statement *s) {
switch (s->kind) {
case STMT_DECL:
- if (!cgen_sdecls_decl(g, s->decl))
- return false;
+ cgen_sdecls_decl(g, s->decl);
break;
case STMT_EXPR:
- if (!cgen_sdecls_expr(g, &s->expr))
- return false;
+ cgen_sdecls_expr(g, &s->expr);
break;
case STMT_RET:
if (s->ret.flags & RET_HAS_EXPR)
- if (!cgen_sdecls_expr(g, &s->ret.expr))
- return false;
+ cgen_sdecls_expr(g, &s->ret.expr);
break;
case STMT_INCLUDE:
arr_foreach(s->inc.stmts, Statement, sub)
- if (!cgen_sdecls_stmt(g, sub))
- return false;
+ cgen_sdecls_stmt(g, sub);
break;
}
- return true;
}
-static bool cgen_sdecls_file(CGenerator *g, ParsedFile *f) {
+static void cgen_sdecls_file(CGenerator *g, ParsedFile *f) {
arr_foreach(f->stmts, Statement, s) {
- if (!cgen_sdecls_stmt(g, s))
- return false;
+ cgen_sdecls_stmt(g, s);
}
- return true;
}
diff --git a/test.toc b/test.toc
index 8eed5b7..01c9646 100644
--- a/test.toc
+++ b/test.toc
@@ -1,13 +1,5 @@
-io ::= nms {
-#include "std/io.toc";
-};
-
-foo ::= fn() <int, int> {
- 3, 5
-};
main ::= fn() {
- _, x := foo();
- y, _ := foo();
- io.puti(x); io.puti(y);
+ x :: &int = new(int);
+ y := x;
}; \ No newline at end of file
diff --git a/toc.c b/toc.c
index cb01b34..152c6d7 100644
--- a/toc.c
+++ b/toc.c
@@ -4,7 +4,38 @@
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-/* NOTE: all stages should use the same allocator! */
+
+/*
+ NOTE:
+ Structure of the toc compiler:
+ tokenizer => parser => typing (types.c) => cgen
+ (lexing)
+
+ toc tries to continue even after the first error.
+ It will not continue during cgen, but it will during tokenization,
+ parsing, and typing. If one stage fails, the following ones do not
+ start.
+
+ toc's memory management works using an allocator which never frees anything.
+ This is because most of toc's data is kept around until the end of the program anyways.
+ Use the allocator for "permanent" allocations, and err_malloc/calloc/realloc for temporary
+ allocations (to avoid having it take up space for a long time).
+
+ Because of this, memory leaks can happen if the compilation fails at any point, but they
+ should not happen if the compilation succeeds. Usually if there's an error
+ which causes a memory leak, it will be very small.
+
+ Functions which can fail (i.e. print an error message and stop) return a Status,
+ which is a bool, but GCC warns about not using the return value.
+
+ The fixed-width types U8/16/32/64 and I8/16/32/64 have been defined.
+ data_structures.c contains a dynamic array implementation which is very useful.
+ Many of the members of the types below are dynamic arrays.
+
+ It is assumed that the number of identifiers in a declaration, or parameters to a function
+ will fit in an int, since a function with (at least) 32768 parameters is ridiculous.
+*/
+
/* Includes all of toc's files */
#include <assert.h>
@@ -70,7 +101,6 @@ static void print_block_location(Block *b);
#define join3(a,b) a##b
#define join2(a,b) join3(a,b)
#define join(a,b) join2(a,b)
-#define eval(x) x
static void fprint_char_literal(FILE *f, char c) {
if (isprint(c))
@@ -137,7 +167,7 @@ static char *read_file_contents(Allocator *a, const char *filename, Location whe
#include "infer.c"
#include "types.c"
static bool cgen_decls_file(CGenerator *g, ParsedFile *f);
-static bool cgen_sdecls_file(CGenerator *g, ParsedFile *f);
+static void cgen_sdecls_file(CGenerator *g, ParsedFile *f);
#include "cgen.c"
#include "sdecls_cgen.c"
#include "decls_cgen.c"
diff --git a/tokenizer.c b/tokenizer.c
index 5a7e272..cd82c81 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -277,7 +277,7 @@ static Token *tokr_add(Tokenizer *t) {
return token;
}
-static bool tokenize_file(Tokenizer *t, File *file) {
+static Status tokenize_file(Tokenizer *t, File *file) {
int has_err = 0;
t->s = file->contents;
t->file = file;
diff --git a/types.c b/types.c
index 0148ec2..75f8f8a 100644
--- a/types.c
+++ b/types.c
@@ -3,8 +3,8 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static bool types_stmt(Typer *tr, Statement *s);
-static bool type_resolve(Typer *tr, Type *t, Location where);
+static Status types_stmt(Typer *tr, Statement *s);
+static Status type_resolve(Typer *tr, Type *t, Location where);
static inline void *typer_malloc(Typer *tr, size_t bytes) {
@@ -72,7 +72,7 @@ static size_t compiler_alignof_builtin(BuiltinType b) {
}
/* finds offsets and size */
-static bool struct_find_offsets(StructDef *s) {
+static Status struct_find_offsets(StructDef *s) {
/* assume the align of a struct is the greatest align out of its children's */
if (!(s->flags & STRUCT_DEF_FOUND_OFFSETS)) {
if (s->flags & STRUCT_DEF_FINDING_OFFSETS) {
@@ -246,7 +246,7 @@ static bool type_eq(Type *a, Type *b) {
}
/* expected must equal got, or an error will be produced */
-static bool type_must_eq(Location where, Type *expected, Type *got) {
+static Status type_must_eq(Location where, Type *expected, Type *got) {
if (!type_eq(expected, got)) {
char *str_ex = type_to_str(expected);
char *str_got = type_to_str(got);
@@ -257,7 +257,7 @@ static bool type_must_eq(Location where, Type *expected, Type *got) {
}
/* prints an error and returns false if the given expression is not an l-value */
-static bool expr_must_lval(Expression *e) {
+static Status expr_must_lval(Expression *e) {
/* NOTE: make sure you update eval when you change this */
switch (e->kind) {
case EXPR_IDENT: {
@@ -359,7 +359,7 @@ enum {
TYPE_OF_FN_IS_INSTANCE = 0x01
};
-static bool type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
+static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
t->kind = TYPE_FN;
t->fn.types = NULL;
t->fn.constness = NULL; /* OPTIM: constness doesn't need to be a dynamic array */
@@ -509,7 +509,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
}
/* may modify ident */
-static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t) {
+static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t) {
t->flags = 0;
Identifier i = *ident;
#if 0
@@ -660,7 +660,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t)
}
/* fixes the type (replaces [5+3]int with [8]int, etc.) */
-static bool type_resolve(Typer *tr, Type *t, Location where) {
+static Status type_resolve(Typer *tr, Type *t, Location where) {
Evaluator *ev = tr->evalr;
if (t->flags & TYPE_IS_RESOLVED) return true;
t->was_expr = NULL;
@@ -817,22 +817,22 @@ static bool type_can_be_truthy(Type *t) {
}
typedef enum {
- STATUS_NONE,
- STATUS_WARN,
- STATUS_ERR
-} Status;
+ CAST_STATUS_NONE,
+ CAST_STATUS_WARN,
+ CAST_STATUS_ERR
+} CastStatus;
-static Status type_cast_status(Type *from, Type *to) {
+static CastStatus type_cast_status(Type *from, Type *to) {
assert(from->flags & TYPE_IS_RESOLVED);
assert(to->flags & TYPE_IS_RESOLVED);
if (to->kind == TYPE_UNKNOWN)
- return STATUS_NONE;
+ return CAST_STATUS_NONE;
switch (from->kind) {
- case TYPE_UNKNOWN: return STATUS_NONE;
+ case TYPE_UNKNOWN: return CAST_STATUS_NONE;
case TYPE_STRUCT:
case TYPE_VOID:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
case TYPE_BUILTIN:
switch (from->builtin) {
case BUILTIN_I8:
@@ -858,24 +858,24 @@ static Status type_cast_status(Type *from, Type *to) {
case BUILTIN_F64:
case BUILTIN_BOOL:
case BUILTIN_CHAR:
- return STATUS_NONE;
+ return CAST_STATUS_NONE;
case BUILTIN_TYPE:
case BUILTIN_NMS:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
}
assert(0);
break;
case TYPE_UNKNOWN:
- return STATUS_NONE;
+ return CAST_STATUS_NONE;
case TYPE_PTR:
- return STATUS_WARN;
+ return CAST_STATUS_WARN;
default:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
}
break;
case BUILTIN_F32:
case BUILTIN_F64:
- if (to->kind != TYPE_BUILTIN) return STATUS_ERR;
+ if (to->kind != TYPE_BUILTIN) return CAST_STATUS_ERR;
switch (to->builtin) {
case BUILTIN_I8:
case BUILTIN_U8:
@@ -888,50 +888,50 @@ static Status type_cast_status(Type *from, Type *to) {
case BUILTIN_F32:
case BUILTIN_F64:
case BUILTIN_BOOL:
- return STATUS_NONE;
+ return CAST_STATUS_NONE;
case BUILTIN_CHAR:
case BUILTIN_TYPE:
case BUILTIN_NMS:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
}
assert(0);
break;
case BUILTIN_CHAR:
if (to->kind == TYPE_BUILTIN && type_builtin_is_int(to->builtin))
- return STATUS_NONE;
- return STATUS_ERR;
+ return CAST_STATUS_NONE;
+ return CAST_STATUS_ERR;
case BUILTIN_BOOL:
- return type_can_be_truthy(to) ? STATUS_NONE : STATUS_ERR;
+ return type_can_be_truthy(to) ? CAST_STATUS_NONE : CAST_STATUS_ERR;
case BUILTIN_TYPE:
case BUILTIN_NMS:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
}
break;
- case TYPE_TUPLE: return STATUS_ERR;
+ case TYPE_TUPLE: return CAST_STATUS_ERR;
case TYPE_FN:
if (to->kind == TYPE_PTR || to->kind == TYPE_FN)
- return STATUS_WARN;
- return STATUS_ERR;
+ return CAST_STATUS_WARN;
+ return CAST_STATUS_ERR;
case TYPE_PTR:
if (to->kind == TYPE_BUILTIN && type_builtin_is_int(to->builtin))
- return STATUS_WARN;
+ return CAST_STATUS_WARN;
if (to->kind == TYPE_PTR)
- return STATUS_NONE;
+ return CAST_STATUS_NONE;
if (to->kind == TYPE_FN)
- return STATUS_WARN;
+ return CAST_STATUS_WARN;
/* TODO: Cast from ptr to arr */
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
case TYPE_ARR:
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
case TYPE_SLICE:
if (to->kind == TYPE_PTR && type_eq(from->slice, to->ptr))
- return STATUS_NONE;
- return STATUS_ERR;
+ return CAST_STATUS_NONE;
+ return CAST_STATUS_ERR;
case TYPE_EXPR:
break;
}
assert(0);
- return STATUS_ERR;
+ return CAST_STATUS_ERR;
}
static bool arg_is_const(Expression *arg, Constness constness) {
@@ -947,7 +947,7 @@ static bool arg_is_const(Expression *arg, Constness constness) {
/* MUST be called after type_of_fn. */
/* pass NULL for instance if this isn't an instance */
-static bool types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
+static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
FnExpr *prev_fn = tr->fn;
bool success = true;
Expression *ret_expr;
@@ -1009,7 +1009,7 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
}
/* puts a dynamic array of the argument indices of the parameters into order. *order must be freed, even if function fails */
-static bool call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Location where, I16 **orderp) {
+static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Location where, I16 **orderp) {
*orderp = NULL;
assert(fn_type->flags & TYPE_IS_RESOLVED);
size_t nparams = arr_len(fn_type->fn.types)-1;
@@ -1132,7 +1132,7 @@ static bool call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Loca
/*
*order must be freed, regardless of return value. if (*order)[i] == -1, that parameter was not set.
*/
-static bool parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where) {
+static Status parameterized_struct_arg_order(StructDef *struc, Argument *args, I16 **order, Location where) {
size_t nargs = arr_len(args);
/*
@@ -1336,10 +1336,10 @@ static char *eval_expr_as_cstr(Typer *tr, Expression *e, const char *what_is_thi
}
-static bool types_expr(Typer *tr, Expression *e) {
+static Status types_expr(Typer *tr, Expression *e) {
if (e->flags & EXPR_FOUND_TYPE) return true;
Type *t = &e->type;
- t->flags = 0;
+ t->flags = TYPE_IS_RESOLVED;
t->was_expr = NULL;
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 */
@@ -1533,18 +1533,18 @@ static bool types_expr(Typer *tr, Expression *e) {
return false;
if (!type_resolve(tr, &c->type, e->where))
return false;
- Status status = type_cast_status(&c->expr->type, &c->type);
- if (status != STATUS_NONE) {
+ CastStatus status = type_cast_status(&c->expr->type, &c->type);
+ if (status != CAST_STATUS_NONE) {
char *from = type_to_str(&c->expr->type);
char *to = type_to_str(&c->type);
- if (status == STATUS_ERR)
+ if (status == CAST_STATUS_ERR)
err_print(e->where, "Cannot cast from type %s to %s.", from, to);
else
warn_print(e->where, "Casting from type %s to %s.", from, to);
free(from);
free(to);
- if (status == STATUS_ERR)
+ if (status == CAST_STATUS_ERR)
return false;
}
*t = c->type;
@@ -2592,7 +2592,7 @@ static bool types_expr(Typer *tr, Expression *e) {
}
-static bool types_block(Typer *tr, Block *b) {
+static Status types_block(Typer *tr, Block *b) {
if (b->flags & BLOCK_FOUND_TYPES)
return true;
@@ -2643,7 +2643,7 @@ static bool types_block(Typer *tr, Block *b) {
return success;
}
-static bool types_decl(Typer *tr, Declaration *d) {
+static Status types_decl(Typer *tr, Declaration *d) {
if (d->flags & DECL_FOUND_TYPE) return true;
bool success = true;
@@ -2673,6 +2673,7 @@ static bool types_decl(Typer *tr, Declaration *d) {
success = false;
goto ret;
}
+ assert(d->expr.type.flags & TYPE_IS_RESOLVED);
if (d->flags & DECL_ANNOTATES_TYPE) {
if (!type_must_eq(d->expr.where, &d->type, &d->expr.type)) {
success = false;
@@ -2783,6 +2784,14 @@ static bool types_decl(Typer *tr, Declaration *d) {
goto ret;
}
}
+ if (d->flags & DECL_IS_CONST) {
+ if (d->type.kind == TYPE_PTR) {
+ err_print(d->where, "You can't have a constant pointer.");
+ success = false;
+ goto ret;
+ }
+ }
+
if (n_idents == 1 && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_NMS) {
bool is_at_top_level = true;
typedef Block *BlockPtr;
@@ -2811,7 +2820,7 @@ static bool types_decl(Typer *tr, Declaration *d) {
return success;
}
-static bool types_stmt(Typer *tr, Statement *s) {
+static Status types_stmt(Typer *tr, Statement *s) {
if (s->flags & STMT_TYPED) return true;
switch (s->kind) {
case STMT_EXPR:
@@ -2914,7 +2923,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a
*(Block **)arr_adda(&tr->blocks, allocr) = NULL;
}
-static bool types_file(Typer *tr, ParsedFile *f) {
+static Status types_file(Typer *tr, ParsedFile *f) {
bool ret = true;
tr->parsed_file = f;
arr_foreach(f->stmts, Statement, s) {
diff --git a/types.h b/types.h
index 2ed4b24..57e9d00 100644
--- a/types.h
+++ b/types.h
@@ -64,6 +64,11 @@ typedef U8 bool;
#define true ((bool)1)
#endif
+#if defined __GNUC__ && !defined NO_WARN_UNUSED_RESULT
+#define Status bool __attribute__((warn_unused_result))
+#else
+#define Status bool
+#endif
typedef int8_t I8;
#define I8_MAX INT8_MAX
@@ -923,7 +928,6 @@ typedef struct CGenerator {
Block *block;
Namespace *nms;
FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */
- Evaluator *evalr;
Identifier main_ident;
Identifiers *globals;
char *nms_prefix; /* dynamic (null-terminated) array of characters, the current namespace C prefix (e.g. "foo__bar__") */