summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c89
1 files changed, 83 insertions, 6 deletions
diff --git a/main.c b/main.c
index e39c00b..6da1bf2 100644
--- a/main.c
+++ b/main.c
@@ -12,7 +12,7 @@
#include "strio.h"
#include "ir.h"
-int no_opt = 0;
+int no_opt = 1;
typedef struct {
DYNARR(Proc) procs;
@@ -35,7 +35,9 @@ Node *parse_expr(Lexer *l, Proc *p);
void parse_return(Lexer *l, Proc *p) {
lex_next(l);
- p->stop = node_new(p, N_RETURN, p->start, parse_expr(l, p));
+ Node *n = node_new(p, N_RETURN, p->ctrl, parse_expr(l, p));
+ node_add(p, n, p->stop);
+ p->ctrl = n;
}
void parse_let(Lexer *l, Proc *p) {
@@ -57,13 +59,16 @@ recurse:
void parse_stmt(Lexer *l, Proc *p);
/* TODO: return node from this! */
-void parse_block(Lexer *l, Proc *p) {
+void parse_block(Lexer *l, Proc *p, ScopeNameList *nl) {
lex_next(l);
scope_push(&p->scope, p);
while (l->tok != TOK_RBRACE) {
lex_expected_not(l, TM_EOF);
parse_stmt(l, p);
}
+ if (nl) {
+ scope_collect(&p->scope, p, nl, &p->arena);
+ }
scope_pop(&p->scope, p);
lex_expected(l, TM_RBRACE);
lex_next(l);
@@ -80,6 +85,76 @@ void parse_assign(Lexer *l, Proc *p) {
}
}
+void merge_scope(Proc *p, ScopeNameList *na, ScopeNameList *nb) {
+ for (ScopeFrame *f = p->scope.tail; f; f = f->prev) {
+ for (NameBinding *b = f->latest; b; b = b->prev) {
+ int i, j;
+ for (i = 0; i < na->len && !str_eql(na->data[i].name, b->name); i++);
+ for (j = 0; j < nb->len && !str_eql(nb->data[j].name, b->name); j++);
+ if (i >= na->len && j >= nb->len) continue; /* no change */
+ Node *phi;
+ if (i >= na->len) {
+ phi = node_new(p, N_PHI, p->ctrl, b->node, nb->data[j].node);
+ } else if (j >= na->len) {
+ phi = node_new(p, N_PHI, p->ctrl, na->data[i].node, b->node);
+ } else {
+ phi = node_new(p, N_PHI, p->ctrl, na->data[i].node, nb->data[j].node);
+ }
+ node_add(p, phi, p->keepalive);
+ node_remove(p, b->node, p->keepalive);
+ b->node = phi;
+ }
+ }
+
+ for (int i = 0; i < na->len; i++) node_remove(p, na->data[i].node, p->keepalive);
+ for (int i = 0; i < nb->len; i++) node_remove(p, nb->data[i].node, p->keepalive);
+}
+
+void parse_if(Lexer *l, Proc *p) {
+ lex_next(l);
+ Node *cond = parse_expr(l, p);
+ Node *ctrl_if = NULL, *ctrl_else = NULL;
+ Node *if_node = node_new(p, N_IF_ELSE, p->ctrl, cond);
+ if_node->val = (Value) {
+ .type = { T_TOP, T_TUPLE, NULL },
+ .tuple = {
+ .len = 2,
+ .cap = 0,
+ .data = (Value[2]) {
+ { .type = { T_CTRL, T_NONE, NULL } },
+ { .type = { T_CTRL, T_NONE, NULL } },
+ }
+ }
+ };
+ Node *if_true = node_new(p, N_PROJ, if_node);
+ Node *if_false = node_new(p, N_PROJ, if_node);
+ ScopeNameList scope_before = { 0 }, scope_true = { 0 }, scope_false = { 0 };
+ if_true->val.i = 0;
+ if_false->val.i = 1;
+ scope_collect(&p->scope, p, &scope_before, &p->arena);
+ NODE_KEEP(p, cond, {
+ p->ctrl = if_true;
+ lex_expected(l, TM_LBRACE);
+ parse_block(l, p, &scope_true);
+ ctrl_if = p->ctrl;
+ if (l->tok == TOK_ELSE) {
+ NODE_KEEP(p, ctrl_if, {
+ p->ctrl = if_false;
+ lex_expect(l, TM_LBRACE);
+ parse_block(l, p, &scope_false);
+ ctrl_else = p->ctrl;
+ });
+ }
+ });
+ if (ctrl_else) {
+ p->ctrl = node_new(p, N_REGION, ctrl_if, ctrl_else);
+ merge_scope(p, &scope_true, &scope_false);
+ } else {
+ p->ctrl = node_new(p, N_REGION, ctrl_if, if_false);
+ merge_scope(p, &scope_before, &scope_true);
+ }
+}
+
void parse_stmt(Lexer *l, Proc *p) {
/* TODO */
(void)l;
@@ -91,18 +166,20 @@ void parse_stmt(Lexer *l, Proc *p) {
parse_let(l, p);
break;
case TOK_LBRACE:
- parse_block(l, p);
+ parse_block(l, p, NULL);
break;
case TOK_IDENT:
parse_assign(l, p);
break;
+ case TOK_IF:
+ parse_if(l, p);
+ break;
default:
lex_expected(l, TM_RBRACE);
break;
}
}
-
Type parse_type(Lexer *l, Proc *proc) {
(void)proc;
Type t = { .lvl = T_BOT };
@@ -137,7 +214,7 @@ void parse_args_list(Lexer *l, Proc *proc) {
lex_expect(l, TM_IDENT | TM_COMMA);
if (l->tok == TOK_COMMA) continue;
Value v = (Value) { .type = parse_type(l, proc) };
- ZDA_PUSH(&start->val.tuple, v, &proc->arena);
+ ZDA_PUSH(&proc->arena, &start->val.tuple, v);
lex_expected(l, TM_RPAREN | TM_COMMA);
for (int j = 0; j < id; j++) {
Node *proj = node_new(proc, N_PROJ, proc->start);