diff options
| author | WormHeamer | 2025-08-08 04:43:37 -0400 |
|---|---|---|
| committer | WormHeamer | 2025-08-08 04:43:37 -0400 |
| commit | 73bd0a21ab9b5073ea7d17fb85b3469d110dc06d (patch) | |
| tree | 274d5203fec0fafd09e7aed7d247f22775c0678b /main.c | |
| parent | 374caf13f412f5062888bc2c49b011bec884e531 (diff) | |
rework some stuff, maybe bugfix, loosen associative typechecking
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 92 |
1 files changed, 63 insertions, 29 deletions
@@ -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; |
