summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c221
-rw-r--r--copy.c156
-rw-r--r--decls_cgen.c6
-rw-r--r--main.c2
-rw-r--r--test.toc20
-rw-r--r--tokenizer.c2
-rw-r--r--types.c21
7 files changed, 231 insertions, 197 deletions
diff --git a/cgen.c b/cgen.c
index 8191d71..5d98814 100644
--- a/cgen.c
+++ b/cgen.c
@@ -26,106 +26,120 @@ 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);
+#define cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f) \
+ if (!fn_enter(fn, 0)) return false; \
+ arr_foreach(fn->params, Declaration, param) \
+ if (!decl_f(g, param)) \
+ return false; \
+ arr_foreach(fn->ret_decls, Declaration, r) \
+ if (!decl_f(g, r)) \
+ return false; \
+ if (!block_f(g, &fn->body)) \
+ return false; \
+ fn_exit(fn);
+
/* calls f on every sub-expression of e, block_f on every sub-block, and decl_f on every sub-declaration. */
-#define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \
- switch (e->kind) { \
- case EXPR_TYPE: \
- case EXPR_VAL: \
- case EXPR_C: \
- case EXPR_DSIZEOF: \
- case EXPR_DALIGNOF: \
- case EXPR_IDENT: \
- case EXPR_LITERAL_BOOL: \
- case EXPR_LITERAL_INT: \
- case EXPR_LITERAL_STR: \
- case EXPR_LITERAL_CHAR: \
- case EXPR_LITERAL_FLOAT: \
- break; \
- case EXPR_UNARY_OP: \
- if (!f(g, e->unary.of)) return false; \
- break; \
- case EXPR_BINARY_OP: \
- if (!f(g, e->binary.lhs)) return false; \
- if (e->binary.op != BINARY_DOT) \
- if (!f(g, e->binary.rhs)) \
- return false; \
- break; \
- case EXPR_CAST: \
- if (!f(g, e->cast.expr)) \
- return false; \
- break; \
- case EXPR_CALL: \
- if (!f(g, e->call.fn)) \
- return false; \
- arr_foreach(e->call.arg_exprs, Expression, arg) \
- if (!f(g, arg)) \
- return false; \
- break; \
- case EXPR_BLOCK: \
- if (!block_f(g, &e->block)) \
- return false; \
- break; \
- case EXPR_IF: \
- if (e->if_.cond) \
- if (!f(g, e->if_.cond)) \
- return false; \
- if (!block_f(g, &e->if_.body)) \
- return false; \
- if (e->if_.next_elif) \
- if (!f(g, e->if_.next_elif)) \
- return false; \
- break; \
- case EXPR_WHILE: \
- if (e->while_.cond) \
- if (!f(g, e->while_.cond)) \
- return false; \
- if (!block_f(g, &e->while_.body)) \
- return false; \
- break; \
- case EXPR_EACH: { \
- EachExpr *ea = &e->each; \
- if (!each_enter(e)) return false; \
- if (ea->flags & EACH_IS_RANGE) { \
- if (!f(g, ea->range.from)) \
- return false; \
- if (ea->range.to && !f(g, ea->range.to)) \
- return false; \
- /* step is a value, not an expression */ \
- } else { \
- if (!f(g, ea->of)) \
- return false; \
- } \
- if (!block_f(g, &ea->body)) return false; \
- each_exit(e); \
- } break; \
- case EXPR_TUPLE: \
- arr_foreach(e->tuple, Expression, x) \
- if (!f(g, x)) \
- return false; \
- break; \
- case EXPR_SLICE: \
- if (!f(g, e->slice.of)) return false; \
- if (e->slice.from && !f(g, e->slice.from)) \
- return false; \
- if (e->slice.to && !f(g, e->slice.to)) \
- return false; \
- break; \
- case EXPR_FN: \
- if (!fn_enter(&e->fn, 0)) return false; \
- arr_foreach(e->fn.params, Declaration, param) \
- if (!decl_f(g, param)) \
- return false; \
- arr_foreach(e->fn.ret_decls, Declaration, r) \
- if (!decl_f(g, r)) \
- return false; \
- if (!block_f(g, &e->fn.body)) \
- return false; \
- fn_exit(&e->fn); \
- break; \
- case EXPR_NEW: \
- if (e->new.n && !f(g, e->new.n)) \
- return false; \
- break; \
+#define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \
+ switch (e->kind) { \
+ case EXPR_TYPE: \
+ case EXPR_VAL: \
+ case EXPR_C: \
+ case EXPR_DSIZEOF: \
+ case EXPR_DALIGNOF: \
+ case EXPR_IDENT: \
+ case EXPR_LITERAL_BOOL: \
+ case EXPR_LITERAL_INT: \
+ case EXPR_LITERAL_STR: \
+ case EXPR_LITERAL_CHAR: \
+ case EXPR_LITERAL_FLOAT: \
+ break; \
+ case EXPR_UNARY_OP: \
+ if (!f(g, e->unary.of)) return false; \
+ break; \
+ case EXPR_BINARY_OP: \
+ if (!f(g, e->binary.lhs)) return false; \
+ if (e->binary.op != BINARY_DOT) \
+ if (!f(g, e->binary.rhs)) \
+ return false; \
+ break; \
+ case EXPR_CAST: \
+ if (!f(g, e->cast.expr)) \
+ return false; \
+ break; \
+ case EXPR_CALL: \
+ if (!f(g, e->call.fn)) \
+ return false; \
+ arr_foreach(e->call.arg_exprs, Expression, arg) \
+ if (!f(g, arg)) \
+ return false; \
+ break; \
+ case EXPR_BLOCK: \
+ if (!block_f(g, &e->block)) \
+ return false; \
+ break; \
+ case EXPR_IF: \
+ if (e->if_.cond) \
+ if (!f(g, e->if_.cond)) \
+ return false; \
+ if (!block_f(g, &e->if_.body)) \
+ return false; \
+ if (e->if_.next_elif) \
+ if (!f(g, e->if_.next_elif)) \
+ return false; \
+ break; \
+ case EXPR_WHILE: \
+ if (e->while_.cond) \
+ if (!f(g, e->while_.cond)) \
+ return false; \
+ if (!block_f(g, &e->while_.body)) \
+ return false; \
+ break; \
+ case EXPR_EACH: { \
+ EachExpr *ea = &e->each; \
+ if (!each_enter(e)) return false; \
+ if (ea->flags & EACH_IS_RANGE) { \
+ if (!f(g, ea->range.from)) \
+ return false; \
+ if (ea->range.to && !f(g, ea->range.to)) \
+ return false; \
+ /* step is a value, not an expression */ \
+ } else { \
+ if (!f(g, ea->of)) \
+ return false; \
+ } \
+ if (!block_f(g, &ea->body)) return false; \
+ each_exit(e); \
+ } break; \
+ case EXPR_TUPLE: \
+ arr_foreach(e->tuple, Expression, x) \
+ if (!f(g, x)) \
+ return false; \
+ break; \
+ case EXPR_SLICE: \
+ if (!f(g, e->slice.of)) return false; \
+ if (e->slice.from && !f(g, e->slice.from)) \
+ return false; \
+ if (e->slice.to && !f(g, e->slice.to)) \
+ return false; \
+ break; \
+ case EXPR_FN: { \
+ FnExpr *fn = &e->fn; \
+ if (e->type.fn.constness) { \
+ Instance **data = fn->instance.data; \
+ for (U64 i = 0; i < f->instances.cap; i++) { \
+ if (f->instances.occupied[i]) { \
+ cgen_recurse_subexprs_fn_simple(&(*data)->fn, decl_f, block_f); \
+ } \
+ data++; \
+ } \
+ } else { \
+ cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f); \
+ } \
+ break; \
+ case EXPR_NEW: \
+ if (e->new.n && !f(g, e->new.n)) \
+ return false; \
+ break; \
}
static bool cgen_block_enter(CGenerator *g, Block *b) {
@@ -1377,7 +1391,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_TUPLE:
/* the only time this should happen is if you're stating
a tuple, e.g. 3, 5;, but we've errored about that before
- (the comma operator does not exist in toc!) */
+ */
case EXPR_TYPE:
assert(0);
break;
@@ -1692,7 +1706,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
struct declarations are handled by typedefs_cgen,
and struct definitions are handled by decls_cgen.
we don't need to do anything here.
- */
+ */
continue;
} else if (type->kind == TYPE_FN && (d->flags & DECL_IS_CONST)) {
/* don't generate function pointer declaration for constant fns */
@@ -1766,6 +1780,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
/* does NOT call cgen_expr_pre for ret. */
static bool cgen_ret(CGenerator *g, Expression *ret) {
assert((g->fn->ret_type.kind == TYPE_VOID) == (ret == NULL));
+ if (ret) assert(type_eq(&g->fn->ret_type, &ret->type));
if (!ret) {
cgen_write(g, "return");
} else if (cgen_uses_ptr(&g->fn->ret_type)) {
@@ -1834,7 +1849,7 @@ static bool cgen_defs_expr(CGenerator *g, Expression *e) {
for (U64 i = 0; i < instances->cap; i++) {
if (instances->occupied[i]) {
/* generate this instance */
- if (!cgen_fn(g, f, e->where, is[i]->c.id, is[i]->val.tuple))
+ if (!cgen_fn(g, &is[i]->fn, e->where, is[i]->c.id, is[i]->val.tuple))
return false;
}
}
@@ -1891,7 +1906,7 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
/*
TODO: to improve compile times, don't include stdlib.h
(you can even get away with not including stdio.h with posix file descriptors)
- */
+ */
cgen_write(g, "#include <stdint.h>\n"
"#include <stdlib.h>\n"
"#include <stdio.h>\n"
diff --git a/copy.c b/copy.c
index 1677a7d..a296171 100644
--- a/copy.c
+++ b/copy.c
@@ -1,8 +1,13 @@
/* 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_decl(Allocator *a, Declaration *out, Declaration *in);
-static void copy_block(Allocator *a, Block *out, Block *in);
+typedef struct {
+ Allocator *allocr;
+ Block *block;
+} Copier;
+
+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);
static void copy_val(Allocator *allocr, Value *out, Value *in, Type *t) {
switch (t->kind) {
@@ -36,7 +41,7 @@ static void copy_val(Allocator *allocr, Value *out, Value *in, Type *t) {
}
}
-static void copy_type(Allocator *a, Type *out, Type *in) {
+static void copy_type(Copier *c, Type *out, Type *in) {
assert(!(in->flags & TYPE_IS_RESOLVED));
*out = *in;
switch (in->kind) {
@@ -49,65 +54,69 @@ static void copy_type(Allocator *a, Type *out, Type *in) {
case TYPE_FN: {
size_t ntypes = arr_len(in->fn.types);
out->fn.types = NULL;
- arr_set_lena(&out->fn.types, ntypes, a);
+ arr_set_lena(&out->fn.types, ntypes, c->allocr);
for (size_t i = 0; i < ntypes; i++) {
- copy_type(a, &out->fn.types[i], &in->fn.types[i]);
+ copy_type(c, &out->fn.types[i], &in->fn.types[i]);
}
} break;
case TYPE_TUPLE: {
size_t ntypes = arr_len(in->tuple);
out->tuple = NULL;
- arr_set_lena(&out->tuple, ntypes, a);
+ arr_set_lena(&out->tuple, ntypes, c->allocr);
for (size_t i = 0; i < ntypes; i++) {
- copy_type(a, &out->tuple[i], &in->tuple[i]);
+ copy_type(c, &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);
+ out->arr.n_expr = allocr_malloc(c->allocr, sizeof *out->arr.n_expr);
+ copy_expr(c, out->arr.n_expr, in->arr.n_expr);
+ out->arr.of = allocr_malloc(c->allocr, sizeof *out->arr.of);
+ copy_type(c, 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);
+ out->ptr = allocr_malloc(c->allocr, sizeof *out->ptr);
+ copy_type(c, out->ptr, in->ptr);
break;
case TYPE_SLICE:
- out->ptr = allocr_malloc(a, sizeof *out->slice);
- copy_type(a, out->slice, in->slice);
+ out->ptr = allocr_malloc(c->allocr, sizeof *out->slice);
+ copy_type(c, out->slice, in->slice);
break;
case TYPE_STRUCT: {
size_t nfields = arr_len(in->struc.fields);
out->struc.fields = NULL;
- arr_set_lena(&out->struc.fields, nfields, a);
+ arr_set_lena(&out->struc.fields, nfields, c->allocr);
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);
+ copy_type(c, fout->type, fin->type);
}
} break;
}
}
-static void copy_fn_expr(Allocator *a, FnExpr *fout, FnExpr *fin, bool copy_body) {
+static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) {
+ *fout = *fin;
size_t i;
size_t nparam_decls = arr_len(fin->params);
fout->params = NULL;
- arr_set_lena(&fout->params, nparam_decls, a);
+ arr_set_lena(&fout->params, nparam_decls, c->allocr);
for (i = 0; i < nparam_decls; i++)
- copy_decl(a, fout->params + i, fin->params + i);
+ copy_decl(c, fout->params + i, fin->params + i);
size_t nret_decls = arr_len(fin->ret_decls);
- fout->ret_decls = NULL;
- arr_set_lena(&fout->ret_decls, nret_decls, a);
- for (i = 0; i < nret_decls; i++)
- copy_decl(a, fout->ret_decls + i, fin->ret_decls + i);
- copy_type(a, &fout->ret_type, &fin->ret_type);
+ if (fin->ret_decls) {
+ fout->ret_decls = NULL;
+ arr_set_lena(&fout->ret_decls, nret_decls, c->allocr);
+ for (i = 0; i < nret_decls; i++)
+ 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(a, &fout->body, &fin->body);
+ copy_block(c, &fout->body, &fin->body);
}
-static void copy_expr(Allocator *a, Expression *out, Expression *in) {
+static void copy_expr(Copier *c, Expression *out, Expression *in) {
+ Allocator *a = c->allocr;
*out = *in;
switch (in->kind) {
case EXPR_LITERAL_FLOAT:
@@ -118,99 +127,99 @@ static void copy_expr(Allocator *a, Expression *out, Expression *in) {
case EXPR_IDENT:
break;
case EXPR_UNARY_OP:
- copy_expr(a, out->unary.of = allocr_malloc(a, sizeof *out->unary.of), in->unary.of);
+ copy_expr(c, 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);
+ copy_expr(c, out->binary.lhs = allocr_malloc(a, sizeof *out->binary.lhs), in->binary.lhs);
+ copy_expr(c, 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);
+ copy_expr(c, 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);
+ copy_expr(c, iout->next_elif = allocr_malloc(a, sizeof *iout->next_elif), iin->next_elif);
+ copy_block(c, &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);
+ copy_expr(c, wout->cond = allocr_malloc(a, sizeof *wout->cond), win->cond);
+ copy_block(c, &wout->body, &win->body);
} break;
case EXPR_EACH: {
EachExpr *ein = &in->each;
EachExpr *eout = &out->each;
- copy_type(a, &eout->type, &ein->type);
+ copy_type(c, &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);
+ copy_expr(c, 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);
+ copy_expr(c, 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);
+ copy_expr(c, 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_expr(c, eout->of = allocr_malloc(a, sizeof *eout->of), ein->of);
}
- copy_block(a, &eout->body, &ein->body);
+ copy_block(c, &eout->body, &ein->body);
} break;
case EXPR_FN:
- copy_fn_expr(a, &out->fn, &in->fn, true);
+ copy_fn_expr(c, &out->fn, &in->fn, true);
break;
case EXPR_CAST: {
CastExpr *cin = &in->cast;
CastExpr *cout = &out->cast;
- copy_type(a, &cout->type, &cin->type);
- copy_expr(a, cout->expr = allocr_malloc(a, sizeof *cout->expr), cin->expr);
+ copy_type(c, &cout->type, &cin->type);
+ copy_expr(c, cout->expr = allocr_malloc(a, sizeof *cout->expr), cin->expr);
} break;
case EXPR_NEW: {
NewExpr *nin = &in->new;
NewExpr *nout = &out->new;
- copy_type(a, &nout->type, &nin->type);
- if (nin->n) copy_expr(a, nout->n = allocr_malloc(a, sizeof *nout->n), nin->n);
+ copy_type(c, &nout->type, &nin->type);
+ if (nin->n) copy_expr(c, nout->n = allocr_malloc(a, sizeof *nout->n), nin->n);
} break;
case EXPR_CALL: {
CallExpr *cin = &in->call;
CallExpr *cout = &out->call;
- copy_expr(a, cout->fn = allocr_malloc(a, sizeof *cout->fn), cin->fn);
+ copy_expr(c, cout->fn = allocr_malloc(a, sizeof *cout->fn), cin->fn);
size_t nargs = arr_len(cin->arg_exprs);
cout->arg_exprs = NULL;
arr_set_lena(&cout->arg_exprs, nargs, a);
for (size_t i = 0; i < nargs; i++) {
- copy_expr(a, cout->arg_exprs + i, cin->arg_exprs + i);
+ copy_expr(c, cout->arg_exprs + i, cin->arg_exprs + i);
}
} break;
case EXPR_BLOCK:
- copy_block(a, &out->block, &in->block);
+ copy_block(c, &out->block, &in->block);
break;
case EXPR_TUPLE: {
size_t nexprs = arr_len(in->tuple);
out->tuple = NULL;
arr_set_lena(&out->tuple, nexprs, a);
for (size_t i = 0; i < nexprs; i++)
- copy_expr(a, out->tuple + i, in->tuple + i);
+ copy_expr(c, out->tuple + i, in->tuple + i);
} break;
case EXPR_C:
- copy_expr(a, out->c.code = allocr_malloc(a, sizeof *out->c.code), in->c.code);
+ copy_expr(c, out->c.code = allocr_malloc(a, sizeof *out->c.code), in->c.code);
break;
case EXPR_DSIZEOF:
- copy_expr(a, out->dsizeof.of = allocr_malloc(a, sizeof *out->dsizeof.of), in->dsizeof.of);
+ copy_expr(c, out->dsizeof.of = allocr_malloc(a, sizeof *out->dsizeof.of), in->dsizeof.of);
break;
case EXPR_DALIGNOF:
- copy_expr(a, out->dalignof.of = allocr_malloc(a, sizeof *out->dalignof.of), in->dalignof.of);
+ copy_expr(c, out->dalignof.of = allocr_malloc(a, sizeof *out->dalignof.of), in->dalignof.of);
break;
case EXPR_SLICE: {
SliceExpr *sin = &in->slice;
SliceExpr *sout = &out->slice;
- copy_expr(a, sout->of = allocr_malloc(a, sizeof *sout->of), sin->of);
+ copy_expr(c, sout->of = allocr_malloc(a, sizeof *sout->of), sin->of);
if (sin->from)
- copy_expr(a, sout->from = allocr_malloc(a, sizeof *sout->from), sin->from);
+ copy_expr(c, sout->from = allocr_malloc(a, sizeof *sout->from), sin->from);
if (sin->to)
- copy_expr(a, sout->to = allocr_malloc(a, sizeof *sout->to), sin->to);
+ copy_expr(c, sout->to = allocr_malloc(a, sizeof *sout->to), sin->to);
} break;
case EXPR_TYPE:
- copy_type(a, &out->typeval, &in->typeval);
+ copy_type(c, &out->typeval, &in->typeval);
break;
case EXPR_VAL:
copy_val(a, &out->val, &in->val, &in->type);
@@ -218,41 +227,48 @@ static void copy_expr(Allocator *a, Expression *out, Expression *in) {
}
}
-static void copy_decl(Allocator *a, Declaration *out, Declaration *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(a, &out->expr, &in->expr);
+ copy_expr(c, &out->expr, &in->expr);
if (in->flags & DECL_FOUND_VAL) {
- copy_val(a, &out->val, &in->val, &in->type);
+ copy_val(c->allocr, &out->val, &in->val, &in->type);
}
if (in->flags & DECL_ANNOTATES_TYPE)
- copy_type(a, &out->type, &in->type);
+ copy_type(c, &out->type, &in->type);
}
-static void copy_stmt(Allocator *a, Statement *out, Statement *in) {
+static void copy_stmt(Copier *c, 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);
+ copy_expr(c, &out->ret.expr, &in->ret.expr);
break;
case STMT_EXPR:
- copy_expr(a, &out->expr, &in->expr);
+ copy_expr(c, &out->expr, &in->expr);
break;
case STMT_DECL:
- copy_decl(a, &out->decl, &in->decl);
+ copy_decl(c, &out->decl, &in->decl);
break;
}
}
-static void copy_block(Allocator *a, Block *out, Block *in) {
+static void copy_block(Copier *c, Block *out, Block *in) {
*out = *in;
size_t nstmts = arr_len(in->stmts);
out->stmts = NULL;
- arr_set_lena(&out->stmts, nstmts, a);
+ out->parent = c->block;
+ c->block = out;
+ if (in->ret_expr)
+ copy_expr(c, out->ret_expr = allocr_malloc(c->allocr, sizeof *out->ret_expr), in->ret_expr);
+
+ arr_set_lena(&out->stmts, nstmts, c->allocr);
for (size_t i = 0; i < nstmts; i++) {
- copy_stmt(a, &out->stmts[i], &in->stmts[i]);
+ copy_stmt(c, &out->stmts[i], &in->stmts[i]);
}
+ c->block = out->parent;
}
diff --git a/decls_cgen.c b/decls_cgen.c
index 19eb0bc..f07b17e 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -73,11 +73,9 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
if (!cgen_fn_header(g, &d->expr.fn, d->where, 0, 0))
return false;
cgen_write(g, ";");
- cgen_nl(g);
+ fn_exit(&d->expr.fn);
}
- if (!cgen_decls_block(g, &d->expr.fn.body))
- return false;
- fn_exit(&d->expr.fn);
+ cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl);
} else if (d->flags & DECL_HAS_EXPR) {
if (d->flags & DECL_IS_CONST) {
for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
diff --git a/main.c b/main.c
index cc3c36c..b59d7ab 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
/*
TODO:
deal with typing functions with type parameters (we need to type every single instance)
-do typedefs for each instance
+don't cgen decls etc. in parameter initializers
struct parameters
don't allow while {3; 5} (once break is added)
diff --git a/test.toc b/test.toc
index 1ea719b..8adf650 100644
--- a/test.toc
+++ b/test.toc
@@ -2,17 +2,17 @@ puti @= fn(x: int) {
#C("printf(\"%ld\\n\", (long)x);
");
};
-// putf @= fn(x: float) {
- // #C("printf(\"%f\\n\", (double)x);
-// ");
-// };
+putf @= fn(x: float) {
+ #C("printf(\"%f\\n\", (double)x);
+");
+};
-// main @= fn() {
-// puti(f(17));
-// };
+main @= fn() {
+ puti(g(int));
+};
-// f @= fn(k @ int) int {
-// k
-// }; \ No newline at end of file
+g @= fn(t @ Type) int {
+ 87347 as t as int
+}; \ No newline at end of file
diff --git a/tokenizer.c b/tokenizer.c
index 342bbd7..6481cfb 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -214,7 +214,7 @@ static bool tokenize_string(Tokenizer *t, char *str) {
case '/': /* single line comment */
tokr_nextchar(t);
for (t->s++; *t->s && *t->s != '\n'; t->s++);
- if (t->s) tokr_nextchar(t); /* skip newline */
+ if (*t->s) tokr_nextchar(t); /* skip newline */
break;
case '*': { /* multi line comment */
tokr_nextchar(t);
diff --git a/types.c b/types.c
index 89587f3..c607f2f 100644
--- a/types.c
+++ b/types.c
@@ -191,7 +191,8 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
if (!(flags & TYPE_OF_FN_NO_COPY_EVEN_IF_CONST) && fn_has_any_const_params(f)) {
/* OPTIM don't copy so much */
newf = typer_malloc(tr, sizeof *newf);
- copy_fn_expr(tr->allocr, newf, f, false);
+ Copier cop = {.block = f->body.parent, .allocr = tr->allocr};
+ copy_fn_expr(&cop, newf, f, false);
f = newf;
}
@@ -607,7 +608,8 @@ static bool types_fn(Typer *tr, FnExpr *f, Type *t, Location where,
assert(t->kind == TYPE_FN);
if (instance) {
- copy_fn_expr(tr->allocr, &instance->fn, f, true);
+ Copier cop = {.allocr = tr->allocr, .block = f->body.parent};
+ copy_fn_expr(&cop, &instance->fn, f, true);
f = &instance->fn;
Value *compile_time_args = instance->val.tuple;
U64 which_are_const = compile_time_args[0].u64;
@@ -1162,11 +1164,14 @@ static bool types_expr(Typer *tr, Expression *e) {
bool instance_already_exists;
c->instance = instance_table_adda(tr->allocr, &fn->instances, table_index, &table_index_type, &instance_already_exists);
- c->instance->c.id = fn->instances.n; /* let's help cgen out and assign an ID to this */
- arr_clear(&table_index_type.tuple);
- /* type this instance */
- if (!types_fn(tr, fn, &f->type, e->where, c->instance))
- return false;
+ if (!instance_already_exists) {
+ c->instance->c.id = fn->instances.n; /* let's help cgen out and assign an ID to this */
+
+ /* type this instance */
+ if (!types_fn(tr, fn, &f->type, e->where, c->instance))
+ return false;
+ arr_clear(&table_index_type.tuple);
+ }
}
*t = *ret_type;
c->arg_exprs = new_args;
@@ -1702,7 +1707,7 @@ static bool types_stmt(Typer *tr, Statement *s) {
return false;
}
if (s->expr.type.kind == TYPE_TUPLE) {
- err_print(s->where, "Statement of a tuple is not allowed. The comma operator does not exist in toc; use a semicolon instead.");
+ err_print(s->where, "Statement of a tuple is not allowed. Use a semicolon instead of a comma here.");
return false;
}
break;