summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-09 15:48:01 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-09 15:48:01 -0500
commit3c31cd066fb761f7fc1f7f98918ae96a55dedc4d (patch)
tree47c06d5f47ecd18a7a8756d0e89c159fc8fc68bc
parentcc5e08b53e724b425c9db31b3ee9ec445a394ae6 (diff)
fixed local functions
-rw-r--r--cgen.c166
-rw-r--r--decls_cgen.c94
-rw-r--r--main.c3
-rw-r--r--test.toc32
-rw-r--r--typedefs_cgen.c92
-rw-r--r--types.c25
6 files changed, 206 insertions, 206 deletions
diff --git a/cgen.c b/cgen.c
index 78b706e..9bae62d 100644
--- a/cgen.c
+++ b/cgen.c
@@ -11,6 +11,104 @@ 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_ptr(CGenerator *g, void *v, Type *t, Location where);
+static bool cgen_defs_block(CGenerator *g, Block *b);
+
+/* calls f on every sub-expression of e, and block_f on every sub-block. */
+#define cgen_recurse_subexprs(g, e, f, block_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, 0)) 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; \
+ 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; \
+ }
+
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
@@ -365,9 +463,9 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
/*
-Either set_expr or set_str should be NULL and either to_expr or to_str should be NULL
-Also, set_str and/or to_str should be NULL
-this will call cgen_expr_pre for set_expr and to_expr
+ Either set_expr or set_str should be NULL and either to_expr or to_str should be NULL
+ Also, set_str and/or to_str should be NULL
+ this will call cgen_expr_pre for set_expr and to_expr
*/
static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, Expression *to_expr,
const char *to_str) {
@@ -1476,17 +1574,17 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) {
/*
Because Value is a union, a pointer to v works as a pointer to any member.
As a result, this function is only needed for type checking.
- */
+ */
return cgen_val_ptr(g, v, t, where);
}
+
static bool cgen_decl(CGenerator *g, Declaration *d) {
int has_expr = d->flags & DECL_FLAG_HAS_EXPR;
bool is_tuple = d->type.kind == TYPE_TUPLE;
if (cgen_fn_is_direct(g, d)) {
- if (!cgen_fn(g, &d->expr.fn, d->where))
- return false;
+ /* definition already generated by cgen_defs_decl */
} else if ((d->flags & DECL_FLAG_CONST) || g->block == NULL) {
/* declarations where we use a value */
for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
@@ -1629,6 +1727,58 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
return true;
}
+static bool cgen_defs_expr(CGenerator *g, Expression *e) {
+ if (e->kind == EXPR_FN) {
+ if (!cgen_fn(g, &e->fn, e->where))
+ 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 (!cgen_fn(g, &d->expr.fn, d->where))
+ return false;
+ if (!cgen_defs_block(g, &d->expr.fn.body))
+ return false;
+ } else {
+ if (d->flags & DECL_FLAG_HAS_EXPR) {
+ if (!cgen_defs_expr(g, &d->expr))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+static bool cgen_defs_stmt(CGenerator *g, Statement *s) {
+ switch (s->kind) {
+ case STMT_DECL:
+ if (!cgen_defs_decl(g, &s->decl))
+ return false;
+ break;
+ case STMT_EXPR:
+ if (!cgen_defs_expr(g, &s->expr))
+ return false;
+ break;
+ case STMT_RET:
+ if (s->ret.flags & RET_HAS_EXPR)
+ if (!cgen_defs_expr(g, &s->ret.expr))
+ return false;
+ break;
+ }
+ return true;
+}
+
+static bool cgen_defs_block(CGenerator *g, Block *b) {
+ arr_foreach(b->stmts, Statement, s) {
+ if (!cgen_defs_stmt(g, s))
+ return false;
+ }
+ return true;
+}
+
static bool cgen_file(CGenerator *g, ParsedFile *f) {
g->block = NULL;
g->file = f;
@@ -1657,6 +1807,10 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
return false;
cgen_write(g, "/* code */\n");
cgen_write(g, "int main() {\n\tmain__();\n\treturn 0;\n}\n\n");
+ arr_foreach(f->stmts, Statement, s) {
+ if (!cgen_defs_stmt(g, s))
+ return false;
+ }
arr_foreach(f->stmts, Statement, s) {
if (!cgen_stmt(g, s))
diff --git a/decls_cgen.c b/decls_cgen.c
index ad0c552..7ac286d 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -3,72 +3,15 @@ static bool cgen_decls_block(CGenerator *g, Block *b);
static bool cgen_decls_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
- case EXPR_UNARY_OP:
- if (!cgen_decls_expr(g, e->unary.of))
- return false;
- break;
- case EXPR_BINARY_OP:
- if (!cgen_decls_expr(g, e->binary.lhs))
- return false;
-
- if (e->binary.op != BINARY_DOT)
- if (!cgen_decls_expr(g, e->binary.rhs))
- return false;
- break;
- case EXPR_CAST:
- if (!cgen_decls_expr(g, e->cast.expr))
- return false;
- break;
case EXPR_CALL:
- if (!cgen_decls_expr(g, e->call.fn))
- return false;
- arr_foreach(e->call.arg_exprs, Expression, a)
- if (!cgen_decls_expr(g, a))
- return false;
- break;
- case EXPR_BLOCK:
- if (!cgen_decls_block(g, &e->block))
- return false;
- break;
- case EXPR_IF:
- if (e->if_.cond)
- if (!cgen_decls_expr(g, e->if_.cond))
- return false;
- if (!cgen_decls_block(g, &e->if_.body))
- return false;
- if (e->if_.next_elif)
- if (!cgen_decls_expr(g, e->if_.next_elif))
- return false;
- break;
- case EXPR_WHILE:
- if (e->while_.cond)
- if (!cgen_decls_expr(g, e->while_.cond))
- return false;
- if (!cgen_decls_block(g, &e->while_.body))
- return false;
- break;
- case EXPR_EACH: {
- EachExpr *ea = &e->each;
- if (ea->flags & EACH_IS_RANGE) {
- if (!cgen_decls_expr(g, ea->range.from))
- return false;
- if (ea->range.to && !cgen_decls_expr(g, ea->range.to))
- return false;
- /* step is a value, not an expression */
- } else {
- if (!cgen_decls_expr(g, ea->of))
- return false;
+ if (e->call.fn->kind == EXPR_IDENT) {
+ IdentDecl *idecl = ident_decl(e->call.fn->ident);
+ if (idecl->kind == IDECL_DECL &&
+ idecl->decl->expr.kind == EXPR_FN) {
+ /* directly calling a function; might need to generate a copy of this function */
+ /* TODO ASDF */
+ }
}
- } break;
- case EXPR_TUPLE:
- arr_foreach(e->tuple, Expression, x)
- if (!cgen_decls_expr(g, x))
- return false;
- break;
- case EXPR_SLICE:
- if (!cgen_decls_expr(g, e->slice.of)) return false;
- if (e->slice.from && !cgen_decls_expr(g, e->slice.from)) return false;
- if (e->slice.to && !cgen_decls_expr(g, e->slice.to)) return false;
break;
case EXPR_FN:
e->fn.c.name = NULL;
@@ -78,24 +21,13 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
return false;
cgen_write(g, ";");
cgen_nl(g);
- if (!cgen_decls_block(g, &e->fn.body))
- return false;
fn_exit(&e->fn);
break;
- case EXPR_TYPE:
- case EXPR_VAL:
- case EXPR_C:
- case EXPR_DSIZEOF:
- case EXPR_DALIGNOF:
- case EXPR_NEW:
- case EXPR_IDENT:
- case EXPR_LITERAL_BOOL:
- case EXPR_LITERAL_INT:
- case EXPR_LITERAL_STR:
- case EXPR_LITERAL_CHAR:
- case EXPR_LITERAL_FLOAT:
+ default:
break;
}
+ cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block);
+
return true;
}
@@ -149,12 +81,6 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) {
static bool cgen_decls_file(CGenerator *g, ParsedFile *f) {
cgen_write(g, "/* declarations */\n");
arr_foreach(f->stmts, Statement, s) {
- /* if only (you need to recurse!) */
- /* OPTIM?? */
- if (s->kind == STMT_DECL) {
- }
- }
- arr_foreach(f->stmts, Statement, s) {
if (!cgen_decls_stmt(g, s))
return false;
}
diff --git a/main.c b/main.c
index 3c0c0b5..6c413f7 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,9 @@
/*
TODO:
compile-time arguments
+evaluate default arguments
+compile-time arguments for out parameter functions
+compile-time arguments for functions returning tuples
don't allow pointers to functions with compile-time arguments
don't allow while {3; 5} (once break is added)
any odd number of "s for a string
diff --git a/test.toc b/test.toc
index 65f9f30..ddd4c04 100644
--- a/test.toc
+++ b/test.toc
@@ -4,31 +4,13 @@ puti @= fn(x: int) {
");
};
-putf @= fn(x: float) {
- #C("printf(\"%f\\n\", (double)x);
-");
-};
-
-sum @= fn(x: []int) int {
- total := 0;
- p := &x[0];
- while p < &x[0] + x.len {
- total += *p;
- p += 1;
- }
- total
-};
-
-some_sum @= fn() int {
- foo := new(int, 10);
- each _, i := foo {
- foo[i] = i;
- }
- sum(foo)
-};
+// putf @= fn(x: float) {
+// #C("printf(\"%f\\n\", (double)x);
+// ");
+// };
main @= fn() {
- puti(some_sum());
- X @= some_sum();
- puti(X);
+ b @= fn(x: int) int { 2*x };
+ puti(b(10));
};
+
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index 8756298..46c629b 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -11,97 +11,7 @@ static bool typedefs_block(CGenerator *g, Block *b) {
}
static bool typedefs_expr(CGenerator *g, Expression *e) {
- switch (e->kind) {
- case EXPR_UNARY_OP:
- if (!typedefs_expr(g, e->unary.of))
- return false;
- break;
- case EXPR_BINARY_OP:
- if (!typedefs_expr(g, e->binary.lhs))
- return false;
-
- if (e->binary.op != BINARY_DOT)
- if (!typedefs_expr(g, e->binary.rhs))
- return false;
- break;
- case EXPR_CAST:
- if (!typedefs_expr(g, e->cast.expr))
- return false;
- break;
- case EXPR_CALL:
- if (!typedefs_expr(g, e->call.fn))
- return false;
- arr_foreach(e->call.arg_exprs, Expression, a)
- if (!typedefs_expr(g, a))
- return false;
- break;
- case EXPR_BLOCK:
- if (!typedefs_block(g, &e->block))
- return false;
- break;
- case EXPR_IF:
- if (e->if_.cond)
- if (!typedefs_expr(g, e->if_.cond))
- return false;
- if (!typedefs_block(g, &e->if_.body))
- return false;
- if (e->if_.next_elif)
- if (!typedefs_expr(g, e->if_.next_elif))
- return false;
- break;
- case EXPR_WHILE:
- if (e->while_.cond)
- if (!typedefs_expr(g, e->while_.cond))
- return false;
- if (!typedefs_block(g, &e->while_.body))
- return false;
- break;
- case EXPR_EACH: {
- EachExpr *ea = &e->each;
- if (ea->flags & EACH_IS_RANGE) {
- if (!typedefs_expr(g, ea->range.from))
- return false;
- if (ea->range.to && !typedefs_expr(g, ea->range.to))
- return false;
- /* step is a value, not an expression */
- } else {
- if (!typedefs_expr(g, ea->of))
- return false;
- }
- } break;
- case EXPR_TUPLE:
- arr_foreach(e->tuple, Expression, x)
- if (!typedefs_expr(g, x))
- return false;
- break;
- case EXPR_SLICE:
- if (!typedefs_expr(g, e->slice.of)) return false;
- if (e->slice.from && !typedefs_expr(g, e->slice.from)) return false;
- if (e->slice.to && !typedefs_expr(g, e->slice.to)) return false;
- break;
- case EXPR_FN:
- fn_enter(&e->fn, 0);
- if (!typedefs_block(g, &e->fn.body))
- return false;
- fn_exit(&e->fn);
- break;
- case EXPR_NEW:
- if (e->new.n && !typedefs_expr(g, e->new.n))
- return false;
- break;
- case EXPR_VAL:
- case EXPR_TYPE:
- 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;
- }
+ cgen_recurse_subexprs(g, e, typedefs_expr, typedefs_block);
return true;
}
diff --git a/types.c b/types.c
index a635956..f84d9a8 100644
--- a/types.c
+++ b/types.c
@@ -1042,6 +1042,31 @@ static bool types_expr(Typer *tr, Expression *e) {
}
}
}
+ if (fn_decl) {
+ /* evaluate compile-time arguments */
+ size_t i = 0;
+ arr_foreach(fn_decl->params, Declaration, param) {
+ if (param->flags & DECL_FLAG_CONST) {
+ arr_foreach(param->idents, Identifier, ident) {
+ Value arg_val;
+ if (!eval_expr(tr->evalr, &new_args[i], &arg_val)) {
+ if (tr->evalr->enabled) {
+ char *s = ident_to_str(*ident);
+ info_print(new_args[i].where, "(error occured while trying to evaluate compile-time argument, %s)", s);
+ info_print(param->where, "(%s was declared constant here)", s);
+ free(s);
+ }
+ return false;
+ }
+ new_args[i].kind = EXPR_VAL;
+ new_args[i].val = arg_val;
+ i++;
+ }
+ } else {
+ i += arr_len(param->idents);
+ }
+ }
+ }
*t = *ret_type;
c->arg_exprs = new_args;
break;