summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-10-18 11:19:01 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2019-10-18 11:19:01 -0400
commitea40420c8dbf784f764956926af1e3d408afc185 (patch)
tree89471f777f15f0ae8b06e6f86dd5c50282a415bc
parent9167bb6d98fbbf858b90f3ffafd1ab2aeb47ac2d (diff)
while, block exprs
-rw-r--r--cgen.c128
-rw-r--r--main.c2
-rw-r--r--out.c15
-rw-r--r--parse.c2
-rw-r--r--test.toc6
5 files changed, 101 insertions, 52 deletions
diff --git a/cgen.c b/cgen.c
index 05d8970..615a3f0 100644
--- a/cgen.c
+++ b/cgen.c
@@ -362,49 +362,6 @@ 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;
-}
-
/* 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 */
@@ -459,6 +416,12 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
case EXPR_IF:
prefix_id = to->if_.c.id;
goto prefixed;
+ case EXPR_BLOCK:
+ prefix_id = to->block_ret_id;
+ goto prefixed;
+ case EXPR_WHILE:
+ prefix_id = to->while_.c.id;
+ goto prefixed;
prefixed:
for (unsigned long i = 0; i < (unsigned long)arr_len(to->type.tuple); i++) {
cgen_write(g, "(");
@@ -495,13 +458,77 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
}
static bool cgen_expr_pre(CGenerator *g, Expression *e) {
+ IdentID id;
+ char ret_name[64];
switch (e->kind) {
case EXPR_IF:
- cgen_if_pre(g, e);
- break;
case EXPR_WHILE:
- break;
+ case EXPR_BLOCK: {
+ id = g->ident_counter++;
+
+ cgen_ident_id_to_str(ret_name, 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 */
+
+ } break;
+ default: break;
+ }
+
+ switch (e->kind) {
+ case EXPR_IF: {
+ IfExpr *curr = &e->if_;
+ curr->c.id = id;
+ 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_WHILE: {
+ WhileExpr *w = &e->while_;
+ w->c.id = id;
+ cgen_write(g, "while (");
+ if (w->cond) {
+ if (!cgen_expr(g, w->cond))
+ return false;
+ } else {
+ cgen_write(g, "true");
+ }
+ cgen_write(g, ") ");
+ if (!cgen_block(g, &w->body, ret_name))
+ return false;
+ } break;
case EXPR_BLOCK:
+ e->block_ret_id = id;
+ if (!cgen_block(g, &e->block, ret_name))
+ return false;
break;
case EXPR_CALL:
if (!cgen_expr_pre(g, e->call.fn)) return false;
@@ -641,6 +668,13 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_IF:
cgen_ident_id(g, e->if_.c.id);
break;
+ case EXPR_WHILE:
+ if (e->type.kind != TYPE_VOID)
+ cgen_ident_id(g, e->while_.c.id);
+ break;
+ case EXPR_BLOCK:
+ cgen_ident_id(g, e->block_ret_id);
+ break;
case EXPR_CALL:
cgen_write(g, "(");
if (!cgen_expr(g, e->call.fn))
@@ -699,8 +733,8 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
*/
static bool cgen_block(CGenerator *g, Block *b, const char *ret_name) {
Block *prev = g->block;
- cgen_block_enter(g, b);
cgen_write(g, "{");
+ cgen_block_enter(g, b);
cgen_nl(g);
arr_foreach(b->stmts, Statement, s)
if (!cgen_stmt(g, s))
diff --git a/main.c b/main.c
index 2b0227d..78b5560 100644
--- a/main.c
+++ b/main.c
@@ -3,8 +3,8 @@ TODO:
blocks which return tuples
new run-time type resolution
unicode variable names
-re-do cgen
make sure initializers for global variables are compile-time constants
+don't allow while {3; 5} (once break is added)
any odd number of "s for a string
modifiable strings:
s := ["sakjdfhkjh ksjdahfkjsd ahs ahdf hsdaf khsadkjfh"];
diff --git a/out.c b/out.c
index 9aceed9..5fda332 100644
--- a/out.c
+++ b/out.c
@@ -27,13 +27,13 @@ int main() {
#include <stdio.h>
;
void puti(i64 x) {
- {
+{
printf("%ld\n", (long)x);
}}
void main__(void) {
- {
+{
i64 a0_0_; i64 a0_1_; if (0) {
(a0_0_) = 3;(a0_1_) = 5;
} else {
@@ -41,3 +41,14 @@ void main__(void) {
}i64 A; i64 B; (A) = a0_0_; (B) = a0_1_;
(puti(A));
(puti(B));
+ i64 y = 0;
+ while ((y<10)) {
+ i64 a2_;
+ {
+ y = (y+1);;
+ a2_ = y;
+ }(puti(a2_));
+ };
+}}
+
+
diff --git a/parse.c b/parse.c
index d0f1684..041ce77 100644
--- a/parse.c
+++ b/parse.c
@@ -1536,7 +1536,7 @@ static void fprint_expr(FILE *out, Expression *e) {
break;
case EXPR_WHILE:
fprintf(out, "while ");
- fprint_expr(out, e->while_.cond);
+ if (e->while_.cond) fprint_expr(out, e->while_.cond);
fprint_block(out, &e->while_.body);
break;
case EXPR_CALL:
diff --git a/test.toc b/test.toc
index ea94e44..d755af5 100644
--- a/test.toc
+++ b/test.toc
@@ -9,5 +9,9 @@ main @= fn() {
// A, B := 3, 5;
puti(A);
puti(B);
- asdfas := new (int, int);
+ y:int;
+ while y < 10 {
+ puti({y = y + 1; y});
+ }
+
}; \ No newline at end of file