summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-18 10:09:34 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-18 10:09:34 -0400
commit9167bb6d98fbbf858b90f3ffafd1ab2aeb47ac2d (patch)
tree765b63e5d29ab854327db67be5fd75cacd8e9efa
parent54da571f3d6600033e9f7bac3be4aeebdf20d374 (diff)
block tuple ret vals
-rw-r--r--cgen.c140
-rw-r--r--out.c42
-rw-r--r--parse.c20
-rw-r--r--test.toc21
4 files changed, 132 insertions, 91 deletions
diff --git a/cgen.c b/cgen.c
index 23bef3e..05d8970 100644
--- a/cgen.c
+++ b/cgen.c
@@ -2,7 +2,7 @@ static bool cgen_stmt(CGenerator *g, Statement *s);
static bool cgen_block(CGenerator *g, Block *b, const char *ret_name);
static bool cgen_expr_pre(CGenerator *g, Expression *e);
static bool cgen_expr(CGenerator *g, Expression *e);
-static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, Expression *to);
+static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to);
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);
@@ -352,7 +352,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
assert(set_expr);
assert(to_expr);
assert(set_expr->kind == EXPR_TUPLE);
- if (!cgen_set_tuple(g, set_expr->tuple, NULL, to_expr))
+ if (!cgen_set_tuple(g, set_expr->tuple, NULL, NULL, to_expr))
return false;
break;
case TYPE_VOID:
@@ -362,21 +362,64 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
return true;
}
+static bool cgen_if_pre(CGenerator *g, Expression *e) {
+ char ret_name[64];
+ IfExpr *curr = &e->if_;
+ curr->c.id = g->ident_counter++;
+ cgen_ident_id_to_str(ret_name, curr->c.id);
+ char *p = ret_name + strlen(ret_name);
+ if (e->type.kind != TYPE_VOID) {
+ if (e->type.kind == TYPE_TUPLE) {
+ for (unsigned long i = 0; i < arr_len(e->type.tuple); i++) {
+ sprintf(p, "%lu_", i);
+ if (!cgen_type_pre(g, &e->type.tuple[i], e->where)) return false;
+ cgen_write(g, " %s", ret_name);
+ if (!cgen_type_post(g, &e->type.tuple[i], e->where)) return false;
+ cgen_write(g, "; ");
+ }
+
+ } else {
+ cgen_type_pre(g, &e->type, e->where);
+ cgen_write(g, " %s", ret_name);
+ cgen_type_post(g, &e->type, e->where);
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ }
+ *p = 0; /* clear tuple suffixes */
+
+ while (1) {
+ if (curr->cond) {
+ cgen_write(g, "if (");
+ if (!cgen_expr(g, curr->cond))
+ return false;
+ cgen_write(g, ") ");
+ }
+ if (!cgen_block(g, &curr->body, ret_name))
+ return false;
+ if (curr->next_elif) {
+ cgen_write(g, " else ");
+ curr = &curr->next_elif->if_;
+ } else break;
+ }
+ return true;
+}
-/* 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) {
+/* one of exprs, idents, and prefix should be NULL. */
+static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, const char *prefix, Expression *to) {
+ IdentID prefix_id; /* ID of prefix for block */
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, buf[32];
+ char *s = NULL, buf[64];
Expression *e = NULL;
if (idents)
s = cgen_ident_to_str(idents[i]);
else if (exprs)
e = &exprs[i];
else {
- snprintf(buf, sizeof buf, "(*ret%lu_)", i);
+ snprintf(buf, sizeof buf, "(%s%lu_)", prefix, i);
s = buf;
}
if (!cgen_set(g, e, s, &to->tuple[i], NULL)) return false;
@@ -397,7 +440,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
/* out params */
size_t len = exprs ? arr_len(exprs) : arr_len(idents);
- for (size_t i = 0; i < len; i++) {
+ for (unsigned long i = 0; i < (unsigned long)len; i++) {
if (any_args || i > 0)
cgen_write(g, ", ");
if (exprs) {
@@ -408,12 +451,43 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
cgen_write(g, "&");
cgen_ident(g, idents[i]);
} else {
- cgen_write(g, "ret%lu_", i);
+ cgen_write(g, "&(%s%lu_)", prefix, i);
}
}
cgen_writeln(g, ");");
} break;
- default:
+ case EXPR_IF:
+ prefix_id = to->if_.c.id;
+ goto prefixed;
+ prefixed:
+ for (unsigned long i = 0; i < (unsigned long)arr_len(to->type.tuple); i++) {
+ cgen_write(g, "(");
+ if (exprs) {
+ if (!cgen_expr(g, &exprs[i]))
+ return false;
+ } else if (idents) {
+ cgen_ident(g, idents[i]);
+ } else {
+ cgen_write(g, "%s%lu_", prefix, i);
+ }
+ cgen_write(g, ") = ");
+ cgen_ident_id(g, prefix_id);
+ cgen_write(g, "%lu_", i);
+ cgen_write(g, "; ");
+ }
+ break;
+ case EXPR_IDENT:
+ case EXPR_LITERAL_INT:
+ case EXPR_LITERAL_CHAR:
+ case EXPR_LITERAL_BOOL:
+ case EXPR_LITERAL_STR:
+ case EXPR_LITERAL_FLOAT:
+ case EXPR_UNARY_OP:
+ case EXPR_BINARY_OP:
+ case EXPR_FN:
+ case EXPR_CAST:
+ case EXPR_NEW:
+ case EXPR_DIRECT:
assert(0);
return false;
}
@@ -422,34 +496,9 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
static bool cgen_expr_pre(CGenerator *g, Expression *e) {
switch (e->kind) {
- case EXPR_IF: {
- char ret_name[32];
- IfExpr *curr = &e->if_;
- curr->c.id = g->ident_counter++;
- cgen_ident_id_to_str(ret_name, curr->c.id);
- if (e->type.kind != TYPE_VOID) {
- cgen_type_pre(g, &e->type, e->where);
- cgen_write(g, " %s", ret_name);
- cgen_type_post(g, &e->type, e->where);
- cgen_write(g, ";");
- cgen_nl(g);
- }
-
- while (1) {
- if (curr->cond) {
- cgen_write(g, "if (");
- if (!cgen_expr(g, curr->cond))
- return false;
- cgen_write(g, ") ");
- }
- if (!cgen_block(g, &curr->body, ret_name))
- return false;
- if (curr->next_elif) {
- cgen_write(g, " else ");
- curr = &curr->next_elif->if_;
- } else break;
- }
- } break;
+ case EXPR_IF:
+ cgen_if_pre(g, e);
+ break;
case EXPR_WHILE:
break;
case EXPR_BLOCK:
@@ -482,8 +531,8 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
case EXPR_DIRECT:
break;
case EXPR_TUPLE:
- assert(0);
- return false;
+ arr_foreach(e->tuple, Expression, x)
+ if (!cgen_expr_pre(g, x)) return false;
}
return true;
}
@@ -658,8 +707,13 @@ static bool cgen_block(CGenerator *g, Block *b, const char *ret_name) {
return false;
if (b->ret_expr && ret_name) {
- if (!cgen_set(g, NULL, ret_name, b->ret_expr, NULL))
- return false;
+ if (b->ret_expr->type.kind == TYPE_TUPLE) {
+ if (!cgen_set_tuple(g, NULL, NULL, ret_name, b->ret_expr))
+ return false;
+ } else {
+ if (!cgen_set(g, NULL, ret_name, b->ret_expr, NULL))
+ return false;
+ }
cgen_nl(g);
}
cgen_block_exit(g, prev);
@@ -755,7 +809,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
/* TODO: global tuples */
if (g->block != NULL && (d->flags & DECL_FLAG_HAS_EXPR)) {
if (d->expr.type.kind == TYPE_TUPLE) {
- if (!cgen_set_tuple(g, NULL, d->idents, &d->expr)) return false;
+ if (!cgen_set_tuple(g, NULL, d->idents, NULL, &d->expr)) return false;
} else {
cgen_write(g, "{");
@@ -789,7 +843,7 @@ static bool cgen_ret(CGenerator *g, Expression *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))
+ if (!cgen_set_tuple(g, NULL, NULL, "*ret", ret))
return false;
} else {
if (!cgen_set(g, NULL, "*ret_", ret, NULL)) return false;
diff --git a/out.c b/out.c
index 1c3ff2c..9aceed9 100644
--- a/out.c
+++ b/out.c
@@ -17,8 +17,6 @@ typedef unsigned char bool;
/* declarations */
void puti(i64 x);
-void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_));
-i64 asdf(void);
void main__(void);
/* code */
int main() {
@@ -26,44 +24,20 @@ int main() {
return 0;
}
+#include <stdio.h>
+;
void puti(i64 x) {
{
printf("%ld\n", (long)x);
}}
-void mktup(i64 a, i64 b, i64(*ret0_), i64(*ret1_)) {
- {
-}(*ret0_) = a;(*ret1_) = (a+b);return;
-}
-
-
-i64 asdf(void) {
- {
-}return 32187318;
-}
-
-
void main__(void) {
{
- i64 a; i64 b; mktup(10, 20, &a, &b);
-
- (puti(((i64)(((u8)((asdf())))))));
- (puti(a));
- (puti(b));
- i64 a0_;
- if (5) {
- a0_ = 6;
- } else {
- a0_ = 7;
- }i64 x; {
- i64 expr__; i64 a1_;
- if (5) {
- a1_ = 6;
+ i64 a0_0_; i64 a0_1_; if (0) {
+ (a0_0_) = 3;(a0_1_) = 5;
} else {
- a1_ = 7;
- }expr__ = (5+(-a1_));x = expr__;}
- (puti(x));
-}}
-
-
+ (a0_0_) = 4;(a0_1_) = 6;
+ }i64 A; i64 B; (A) = a0_0_; (B) = a0_1_;
+ (puti(A));
+ (puti(B));
diff --git a/parse.c b/parse.c
index 2cef0c2..d0f1684 100644
--- a/parse.c
+++ b/parse.c
@@ -340,6 +340,10 @@ static bool parse_type(Parser *p, Type *type) {
while (1) {
Type *param_type = parser_arr_add(p, &type->fn.types);
if (!parse_type(p, param_type)) return false;
+ if (param_type->kind == TYPE_TUPLE) {
+ err_print(param_type->where, "Functions cannot have tuples as parameters.");
+ return false;
+ }
if (token_is_kw(t->token, KW_RPAREN))
break;
if (!token_is_kw(t->token, KW_COMMA)) {
@@ -377,6 +381,10 @@ static bool parse_type(Parser *p, Type *type) {
t->token = end + 1; /* go past ] */
type->arr.of = parser_malloc(p, sizeof *type->arr.of);
if (!parse_type(p, type->arr.of)) return false;
+ if (type->arr.of->kind == TYPE_TUPLE) {
+ err_print(type->arr.of->where, "You cannot have an array of tuples.");
+ return false;
+ }
type->flags = 0;
type->where = start->where;
break;
@@ -389,6 +397,10 @@ static bool parse_type(Parser *p, Type *type) {
while (1) {
Type *child = parser_arr_add(p, &type->tuple);
if (!parse_type(p, child)) return false;
+ if (child->kind == TYPE_TUPLE) {
+ err_print(child->where, "Tuples cannot contain tuples.");
+ return false;
+ }
if (token_is_kw(t->token, KW_RPAREN)) { /* we're done with the tuple */
t->token++; /* move past ) */
break;
@@ -408,6 +420,10 @@ static bool parse_type(Parser *p, Type *type) {
type->ptr.of = parser_malloc(p, sizeof *type->ptr.of);
t->token++; /* move past & */
if (!parse_type(p, type->ptr.of)) return false;
+ if (type->ptr.of->kind == TYPE_TUPLE) {
+ err_print(type->ptr.of->where, "You cannot have a pointer to a tuple.");
+ return false;
+ }
break;
default:
tokr_err(t, "Unrecognized type.");
@@ -923,6 +939,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
t->token++;
e->kind = EXPR_NEW;
if (!parse_type(p, &e->new.type)) return false;
+ if (e->new.type.kind == TYPE_TUPLE) {
+ err_print(e->where, "You cannot new a tuple.");
+ return false;
+ }
return true;
case KW_DEL:
op = UNARY_DEL;
diff --git a/test.toc b/test.toc
index cda73e2..ea94e44 100644
--- a/test.toc
+++ b/test.toc
@@ -1,20 +1,13 @@
+#C("#include <stdio.h>\n");
+
puti @= fn(x: int) {
#C("printf(\"%ld\\n\", (long)x)");
};
-mktup @= fn(a: int, b: int) (int, int) {
- a, a+b
-};
-
-asdf @= fn() int {
- 32187318
-};
-
main @= fn() {
- a, b := mktup(10, 20);
- // x := mktup;
- puti(asdf() as u8 as i64);
- puti(a); puti(b);
- x := 5+-if 5 { 6 } else { 7 };
- puti(x);
+ A, B := if 0 { 3, 5 } else { 4, 6 };
+ // A, B := 3, 5;
+ puti(A);
+ puti(B);
+ asdfas := new (int, int);
}; \ No newline at end of file