summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-30 18:30:50 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-30 18:30:50 -0500
commite8cd3b66a9bf20e5a68147a9882685299d40f495 (patch)
treef3ab0c59626ddc2dc2b6f10d4580bfd5a65872ff
parent469ed2a877aeadc5286e08fcaee77ce31268495c (diff)
basic type returning
-rw-r--r--cgen.c52
-rw-r--r--decls_cgen.c30
-rw-r--r--main.c4
-rw-r--r--test.toc11
-rw-r--r--types.c2
5 files changed, 74 insertions, 25 deletions
diff --git a/cgen.c b/cgen.c
index db44b76..2e227bf 100644
--- a/cgen.c
+++ b/cgen.c
@@ -429,10 +429,60 @@ static inline void cgen_fn_instance_number(CGenerator *g, U64 instance) {
cgen_write(g, "%"PRIu64"_", instance);
}
+/* does this type have a type type in it? (e.g. [5]Type, &&Type) */
+static bool type_contains_type(Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
+ switch (t->kind) {
+ case TYPE_BUILTIN:
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ return false;
+ case TYPE_TYPE:
+ return true;
+ case TYPE_PTR:
+ return type_contains_type(t->ptr);
+ case TYPE_SLICE:
+ return type_contains_type(t->slice);
+ case TYPE_ARR:
+ return type_contains_type(t->arr.of);
+ case TYPE_FN:
+ arr_foreach(t->fn.types, Type, sub)
+ if (type_contains_type(sub))
+ return true;
+ return false;
+ case TYPE_TUPLE:
+ arr_foreach(t->tuple, Type, sub)
+ if (type_contains_type(sub))
+ return true;
+ return false;
+ case TYPE_STRUCT:
+ arr_foreach(t->struc->fields, Field, f)
+ if (type_contains_type(f->type))
+ return true;
+ return false;
+ case TYPE_EXPR: break;
+ }
+ assert(0);
+ return false;
+}
+
+/* should we generate this function? (or is it just meant for compile time) */
+static bool cgen_should_gen_fn(FnExpr *f) {
+ if (f->ret_decls) {
+ arr_foreach(f->ret_decls, Declaration, decl)
+ if (type_contains_type(&decl->type))
+ return false;
+ return true;
+ } else {
+ return !type_contains_type(&f->ret_type);
+ }
+}
+
/* 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, Location where, U64 instance, U64 which_are_const) {
bool out_param = cgen_uses_ptr(&f->ret_type);
bool any_params = false;
+ assert(cgen_should_gen_fn(f));
if (!f->c.name) /* anonymous fn */
cgen_write(g, "static ");
if (out_param) {
@@ -1478,6 +1528,8 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where, U64 instance, Valu
FnExpr *prev_fn = g->fn;
Block *prev_block = g->block;
U64 which_are_const = compile_time_args ? compile_time_args->u64 : 0;
+ if (!cgen_should_gen_fn(f))
+ return true;
fn_enter(f, 0);
if (!cgen_fn_header(g, f, where, instance, which_are_const))
return false;
diff --git a/decls_cgen.c b/decls_cgen.c
index 35ef2b5..593bf5d 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -5,6 +5,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d);
static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) {
assert(e->kind == EXPR_FN);
FnExpr *f = &e->fn;
+ if (!cgen_should_gen_fn(f))
+ return true;
FnType *type = &e->type.fn;
assert(type->constness);
Instance **data = f->instances.data;
@@ -36,12 +38,14 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
if (!cgen_decls_fn_instances(g, e))
return false;
} else {
- fn_enter(&e->fn, 0);
- if (!cgen_fn_header(g, &e->fn, e->where, 0, 0))
- return false;
- cgen_write(g, ";");
- cgen_nl(g);
- fn_exit(&e->fn);
+ if (cgen_should_gen_fn(&e->fn)) {
+ fn_enter(&e->fn, 0);
+ if (!cgen_fn_header(g, &e->fn, e->where, 0, 0))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ fn_exit(&e->fn);
+ }
}
} break;
default:
@@ -69,12 +73,14 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
if (!cgen_decls_fn_instances(g, &d->expr))
return false;
} else {
- fn_enter(&d->expr.fn, 0);
- 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_should_gen_fn(&d->expr.fn)) {
+ fn_enter(&d->expr.fn, 0);
+ 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);
+ }
}
cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl);
} else if (d->flags & DECL_HAS_EXPR) {
diff --git a/main.c b/main.c
index e07c049..8f1b25e 100644
--- a/main.c
+++ b/main.c
@@ -1,12 +1,10 @@
/*
TODO:
-get rid of TYPE_USER
-- don't do automatic type conversion
-
functions returning Types
test ArrInt @= Arr(int);
packages
+X @= newtype(int); or something
don't allow while {3; 5} (once break is added)
any odd number of "s for a string
make sure futurely/currently-declared types are only used by pointer/slice
diff --git a/test.toc b/test.toc
index 91c14b9..75c471f 100644
--- a/test.toc
+++ b/test.toc
@@ -15,16 +15,11 @@
-t @= struct {
- A: int;
- b: int;
+f @= fn() Type {
+int
};
-f @= fn() {};
main @= fn() {
-
-u @= t;
-x : t;
- y : u = x;
+x : f();
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 2384f32..ab186d1 100644
--- a/types.c
+++ b/types.c
@@ -27,8 +27,6 @@ static bool type_eq(Type *a, Type *b) {
return true; /* allow things such as 3 + #C("5") */
assert(a->flags & TYPE_IS_RESOLVED);
assert(b->flags & TYPE_IS_RESOLVED);
-
- /* TODO: deal with was_expr */
if (a->kind != b->kind) return false;
if (b->flags & TYPE_IS_FLEXIBLE) {