summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-08-08 04:43:37 -0400
committerWormHeamer2025-08-08 04:43:37 -0400
commit73bd0a21ab9b5073ea7d17fb85b3469d110dc06d (patch)
tree274d5203fec0fafd09e7aed7d247f22775c0678b /main.c
parent374caf13f412f5062888bc2c49b011bec884e531 (diff)
rework some stuff, maybe bugfix, loosen associative typechecking
Diffstat (limited to 'main.c')
-rw-r--r--main.c92
1 files changed, 63 insertions, 29 deletions
diff --git a/main.c b/main.c
index 276ea69..8bb7fda 100644
--- a/main.c
+++ b/main.c
@@ -47,9 +47,6 @@ Node *ctrl(Proc *p, Node *n) {
});
return NULL;
}
- if (p->ctrl->val.type.lvl == T_XCTRL) {
- return NULL;
- }
p->ctrl = n;
return n;
}
@@ -61,16 +58,16 @@ void parse_return(Lexer *l, Proc *p) {
n = node_new(p, N_RETURN, p->ctrl);
} else {
Node *e = parse_expr(l, p);
- if (!type_base_eql(&e->val.type, &p->ret_type)) {
+ if (!type_base_eql(&e->type, &p->ret_type)) {
lex_error_at(l, e->src_pos, LE_ERROR,
str_fmt(&p->arena, "incorrect return type (expected %S, got %S)",
type_desc(&p->ret_type, &p->arena),
- type_desc(&e->val.type, &p->arena)));
+ type_desc(&e->type, &p->arena)));
}
n = node_new(p, N_RETURN, p->ctrl, e);
}
n = node_peephole(n, p, l);
- if (n->val.type.lvl != T_XCTRL) {
+ if (n->type.lvl != T_XCTRL) {
node_add(p, n, p->stop);
}
ctrl(p, n);
@@ -121,17 +118,49 @@ void parse_assign(Lexer *l, Proc *p) {
lex_error_at(l, pos, LE_ERROR, S("undeclared identifier"));
}
Node *e = parse_expr(l, p);
- if (!type_base_eql(&e->val.type, &b->node->val.type)) {
+ if (!type_base_eql(&e->type, &b->node->type)) {
lex_error_at(l, pos, LE_ERROR,
str_fmt(&p->arena, "tried to assign value of type %S to variable of type %S",
- type_desc(&e->val.type, &p->arena),
- type_desc(&b->node->val.type, &p->arena)));
+ type_desc(&e->type, &p->arena),
+ type_desc(&b->node->type, &p->arena)));
}
scope_update(b, e, p);
}
-void merge_scope(Lexer *l, Proc *p, ScopeNameList *before, ScopeNameList *ntrue, ScopeNameList *nfalse) {
- node_add(p, p->ctrl, p->keepalive);
+/* TODO: Implement a better system for this.
+ *
+ * Something like:
+ *
+ * ScopeChangeList chg_true = {0}, chg_false = {0};
+ * scope_track_changes(&p->scope, &chg_true, p, scratch);
+ * parse_block(l, p);
+ * scope_rewind_changes(&p->scope, &chg_true, p);
+ * scope_track_changes(&p->scope, &chg_false, p, scratch);
+ * parse_block(l, p);
+ * scope_merge_changes(&p->scope, &chg_true, &chg_false, region, p);
+ *
+ * We put a flag in Scope somewhere that marks where it's tracking changes to,
+ * then have scope_update() look up the name binding being changed in the change
+ * list; if present, update value to the new node. If not, create it with
+ * orig set to the previous value of the name binding, and value to the new node.
+ * Since we're only tracking _changes_, there should be some way to make sure that
+ * newly created let-bindings after tracking starts aren't stored in the list.
+ * Maybe give NameBindings an index, note the index of the latest binding at the
+ * time scope_track_changes() is called, ignore any larger than it.
+ *
+ * Take care with making sure changes remain attached to keepalive --- rewind
+ * doesn't remove the new values, since it's just to revert temporarily.
+ *
+ * Also, probably should have a scratch arena for this sort of throwaway parsing
+ * data, instead of putting stuff in the procedure graph arena. It can be reset
+ * after each statement.
+ *
+ * Also also, switch scopes from a linked list to something a bit faster, like
+ * a simple arena-backed hash trie.
+ *
+ */
+
+void merge_scope(Lexer *l, Proc *p, Node *region, ScopeNameList *before, ScopeNameList *ntrue, ScopeNameList *nfalse) {
for (int i = 0; i < before->len; i++) {
int j, k;
ScopeName *b4 = &before->data[i];
@@ -143,21 +172,20 @@ void merge_scope(Lexer *l, Proc *p, ScopeNameList *before, ScopeNameList *ntrue,
Node *phi;
if (!no) {
if (yes->node == b4->node) continue;
- phi = node_new(p, N_PHI, p->ctrl, yes->node, b4->node);
+ phi = node_new(p, N_PHI, region, yes->node, b4->node);
} else if (!yes) {
if (no->node == b4->node) continue;
- phi = node_new(p, N_PHI, p->ctrl, b4->node, no->node);
+ phi = node_new(p, N_PHI, region, b4->node, no->node);
} else {
if (yes->node == b4->node && no->node == b4->node) continue;
- phi = node_new(p, N_PHI, p->ctrl, yes->node, no->node);
+ phi = node_new(p, N_PHI, region, yes->node, no->node);
}
- //fprintf(stderr, "phi('%.*s', %d, %d)\n", (int)b4->name.n, b4->name.s, phi->in.data[1]->id, phi->in.data[2]->id);
+ fprintf(stderr, "phi('%.*s', %d, %d)\n", (int)b4->name.n, b4->name.s, phi->in.data[1]->id, phi->in.data[2]->id);
phi = node_peephole(phi, p, l);
NameBinding *b = scope_find(&p->scope, b4->name);
assert(b);
scope_update(b, phi, p);
}
- node_remove(p, p->ctrl, p->keepalive);
}
/* TODO: find out a way to encode known relations between nodes, based on the
@@ -206,9 +234,9 @@ void parse_if(Lexer *l, Proc *p) {
node_add(p, if_false, p->keepalive);
ScopeNameList scope_before = { 0 }, scope_true = { 0 }, scope_false = { 0 };
scope_collect(&p->scope, p, &scope_before, &p->arena);
- if (cond->val.type.lvl == T_CONST) {
- if (cond->val.i) if_false->val.type.lvl = T_XCTRL;
- else if_true->val.type.lvl = T_XCTRL;
+ if (cond->type.lvl == T_CONST) {
+ if (cond->val.i) if_false->type.lvl = T_XCTRL;
+ else if_true->type.lvl = T_XCTRL;
}
ctrl(p, if_true);
//assert(if_true->in.len > 0);
@@ -233,6 +261,8 @@ void parse_if(Lexer *l, Proc *p) {
if (ctrl_else) {
//assert(ctrl_if->in.len > 0);
//assert(ctrl_else->in.len > 0);
+ assert(ctrl_if);
+ assert(ctrl_else);
region = node_new(p, N_REGION, ctrl_if, ctrl_else);
node_add_out(p, region, p->keepalive);
node_remove(p, ctrl_if, p->keepalive);
@@ -240,6 +270,8 @@ void parse_if(Lexer *l, Proc *p) {
} else {
//assert(ctrl_if->in.len > 0);
//assert(if_false->in.len > 0);
+ assert(ctrl_if);
+ assert(if_false);
region = node_new(p, N_REGION, ctrl_if, if_false);
node_add_out(p, region, p->keepalive);
node_remove(p, ctrl_if, p->keepalive);
@@ -251,12 +283,14 @@ void parse_if(Lexer *l, Proc *p) {
node_remove(p, if_false, p->keepalive);
//p->ctrl = node_peephole(node_new(p, N_REGION, if_true, if_false), p, l);
assert(p->ctrl->in.len > 0);
- merge_scope(l, p, &scope_before, &scope_true, &scope_false);
+ assert(region->in.data[0]);
+ assert(region->in.data[1]);
+ merge_scope(l, p, region, &scope_before, &scope_true, &scope_false);
scope_uncollect(&p->scope, p, &scope_true);
scope_uncollect(&p->scope, p, &scope_false);
scope_uncollect(&p->scope, p, &scope_before);
node_del_out(region, p->keepalive);
- assert(p->ctrl == region);
+ //assert(p->ctrl == region);
/* make sure we're not orphaning any phi nodes*/
if (p->ctrl->out.len < 1) {
ctrl(p, node_peephole(p->ctrl, p, l));
@@ -334,7 +368,7 @@ void parse_args_list(Lexer *l, Proc *proc) {
lex_expected(l, TM_RPAREN | TM_COMMA);
for (int j = 0; j < id; j++) {
Node *proj = node_new(proc, N_PROJ, proc->start);
- proj->val.type = v.type;
+ proj->type = v.type;
proj->val.i = i++;
ZDA_PUSH(&proc->arena, &start->val.tuple, v);
scope_bind(&proc->scope, idbuf[j].name, proj, idbuf[j].pos, proc);
@@ -498,7 +532,7 @@ void parse_unit(Lexer *l) {
void node_print(Node *n, Proc *p) {
if (n->walked) return;
- if (n->type == N_START) {
+ if (n->op == N_START) {
Str s = S("");
int c = n->val.tuple.len;
Value *v = n->val.tuple.data;
@@ -507,8 +541,8 @@ void node_print(Node *n, Proc *p) {
str_cat(&s, type_desc(&v[i].type, &p->arena), &p->arena);
}
printf("\t%d [label=\"start(%.*s)\"]", n->id, (int)s.n, s.s);
- } else if (n->type == N_LIT) {
- switch (n->val.type.t) {
+ } else if (n->op == N_LIT) {
+ switch (n->type.t) {
case T_INT:
printf("\t%d [label=\"%ld\"]", n->id, n->val.i);
break;
@@ -516,7 +550,7 @@ void node_print(Node *n, Proc *p) {
printf("\t%d [label=\"%s\"]", n->id, n->val.i ? "true" : "false");
break;
case T_NONE:
- if (n->val.type.lvl == T_XCTRL) {
+ if (n->type.lvl == T_XCTRL) {
printf("\t%d [label=\"~ctrl\"]", n->id);
break;
}
@@ -525,17 +559,17 @@ void node_print(Node *n, Proc *p) {
printf("\t%d [label=\"literal %d\"]", n->id, n->id);
break;
}
- } else if (n->type == N_PROJ) {
+ } else if (n->op == N_PROJ) {
Str d = type_desc(&n->in.data[0]->val.tuple.data[n->val.i].type, &p->arena);
printf("\t%d [label=\"%.*s(%ld)\", shape=record]", n->id, (int)d.n, d.s, n->val.i);
} else {
- printf("\t%d [label=\"%s\", shape=record]", n->id, node_type_name(n->type));
+ printf("\t%d [label=\"%s\", shape=record]", n->id, node_type_name(n->op));
}
printf("\n");
n->walked = 1;
for (int i = 0; i < n->out.len; i++) {
Node *o = n->out.data[i];
- if (o->type == N_LIT) {
+ if (o->op == N_LIT) {
printf("\t%d -> %d [style=dashed]\n", n->id, o->id);
} else {
int j;