summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--copy.c48
-rw-r--r--main.c1
-rw-r--r--types.c4
3 files changed, 32 insertions, 21 deletions
diff --git a/copy.c b/copy.c
index 178a1d2..07b003b 100644
--- a/copy.c
+++ b/copy.c
@@ -176,8 +176,16 @@ static inline void *copier_malloc(Copier *c, size_t n) {
return allocr_malloc(c->allocr, n);
}
-static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) {
+enum {
+ COPY_FN_EXPR_DONT_COPY_HEADER = 0x01,
+ COPY_FN_EXPR_DONT_COPY_BODY = 0x02
+};
+
+static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) {
*fout = *fin;
+ bool copy_body = (flags & COPY_FN_EXPR_DONT_COPY_BODY) == 0;
+ bool copy_header = (flags & COPY_FN_EXPR_DONT_COPY_HEADER) == 0;
+
if (fin->flags & FN_EXPR_FOREIGN) {
copy_expr(c, fout->foreign.name_expr = copier_malloc(c, sizeof *fin->foreign.name_expr), fin->foreign.name_expr);
copy_expr(c, fout->foreign.lib_expr = copier_malloc(c, sizeof *fin->foreign.lib_expr), fin->foreign.lib_expr);
@@ -192,23 +200,25 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, bool copy_body) {
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;
- arr_set_lena(&fout->params, nparam_decls, c->allocr);
- for (i = 0; i < nparam_decls; ++i)
- copy_decl(c, fout->params + i, fin->params + i);
- size_t nret_decls = arr_len(fin->ret_decls);
- 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) {
- c->block = prev;
- copy_block(c, &fout->body, &fin->body, copy_body ? COPY_BLOCK_DONT_CREATE_IDENTS : 0);
+ if (copy_header) {
+ size_t i;
+ size_t nparam_decls = arr_len(fin->params);
+ fout->params = NULL;
+ arr_set_lena(&fout->params, nparam_decls, c->allocr);
+ for (i = 0; i < nparam_decls; ++i)
+ copy_decl(c, fout->params + i, fin->params + i);
+ size_t nret_decls = arr_len(fin->ret_decls);
+ 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) {
+ c->block = prev;
+ copy_block(c, &fout->body, &fin->body, copy_body ? COPY_BLOCK_DONT_CREATE_IDENTS : 0);
+ }
}
}
}
@@ -293,7 +303,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) {
copy_block(c, &fout->body, &fin->body, COPY_BLOCK_DONT_CREATE_IDENTS);
} break;
case EXPR_FN:
- copy_fn_expr(c, out->fn = allocr_malloc(a, sizeof *out->fn), in->fn, true);
+ copy_fn_expr(c, out->fn = allocr_malloc(a, sizeof *out->fn), in->fn, 0);
break;
case EXPR_CAST: {
CastExpr *cin = &in->cast;
diff --git a/main.c b/main.c
index 9320f0e..c75618e 100644
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
/*
TODO:
variadic fns
+const varargs
make sure you can't have a variadic function pointer
#foreign variadic fns
where
diff --git a/types.c b/types.c
index 5e387dd..0466800 100644
--- a/types.c
+++ b/types.c
@@ -425,7 +425,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
bool generic = !(flags & TYPE_OF_FN_IS_INSTANCE) && fn_has_any_const_params(f);
if (generic) {
Copier cop = copier_create(tr->allocr, &f->body);
- copy_fn_expr(&cop, &fn_copy, f, false);
+ copy_fn_expr(&cop, &fn_copy, f, COPY_FN_EXPR_DONT_COPY_BODY);
f = &fn_copy;
}
size_t idx = 0;
@@ -2009,7 +2009,7 @@ static Status types_expr(Typer *tr, Expression *e) {
original_fn = fn;
fn_copy = typer_malloc(tr, sizeof *fn_copy);
Copier cop = copier_create(tr->allocr, fn->body.parent);
- copy_fn_expr(&cop, fn_copy, fn, true);
+ copy_fn_expr(&cop, fn_copy, fn, has_varargs ? COPY_FN_EXPR_DONT_COPY_HEADER : 0);
}
if (fn_type->constness) {