summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-12 17:49:31 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-12 17:49:31 -0500
commit1077f5a64081f98ec504aef3d93e8efeae2062cb (patch)
tree6a26ad9f288e0541df7da3804c533dee69603211
parent98fcdba9bf63ad79f40b832f3bff42f54aca6aab (diff)
compile time parameters
-rw-r--r--cgen.c121
-rw-r--r--decls_cgen.c20
-rw-r--r--main.c3
-rw-r--r--test.toc11
-rw-r--r--typedefs_cgen.c9
-rw-r--r--types.h1
6 files changed, 126 insertions, 39 deletions
diff --git a/cgen.c b/cgen.c
index 3830359..803333b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -22,7 +22,8 @@ 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(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);
@@ -892,13 +893,17 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
}
cgen_write(g, "; ");
if (is_range) {
+ if (ea->range.stepval) {
+ if (!cgen_val_pre(g, *ea->range.stepval, &ea->type, e->where))
+ return false;
+ }
if (ea->value)
cgen_ident(g, ea->value);
else
cgen_write(g, "val_");
cgen_write(g, " += ");
if (ea->range.stepval) {
- if (!cgen_val(g, ea->range.stepval, &ea->type, e->where))
+ if (!cgen_val(g, *ea->range.stepval, &ea->type, e->where))
return false;
} else {
cgen_write(g, "1");
@@ -1074,13 +1079,16 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
return false;
break;
case EXPR_VAL:
+ if (!cgen_val_pre(g, e->val, &e->type, e->where))
+ return false;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
e->val_c_id = g->ident_counter++;
cgen_write(g, " ");
cgen_ident_id(g, e->val_c_id);
if (!cgen_type_post(g, &e->type, e->where)) return false;
cgen_write(g, " = ");
- cgen_val(g, &e->val, &e->type, e->where);
+ if (!cgen_val(g, e->val, &e->type, e->where))
+ return false;
cgen_write(g, ";");
cgen_nl(g);
break;
@@ -1308,6 +1316,33 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_CALL:
if (cgen_uses_ptr(&e->type)) {
cgen_ident_id(g, e->call.c.id);
+ } else if (e->call.c.instance) {
+ assert(e->call.fn->kind == EXPR_IDENT);
+ Identifier name = e->call.fn->ident;
+ cgen_write(g, "(");
+ cgen_ident(g, name);
+ cgen_write(g, "%"PRIu32, e->call.c.instance);
+ cgen_write(g, "(");
+ FnExpr *f = &ident_decl(name)->decl->expr.fn;
+ Expression *args = e->call.arg_exprs;
+ bool first_arg = true;
+ int i = 0;
+ arr_foreach(f->params, Declaration, param) {
+ if (!(param->flags & DECL_IS_CONST)) {
+ arr_foreach(param->idents, Identifier, ident) {
+ if (!first_arg)
+ cgen_write(g, ", ");
+ first_arg = false;
+ if (!cgen_expr(g, &args[i]))
+ return false;
+ i++;
+ }
+ } else {
+ i += (int)arr_len(param->idents);
+ }
+ }
+ cgen_write(g, ")");
+ cgen_write(g, ")");
} else {
cgen_write(g, "(");
if (!cgen_expr(g, e->call.fn))
@@ -1442,20 +1477,46 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
}
}
-static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) {
+/* 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, Location where, I64 instance, Value *compile_time_args) {
+ /* see also cgen_defs_expr */
FnExpr *prev_fn = g->fn;
Block *prev_block = g->block;
fn_enter(f, 0);
- if (!cgen_fn_header(g, f, where, 0))
+ if (!cgen_fn_header(g, f, where, instance))
return false;
- cgen_write(g, " ");
g->fn = f;
- cgen_write(g, "{");
+ cgen_write(g, " {");
cgen_nl(g);
arr_foreach(f->ret_decls, Declaration, d) {
if (!cgen_decl(g, d))
return false;
}
+ if (compile_time_args) {
+ int carg_idx = 0;
+ arr_foreach(f->params, Declaration, param) {
+ if (param->flags & DECL_IS_CONST) {
+ int i = 0;
+ arr_foreach(param->idents, Identifier, ident) {
+ Type *type = param->type.kind == TYPE_TUPLE ? &param->type.tuple[i]
+ : &param->type;
+ if (!cgen_val_pre(g, compile_time_args[carg_idx], type, where))
+ return false;
+ if (!cgen_type_pre(g, type, where)) return false;
+ cgen_write(g, " const ");
+ cgen_ident(g, *ident);
+ if (!cgen_type_post(g, type, where)) return false;
+ cgen_write(g, " = ");
+ if (!cgen_val(g, compile_time_args[carg_idx], type, where))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ carg_idx++;
+ }
+ }
+ }
+
+ }
if (!cgen_block_enter(g, &f->body)) return false;
if (!cgen_block(g, &f->body, NULL, CGEN_BLOCK_NOENTER | CGEN_BLOCK_NOBRACES))
return false;
@@ -1580,13 +1641,13 @@ 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) {
- return cgen_val_ptr_pre(g, v, t, where);
+static bool 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) {
- return cgen_val_ptr(g, val_get_ptr(v, t), t, where);
+static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) {
+ return cgen_val_ptr(g, val_get_ptr(&v, t), t, where);
}
@@ -1627,7 +1688,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
}
continue;
}
- if (!cgen_val_pre(g, val, type, d->where))
+ if (!cgen_val_pre(g, *val, type, d->where))
return false;
if (g->block != NULL)
cgen_write(g, "static ");
@@ -1637,7 +1698,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (!cgen_type_post(g, type, d->where)) return false;
if (has_expr) {
cgen_write(g, " = ");
- if (!cgen_val(g, val, type, d->where))
+ if (!cgen_val(g, *val, type, d->where))
return false;
}
cgen_write(g, ";");
@@ -1740,25 +1801,33 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
static bool cgen_defs_expr(CGenerator *g, Expression *e) {
if (e->kind == EXPR_FN) {
- if (!cgen_fn(g, &e->fn, e->where))
- return false;
+ FnExpr *f = &e->fn;
+ HashTable *instances = f->c.instances;
+ if (instances) {
+ /* generate each instance */
+ ValNumPair *pairs = instances->data;
+ for (U64 i = 0; i < instances->cap; i++) {
+ if (instances->occupied[i]) {
+ /* generate this instance */
+ if (!cgen_fn(g, f, e->where, pairs[i].num, pairs[i].val.tuple))
+ return false;
+ }
+ }
+
+ } else {
+ if (!cgen_fn(g, &e->fn, e->where, 0, NULL))
+ return false;
+ }
+
}
cgen_recurse_subexprs(g, e, cgen_defs_expr, cgen_defs_block);
return true;
}
static bool cgen_defs_decl(CGenerator *g, Declaration *d) {
- if (cgen_fn_is_direct(g, d)) {
- if (!fn_has_any_const_params(&d->expr.fn))
- if (!cgen_fn(g, &d->expr.fn, d->where))
- return false;
- if (!cgen_defs_block(g, &d->expr.fn.body))
+ if (d->flags & DECL_HAS_EXPR) {
+ if (!cgen_defs_expr(g, &d->expr))
return false;
- } else {
- if (d->flags & DECL_HAS_EXPR) {
- if (!cgen_defs_expr(g, &d->expr))
- return false;
- }
}
return true;
}
@@ -1836,7 +1905,7 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
typedef Expression *ExprPtr;
arr_foreach(g->anon_fns, ExprPtr, eptr) {
Expression *e = *eptr;
- cgen_fn(g, &e->fn, e->where);
+ if (!cgen_fn(g, &e->fn, e->where, 0, NULL)) return false;
}
return true;
diff --git a/decls_cgen.c b/decls_cgen.c
index 92b0f3c..1e85883 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -4,13 +4,20 @@ static bool cgen_decls_block(CGenerator *g, Block *b);
static bool cgen_decls_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_CALL:
+ e->call.c.instance = 0;
+
+
if (e->call.fn->kind == EXPR_IDENT) {
IdentDecl *idecl = ident_decl(e->call.fn->ident);
Block *prev = g->block;
/* temporarily set g->block so that cgen_fn_is_direct works */
g->block = idecl->scope;
+
+
if (idecl->kind == IDECL_DECL &&
- cgen_fn_is_direct(g, idecl->decl)) {
+ (idecl->decl->flags & DECL_IS_CONST) &&
+ (idecl->decl->flags & DECL_HAS_EXPR) &&
+ (idecl->decl->expr.kind == EXPR_FN)) {
g->block = prev;
FnExpr *f = &idecl->decl->expr.fn;
f->c.name = idecl->decl->idents[0];
@@ -54,7 +61,8 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
cgen_nl(g);
}
arr_clear(&tuple_types);
- } /* else, there are no compile time arguments; we don't need to generate a separate declaration for this call */
+ e->call.c.instance = (U32)instance_number;
+ }
}
}
break;
@@ -99,9 +107,11 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
if (!cgen_decls_block(g, &d->expr.fn.body))
return false;
fn_exit(&d->expr.fn);
- } else if ((d->flags & DECL_HAS_EXPR) && !(d->flags & DECL_IS_CONST)) {
- if (!cgen_decls_expr(g, &d->expr))
- return false;
+ } else if (d->flags & DECL_HAS_EXPR) {
+ if (!(d->flags & DECL_IS_CONST) || (d->expr.kind == EXPR_FN)) {
+ if (!cgen_decls_expr(g, &d->expr))
+ return false;
+ }
}
return true;
}
diff --git a/main.c b/main.c
index 8e8878e..a0bfcb7 100644
--- a/main.c
+++ b/main.c
@@ -1,12 +1,13 @@
/*
TODO:
-compile-time arguments
+fix local functions
double check that val_get_ptr is being used everywhere it should be
evaluate default arguments
compile-time arguments for out parameter functions
compile-time arguments for functions returning tuples
deal with x, y @= fn(x: int, y @ int){}
don't allow pointers to functions with compile-time arguments
+struct parameters
don't allow while {3; 5} (once break is added)
any odd number of "s for a string
modifiable string literals
diff --git a/test.toc b/test.toc
index 2316a89..1a4364b 100644
--- a/test.toc
+++ b/test.toc
@@ -4,16 +4,19 @@ puti @= fn(x: int) {
");
};
-putf @= fn(x: float) {
- #C("printf(\"%f\\n\", (double)x);
-");
-};
+// putf @= fn(x: float) {
+// #C("printf(\"%f\\n\", (double)x);
+// ");
+// };
add @= fn(x: int, y @int) int {
x + y
};
main @= fn() {
+ // f @= fn(x:int,y@int) int { x+y };
+ // f(3,5);
+
add(3,10);
puti(add(3, 10));
x @= add(3, 7);
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index 49cd8ec..e882419 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -46,9 +46,12 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) {
cgen_nl(g);
}
}
- if ((d->flags & DECL_HAS_EXPR) && !(d->flags & DECL_IS_CONST))
- if (!typedefs_expr(g, &d->expr))
- return false;
+ if (d->flags & DECL_HAS_EXPR) {
+ if (!(d->flags & DECL_IS_CONST) || d->expr.kind == EXPR_FN) {
+ if (!typedefs_expr(g, &d->expr))
+ return false;
+ }
+ }
return true;
}
diff --git a/types.h b/types.h
index da06d30..3a00393 100644
--- a/types.h
+++ b/types.h
@@ -413,6 +413,7 @@ typedef struct {
};
struct {
IdentID id;
+ U32 instance; /* 0 = ordinary function, no compile time args */
} c;
} CallExpr;