summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c25
-rw-r--r--decls_cgen.c28
-rw-r--r--package.c8
-rw-r--r--parse.c5
-rw-r--r--point.toc4
-rw-r--r--test.toc11
-rwxr-xr-xtests/test.sh2
7 files changed, 58 insertions, 25 deletions
diff --git a/cgen.c b/cgen.c
index c8daec9..82857b0 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1566,6 +1566,7 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where, U64 instance, Valu
if (!cgen_decl(g, d))
return false;
}
+
if (!cgen_block_enter(g, &f->body)) return false;
if (!cgen_block(g, &f->body, NULL, CGEN_BLOCK_NOENTER | CGEN_BLOCK_NOBRACES))
return false;
@@ -1728,13 +1729,14 @@ static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) {
static bool cgen_decl(CGenerator *g, Declaration *d) {
int has_expr = d->flags & DECL_HAS_EXPR;
- bool is_tuple = d->type.kind == TYPE_TUPLE;
- if ((d->flags & DECL_IS_CONST) || (g->block == NULL && g->fn == NULL)) {
+ if (cgen_fn_is_direct(g, d))
+ return true; /* dealt with in cgen_defs_ */
+ if (d->flags & DECL_FOUND_VAL) {
/* declarations where we use a value */
- for (size_t idx = 0; idx < arr_len(d->idents); ++idx) {
+ for (int idx = 0, nidents = (int)arr_len(d->idents); idx < nidents; ++idx) {
Identifier i = d->idents[idx];
- Type *type = is_tuple ? &d->type.tuple[idx] : &d->type;
- Value *val = is_tuple ? &d->val.tuple[idx] : &d->val;
+ Type *type = decl_type_at_index(d, idx);
+ Value *val = decl_val_at_index(d, idx);
if (type->kind == TYPE_TYPE) {
/*
confusingly,
@@ -1743,10 +1745,9 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
we don't need to do anything here.
*/
continue;
- } else if (type->kind == TYPE_FN && (d->flags & DECL_IS_CONST)) {
- /* don't generate function pointer declaration for constant fns */
- continue;
}
+ if (g->block == NULL && g->fn == NULL && !i->export_name)
+ cgen_write(g, "static ");
if (has_expr) {
if (!cgen_val_pre(g, *val, type, d->where))
return false;
@@ -1768,10 +1769,12 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
}
} else {
/* declarations where we use an expression */
- size_t nidents = arr_len(d->idents);
- for (size_t idx = 0; idx < nidents; ++idx) {
+ assert(g->block && !(d->flags & DECL_IS_CONST));
+ int nidents = (int)arr_len(d->idents);
+ for (int idx = 0; idx < nidents; ++idx) {
Identifier i = d->idents[idx];
- Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
+ Type *type = decl_type_at_index(d, idx);
+ if (g->block == NULL && g->fn == NULL && !i->export_name) cgen_write(g, "static ");
if (!cgen_type_pre(g, type, d->where)) return false;
cgen_write(g, " ");
cgen_ident(g, i);
diff --git a/decls_cgen.c b/decls_cgen.c
index 0809262..61840a6 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -118,9 +118,31 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
}
}
cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl);
- } else if (d->flags & DECL_HAS_EXPR) {
- if (!cgen_decls_expr(g, &d->expr))
- return false;
+ } else {
+ if (d->flags & DECL_HAS_EXPR) {
+ if (!cgen_decls_expr(g, &d->expr))
+ return false;
+ }
+ if (g->block == NULL && g->fn == NULL) {
+ for (int i = 0, n_idents = (int)arr_len(d->idents); i < n_idents; ++i) {
+ Identifier ident = d->idents[i];
+ Type *type = decl_type_at_index(d, i);
+ if (type->kind != TYPE_TYPE) {
+ if (ident->export_name)
+ cgen_write(g, "extern ");
+ else
+ cgen_write(g, "static ");
+ if (!cgen_type_pre(g, type, d->where))
+ return false;
+ cgen_write(g, " ");
+ cgen_ident(g, ident);
+ if (!cgen_type_post(g, type, d->where))
+ return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ }
+ }
}
return true;
}
diff --git a/package.c b/package.c
index 4763843..bef9a76 100644
--- a/package.c
+++ b/package.c
@@ -107,7 +107,7 @@ static void exptr_start(Exporter *ex, const char *pkg_name, size_t pkg_name_len)
export_u8(ex, toc[2]);
export_u32(ex, TOP_FMT_VERSION);
assert(ftell(ex->out) == 7L);
- export_u32(ex, 0); /* placeholder for identifier offset in file */
+ export_u64(ex, 0); /* placeholder for identifier offset in file */
export_len(ex, pkg_name_len);
export_str(ex, pkg_name, pkg_name_len);
bool has_code = code != NULL;
@@ -559,11 +559,7 @@ static bool export_struct(Exporter *ex, StructDef *s) {
static bool exptr_finish(Exporter *ex) {
long ident_offset = ftell(ex->out);
fseek(ex->out, 7L, SEEK_SET);
- if (ident_offset > U32_MAX) {
- err_print(LOCATION_NONE, "Package file is too large.");
- return false;
- }
- export_u32(ex, (U32)ident_offset);
+ export_u64(ex, (U64)ident_offset);
fseek(ex->out, 0L, SEEK_END);
diff --git a/parse.c b/parse.c
index 3b85e87..b410e66 100644
--- a/parse.c
+++ b/parse.c
@@ -1952,6 +1952,7 @@ static bool parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
}
if (p->file->pkg_name) {
tokr_err(t, "You've already set the package name.");
+ info_print(p->file->pkg_name->where, "The package name was previously set here.");
t->token = end + 1;
return false;
}
@@ -2320,7 +2321,9 @@ static inline Value *decl_val_at_index(Declaration *d, int i) {
}
static inline Type *decl_type_at_index(Declaration *d, int i) {
- return d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type;
+ Type *ret = d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type;
+ assert(ret->kind != TYPE_TUPLE);
+ return ret;
}
diff --git a/point.toc b/point.toc
index e37f37a..ede3c7c 100644
--- a/point.toc
+++ b/point.toc
@@ -4,9 +4,7 @@ pkg "point";
x, y: int;
};
-#export mk_point ::= fn(x, y: int) Point {
- p : Point;
+#export mk_point ::= fn(x, y: int) p : Point {
p.x = x;
p.y = y;
- p
};
diff --git a/test.toc b/test.toc
new file mode 100644
index 0000000..f6bac2f
--- /dev/null
+++ b/test.toc
@@ -0,0 +1,11 @@
+f ::= g();
+
+x ::= 3;
+
+g ::= fn() int { x };
+
+main ::= fn() {
+ #C("printf(\"%ld\\n\", (long)x)");
+ a := g();
+ #C("printf(\"%ld\\n\", (long)a)");
+}; \ No newline at end of file
diff --git a/tests/test.sh b/tests/test.sh
index d0fc3cb..0ac4e1a 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -13,7 +13,7 @@ compile() {
}
do_tests() {
- valgrind -q --exit-on-first-error=yes --error-exitcode=1 $TOC "$DIR/$1/$1.toc" -o "$DIR/$1/$1.c" >/dev/null || exit 1
+ valgrind -q --exit-on-first-error=yes --error-exitcode=1 $TOC "$DIR/$1/$1.toc" -o "$DIR/$1/$1.c" >/dev/null || exit 1
for CC in $COMPILERS; do
for EXTRA_CFLAGS in "-O0 -g" "-O3 -s"; do