summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--a.toc3
-rw-r--r--cgen.c69
-rw-r--r--decls_cgen.c65
-rw-r--r--identifiers.c3
-rw-r--r--main.c1
-rw-r--r--package.c9
-rw-r--r--sdecls_cgen.c2
-rw-r--r--test.toc10
-rw-r--r--types.h6
9 files changed, 107 insertions, 61 deletions
diff --git a/a.toc b/a.toc
index 7efdaf5..b282224 100644
--- a/a.toc
+++ b/a.toc
@@ -19,10 +19,9 @@ pkg "a";
a.data[a.len] = x;
a.len += 1;
};
-/*
+
#export arr_foreach ::= fn(t ::=, a : Arr(t), f : fn(&t)) {
each i := 0..a.len-1 {
f(&a.data[i]);
}
};
-*/ \ No newline at end of file
diff --git a/cgen.c b/cgen.c
index bbb0da9..0a6a6b8 100644
--- a/cgen.c
+++ b/cgen.c
@@ -291,6 +291,8 @@ static void cgen_ident(CGenerator *g, Identifier i) {
if (idecl && idecl->kind == IDECL_DECL && (idecl->decl->flags & DECL_EXPORT)) {
assert(g->pkg_prefix);
cgen_write(g, "%s__", g->pkg_prefix);
+ } else if (i->from_pkg) {
+ cgen_write(g, "%s__", i->from_pkg->c.prefix);
}
if (i == g->main_ident) {
/* don't conflict with C's main! */
@@ -1291,7 +1293,6 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case BINARY_DOT: {
if (type_is_builtin(&e->binary.lhs->type, BUILTIN_PKG)) {
assert(e->binary.lhs->kind == EXPR_VAL);
- cgen_write(g, "%s__", e->binary.lhs->val.pkg->c.prefix);
cgen_ident(g, e->binary.dot.pkg_ident);
handled = true;
} else {
@@ -1909,34 +1910,52 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
return true;
}
-static bool cgen_defs_expr(CGenerator *g, Expression *e) {
- if (e->kind == EXPR_FN) {
- FnExpr *f = e->fn;
- FnType *fn_type = &e->type.fn;
- bool any_const = false;
- if (fn_type->constness) {
- for (size_t i = 0; i < arr_len(fn_type->types)-1; ++i) {
- if (fn_type->constness[i] == CONSTNESS_YES)
- any_const = true;
- }
+static bool cgen_defs_fn(CGenerator *g, FnExpr *f, Type *t) {
+ if (f->c.defined) return true;
+ f->c.defined = true;
+ FnType *fn_type = &t->fn;
+ bool any_const = false;
+ if (fn_type->constness) {
+ for (size_t i = 0; i < arr_len(fn_type->types)-1; ++i) {
+ if (fn_type->constness[i] == CONSTNESS_YES)
+ any_const = true;
}
- if (fn_type->constness) {
- HashTable *instances = &f->instances;
- /* generate each instance */
- Instance **is = instances->data;
- for (U64 i = 0; i < instances->cap; ++i) {
- if (instances->occupied[i]) {
- /* generate this instance */
- if (!cgen_fn(g, &is[i]->fn, e->where, is[i]->c.id, is[i]->val.tuple))
- return false;
- }
+ }
+ if (fn_type->constness) {
+ HashTable *instances = &f->instances;
+ /* generate each instance */
+ Instance **is = instances->data;
+ for (U64 i = 0; i < instances->cap; ++i) {
+ if (instances->occupied[i]) {
+ /* generate this instance */
+ if (!cgen_fn(g, &is[i]->fn, f->where, is[i]->c.id, is[i]->val.tuple))
+ return false;
}
}
- if (!any_const) {
- if (!cgen_fn(g, e->fn, e->where, 0, NULL))
- return false;
+ }
+ if (!any_const) {
+ if (!cgen_fn(g, f, f->where, 0, NULL))
+ return false;
+ }
+ return true;
+}
+
+static bool cgen_defs_expr(CGenerator *g, Expression *e) {
+ if (e->kind == EXPR_FN) {
+ if (!cgen_defs_fn(g, e->fn, &e->type))
+ return false;
+ } else if (e->kind == EXPR_BINARY_OP) {
+ if (e->binary.op == BINARY_DOT && type_is_builtin(&e->binary.lhs->type, BUILTIN_PKG)
+ && e->type.kind == TYPE_FN) {
+ Identifier ident = e->binary.dot.pkg_ident;
+ Declaration *d = ident_decl(ident)->decl;
+ FnExpr *f = (d->flags & DECL_FOUND_VAL) ? d->val.fn : d->expr.fn;
+ if (fn_has_any_const_params(f)) {
+ /* define instances */
+ if (!cgen_defs_fn(g, f, &e->type))
+ return false;
+ }
}
-
}
cgen_recurse_subexprs(g, e, cgen_defs_expr, cgen_defs_block, cgen_defs_decl);
return true;
diff --git a/decls_cgen.c b/decls_cgen.c
index 7af527d..1545dca 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -42,7 +42,7 @@ static bool cgen_decls_type(CGenerator *g, Type *type) {
return true;
}
-static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) {
+static bool cgen_single_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) {
if (cgen_should_gen_fn(f)) {
if (!fn_enter(f, 0))
return false;
@@ -55,17 +55,16 @@ static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance,
return true;
}
-static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) {
- assert(e->kind == EXPR_FN);
- FnExpr *f = e->fn;
- assert(e->type.fn.constness);
+
+static bool cgen_decls_fn_instances(CGenerator *g, FnExpr *f, Type *type) {
+ assert(type->fn.constness);
Instance **data = f->instances.data;
for (U64 i = 0; i < f->instances.cap; ++i) {
if (f->instances.occupied[i]) {
if (cgen_should_gen_fn(&(*data)->fn)) {
(*data)->fn.c.name = f->c.name;
(*data)->fn.c.id = f->c.id;
- if (!cgen_fn_decl(g, &(*data)->fn, e->where, (*data)->c.id, (*data)->val.tuple[0].u64))
+ if (!cgen_single_fn_decl(g, &(*data)->fn, f->where, (*data)->c.id, (*data)->val.tuple[0].u64))
return false;
cgen_write(g, ";");
cgen_nl(g);
@@ -76,7 +75,22 @@ static bool cgen_decls_fn_instances(CGenerator *g, Expression *e) {
return true;
}
+static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
+ FnType *fn_type = &t->fn;
+ if (f->c.declared) return true;
+ f->c.declared = true;
+ if (fn_type->constness) {
+ if (!cgen_decls_fn_instances(g, f, t))
+ return false;
+ } else {
+ if (!cgen_single_fn_decl(g, f, f->where, 0, 0))
+ return false;
+ }
+ return true;
+}
+
static bool cgen_decls_expr(CGenerator *g, Expression *e) {
+ assert(e->flags & EXPR_FOUND_TYPE);
cgen_recurse_subexprs(g, e, cgen_decls_expr, cgen_decls_block, cgen_decls_decl);
switch (e->kind) {
case EXPR_FN: {
@@ -84,14 +98,8 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
f->c.name = NULL;
if (!f->c.id)
f->c.id = ++g->ident_counter;
- FnType *fn_type = &e->type.fn;
- if (fn_type->constness) {
- if (!cgen_decls_fn_instances(g, e))
- return false;
- } else {
- if (!cgen_fn_decl(g, e->fn, e->where, 0, 0))
- return false;
- }
+ if (!cgen_fn_decl(g, e->fn, &e->type))
+ return false;
} break;
case EXPR_TYPE: {
Type *type = &e->typeval;
@@ -107,20 +115,24 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
if (lhs_type->kind == TYPE_PTR)
lhs_type = lhs_type->ptr;
if (e->binary.op == BINARY_DOT && type_is_builtin(lhs_type, BUILTIN_PKG)) {
- assert(e->binary.lhs->kind == EXPR_VAL);
Identifier ident = e->binary.dot.pkg_ident;
IdentDecl *idecl = ident_decl(ident);
assert(idecl);
-
- if (idecl->kind == IDECL_DECL && e->type.kind == TYPE_FN) {
- Declaration *d = idecl->decl;
+ assert(idecl->kind == IDECL_DECL);
+ Declaration *d = idecl->decl;
+ if (e->type.kind == TYPE_FN) {
FnExpr *f = NULL;
if (d->flags & DECL_FOUND_VAL)
f = d->val.fn;
else if (d->expr.kind == EXPR_FN)
f = d->expr.fn;
if (f) {
- if (e->binary.lhs->type.flags & TYPE_IS_RESOLVED) { /* no declarations for templates */
+ if (fn_has_any_const_params(f)) {
+ /* declare the instances */
+ f->c.name = ident;
+ if (!cgen_fn_decl(g, f, &e->type))
+ return false;
+ } else {
bool out_param = cgen_uses_ptr(&f->ret_type);
/* extern function declaration */
cgen_write(g, "extern ");
@@ -130,7 +142,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
if (!cgen_type_pre(g, &f->ret_type, e->where))
return false;
}
- cgen_write(g, " %s__", e->binary.lhs->val.pkg->c.prefix);
+ cgen_write(g, " ");
cgen_ident(g, ident);
if (!out_param) {
if (!cgen_type_post(g, &f->ret_type, e->where))
@@ -140,15 +152,15 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
return false;
cgen_write(g, ";");
cgen_nl(g);
- break;
}
+ break;
}
}
/* extern variable declaration */
cgen_write(g, "extern ");
if (!cgen_type_pre(g, &e->type, e->where))
return false;
- cgen_write(g, " %s__", e->binary.lhs->val.pkg->c.prefix);
+ cgen_write(g, " ");
cgen_ident(g, ident);
if (!cgen_type_post(g, &e->type, e->where))
return false;
@@ -181,13 +193,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
return false;
if (cgen_fn_is_direct(g, d)) {
d->expr.fn->c.name = d->idents[0];
- if (d->expr.type.fn.constness) {
- if (!cgen_decls_fn_instances(g, &d->expr))
- return false;
- } else {
- if (!cgen_fn_decl(g, d->expr.fn, d->expr.where, 0, 0))
- return false;
- }
+ if (!cgen_fn_decl(g, d->expr.fn, &d->expr.type))
+ return false;
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/identifiers.c b/identifiers.c
index c5a4ec1..28989d9 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -169,7 +169,8 @@ static void print_ident(Identifier id) {
static void fprint_ident_reduced_charset(FILE *out, Identifier id) {
assert(id);
if (id->anonymous) {
- fprintf(out, "x___");
+ /* hack to generate unique C identifiers */
+ fprintf(out, "a%p__",(void *)id);
return;
}
for (char *s = id->text; is_ident(*s); ++s) {
diff --git a/main.c b/main.c
index 1da2fd2..5940406 100644
--- a/main.c
+++ b/main.c
@@ -19,6 +19,7 @@
/*
TODO:
packages
+clean up anywhere we used FnExpr *f, Location where
make sure (&Package).something works
---
X ::= newtype(int); or something
diff --git a/package.c b/package.c
index 6b6769e..bacd70e 100644
--- a/package.c
+++ b/package.c
@@ -753,6 +753,7 @@ static bool export_expr(Exporter *ex, Expression *e) {
} break;
case EXPR_EACH: {
EachExpr *ea = e->each;
+ possibly_static_assert(sizeof ea->flags == 1);
export_u8(ex, ea->flags);
if ((ea->flags & EACH_ANNOTATED_TYPE) || found_type)
if (!export_type(ex, &ea->type, e->where))
@@ -906,7 +907,7 @@ static void import_expr(Importer *im, Expression *e) {
if (found_type) {
ea->range.stepval = import_optional_val(im, &ea->type);
} else {
- ea->range.step = import_expr_(im);
+ ea->range.step = import_optional_expr(im);
}
} else {
ea->of = import_expr_(im);
@@ -1034,6 +1035,8 @@ static void import_stmt(Importer *im, Statement *s) {
}
static bool export_block(Exporter *ex, Block *b) {
+ possibly_static_assert(sizeof b->flags == 1);
+ export_u8(ex, b->flags);
export_location(ex, b->where);
export_len(ex, arr_len(b->stmts));
arr_foreach(b->stmts, Statement, s) {
@@ -1046,6 +1049,7 @@ static bool export_block(Exporter *ex, Block *b) {
}
static void import_block(Importer *im, Block *b) {
+ b->flags = import_u8(im);
b->where = import_location(im);
import_arr(im, &b->stmts);
arr_foreach(b->stmts, Statement, s) {
@@ -1070,7 +1074,6 @@ static bool export_fn(Exporter *ex, FnExpr *f) {
arr_foreach(f->ret_decls, Declaration, ret_decl)
if (!export_decl(ex, ret_decl))
return false;
- /* no need to export the return type */
if (!export_block(ex, &f->body))
return false;
return true;
@@ -1193,11 +1196,13 @@ static bool import_footer(Importer *im) {
fread(name, 1, name_len, im->in);
im->ident_map[id] = ident_insert(&im->pkg->idents, &name);
im->ident_map[id]->imported = true;
+ im->ident_map[id]->from_pkg = im->pkg;
}
for (i = 1; i <= im->max_ident_id; ++i) {
if (!im->ident_map[i]) {
im->ident_map[i] = ident_new_anonymous(&im->pkg->idents);
im->ident_map[i]->imported = true;
+ im->ident_map[i]->from_pkg = im->pkg;
}
}
diff --git a/sdecls_cgen.c b/sdecls_cgen.c
index dcbb121..1aa8e51 100644
--- a/sdecls_cgen.c
+++ b/sdecls_cgen.c
@@ -58,6 +58,8 @@ static bool cgen_sdecls_expr(CGenerator *g, Expression *e) {
if (e->kind == EXPR_FN) {
/* needs to go before decls_cgen.c... */
e->fn->c.id = ++g->ident_counter;
+ e->fn->c.declared = false;
+ e->fn->c.defined = false;
}
if (e->kind == EXPR_TYPE) {
if (!cgen_sdecls_type(g, &e->typeval))
diff --git a/test.toc b/test.toc
index d522bad..759f19b 100644
--- a/test.toc
+++ b/test.toc
@@ -9,8 +9,16 @@ putf ::= fn(x: float) {
arr ::= pkg "a";
-
+putptri ::= fn(x: &int) {
+ puti(*x);
+};
main ::= fn() {
x : arr.Arr(int);
+ arr.arr_add(&x, 10);
+ arr.arr_add(&x, 20);
+ arr.arr_add(&x, 80);
+ arr.arr_add(&x, 5430);
+ arr.arr_add(&x, -6546);
+ arr.arr_foreach(x, putptri);
}; \ No newline at end of file
diff --git a/types.h b/types.h
index 86a0a31..ff80575 100644
--- a/types.h
+++ b/types.h
@@ -176,6 +176,7 @@ typedef struct IdentSlot {
char *text; /* actual name of the identifier */
size_t len; /* length of name */
U64 export_id; /* 0 if there's no exported identifier here, otherwise unique positive integer associated with this identifier */
+ struct Package *from_pkg;
struct Package *pkg; /* NULL if this is not associated with a package */
IdentDecl *decls; /* array of declarations of this identifier */
} IdentSlot;
@@ -443,7 +444,7 @@ enum {
BLOCK_FOUND_TYPES = 0x02,
};
typedef struct Block {
- U16 flags;
+ U8 flags;
Location where;
struct Statement *stmts;
struct Expression *ret_expr; /* the return expression of this block, e.g. {foo(); 3} => 3 NULL for no expression. */
@@ -588,6 +589,9 @@ typedef struct FnExpr {
/* if name = NULL, this is an anonymous function, and id will be the ID of the fn. */
Identifier name;
IdentID id;
+ /* needed for imported templates atm */
+ bool declared;
+ bool defined;
} c;
} FnExpr; /* an expression such as fn(x: int) int { 2 * x } */