summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-17 12:33:19 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-17 12:33:19 -0400
commit6092b753c5ba6d5b458c38b283b0f3bc50e5393b (patch)
treede839ca48d448f03bc2f41beacb03fc45b923b4a
parent453724df34aad2bf65f3933f6677f32ec264d08f (diff)
tuples are mostly working
-rw-r--r--cgen.c67
-rw-r--r--out.c19
-rw-r--r--test.toc8
3 files changed, 66 insertions, 28 deletions
diff --git a/cgen.c b/cgen.c
index 04c7317..82fac70 100644
--- a/cgen.c
+++ b/cgen.c
@@ -5,6 +5,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
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 void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
@@ -255,7 +256,7 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
if (any_params || i > 0)
cgen_write(g, ", ");
if (!cgen_type_pre(g, x, where)) return false;
- cgen_write(g, "(*ret%lu__)", (unsigned long)i);
+ cgen_write(g, "(*ret%lu_)", (unsigned long)i);
if (!cgen_type_post(g, x, where)) return false;
}
} else {
@@ -263,7 +264,7 @@ static bool cgen_fn_header(CGenerator *g, FnExpr *f, Location where) {
cgen_write(g, ", ");
if (!cgen_type_pre(g, &f->ret_type, where))
return false;
- cgen_write(g, " (*ret__)");
+ cgen_write(g, " (*ret_)");
if (!cgen_type_post(g, &f->ret_type, where))
return false;
}
@@ -353,20 +354,24 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
}
-/* Either exprs or idents should be NULL */
+/* exprs and/or idents should be NULL. if both are NULL, *retN_ will be used. */
static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, Expression *to) {
switch (to->kind) {
case EXPR_TUPLE:
/* e.g. a, b = 3, 5; */
for (size_t i = 0; i < arr_len(to->tuple); i++) {
- char *s = NULL;
+ char *s = NULL, buf[32];
Expression *e = NULL;
if (idents)
s = cgen_ident_to_str(idents[i]);
- else
+ else if (exprs)
e = &exprs[i];
- if (!cgen_set(g, e, s, to, NULL)) return false;
- free(s);
+ else {
+ snprintf(buf, sizeof buf, "(*ret%lu_)", i);
+ s = buf;
+ }
+ if (!cgen_set(g, e, s, &to->tuple[i], NULL)) return false;
+ if (s != buf) free(s);
}
break;
case EXPR_CALL: {
@@ -386,12 +391,15 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
for (size_t i = 0; i < len; i++) {
if (any_args || i > 0)
cgen_write(g, ", ");
- cgen_write(g, "&");
if (exprs) {
+ cgen_write(g, "&");
if (!cgen_expr(g, &exprs[i]))
return false;
- } else {
+ } else if (idents) {
+ cgen_write(g, "&");
cgen_ident(g, idents[i]);
+ } else {
+ cgen_write(g, "ret%lu_", i);
}
}
cgen_writeln(g, ");");
@@ -613,7 +621,10 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where) {
cgen_ident(g, f->ret_decls[0].idents[0]);
cgen_writeln(g, ";");
}
+ } else if (f->body.ret_expr) {
+ if (!cgen_ret(g, f->body.ret_expr)) return false;
}
+
cgen_write(g, "}");
cgen_nl(g);
g->fn = prev_fn;
@@ -626,7 +637,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
if (cgen_fn_is_direct(g, d)) {
cgen_fn(g, &d->expr.fn, d->where);
} else if (d->flags & DECL_FLAG_CONST) {
- /* TODO */
+ /* TODO? */
} else {
for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
Identifier *i = &d->idents[idx];
@@ -678,6 +689,28 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
return true;
}
+static bool cgen_ret(CGenerator *g, Expression *ret) {
+ assert((g->fn->ret_type.kind == TYPE_VOID) == (ret == NULL));
+ if (!ret) {
+ cgen_write(g, "return");
+ } else if (cgen_uses_ptr(&g->fn->ret_type)) {
+ if (g->fn->ret_type.kind == TYPE_TUPLE) {
+ if (!cgen_set_tuple(g, NULL, NULL, ret))
+ return false;
+ } else {
+ if (!cgen_set(g, NULL, "*ret_", ret, NULL)) return false;
+ }
+ cgen_write(g, "return");
+ } else {
+ cgen_write(g, "return ");
+
+ if (!cgen_expr(g, ret)) return false;
+ }
+ cgen_write(g, ";");
+ cgen_nl(g);
+ return true;
+
+}
static bool cgen_stmt(CGenerator *g, Statement *s) {
switch (s->kind) {
@@ -690,18 +723,8 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
cgen_nl(g);
break;
case STMT_RET:
- if (g->fn->ret_type.kind == TYPE_VOID) {
- cgen_write(g, "return");
- } else if (cgen_uses_ptr(&g->fn->ret_type)) {
- if (!cgen_set(g, NULL, "*ret__", &s->ret.expr, NULL)) return false;
- cgen_write(g, "return");
- } else {
- cgen_write(g, "return ");
-
- if (!cgen_expr(g, &s->ret.expr)) return false;
- }
- cgen_write(g, ";");
- cgen_nl(g);
+ if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL))
+ return false;
break;
}
return true;
diff --git a/out.c b/out.c
index 5a91b99..4b7dfc7 100644
--- a/out.c
+++ b/out.c
@@ -17,7 +17,8 @@ typedef unsigned char bool;
/* declarations */
void puti(i64 x);
-void mktup(i64 a, i64 b, i64(*ret0__), i64(*ret1__));
+void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_));
+i64 asdf(void);
void main__(void);
/* code */
int main() {
@@ -27,19 +28,29 @@ int main() {
void puti(i64 x) {
{
- printf("%lu", x);
+ printf("%lu\n", x);
}}
-void mktup(i64 a, i64 b, i64(*ret0__), i64(*ret1__)) {
+void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_)) {
{
-}}
+}(*ret0_) = a;(*ret1_) = (a+b);return;
+}
+
+
+i64 asdf(void) {
+ {
+}return 7;
+}
void main__(void) {
{
i64 a; i64 b; mktup(10, 20, &a, &b);
+ (puti((asdf())));
+ (puti(a));
+ (puti(b));
}}
diff --git a/test.toc b/test.toc
index 18ecd42..0b402b4 100644
--- a/test.toc
+++ b/test.toc
@@ -1,14 +1,18 @@
puti @= fn(x: int) {
- #C("printf(\"%lu\", x)");
+ #C("printf(\"%lu\\n\", x)");
};
mktup @= fn(a: int, b: int) (int, int) {
a, a+b
};
-
+asdf @= fn() int {
+ 7
+};
main @= fn() {
a, b := mktup(10, 20);
// x := mktup;
+ puti(asdf());
+ puti(a); puti(b);
}; \ No newline at end of file