summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-08-04 00:43:51 -0400
committerWormHeamer2025-08-04 00:43:51 -0400
commita5e5749e41de721c2e982f42f6ba27fc2b6d69c1 (patch)
treeb35b1934468b49384cb185a058e4a1098cb9379e /main.c
parent487e48e985c6fa6762454af661f666fbe77fcdd1 (diff)
add projection nodes, fix peephole optimization
Diffstat (limited to 'main.c')
-rw-r--r--main.c114
1 files changed, 64 insertions, 50 deletions
diff --git a/main.c b/main.c
index 1a4a6d1..f1665e5 100644
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
#include "lex.h"
#include "arena.h"
#include "dynarr.h"
+#include "strio.h"
#include "ir.h"
int no_opt = 0;
@@ -101,14 +102,53 @@ void parse_stmt(Lexer *l, Proc *p) {
}
}
+
+Type parse_type(Lexer *l, Proc *proc) {
+ (void)proc;
+ Type t = { .lvl = T_BOT };
+ if (str_eql(l->ident, S("i64"))) {
+ t.t = T_INT;
+ } else if (str_eql(l->ident, S("bool"))) {
+ t.t = T_BOOL;
+ } else {
+ lex_error(l, LE_ERROR, S("unknown type"));
+ }
+ lex_next(l);
+ return t;
+}
+
+void parse_args_list(Lexer *l, Proc *proc) {
+ Node *start = proc->start;
+ int i = 0;
+ while (l->tok != TOK_RPAREN && l->tok != TOK_EOF) {
+ lex_expect(l, TM_IDENT);
+ Str name = l->ident;
+ LexSpan pos = l->pos;
+ lex_expect(l, TM_IDENT);
+ Value v = (Value) { .type = parse_type(l, proc) };
+ ZDA_PUSH(&start->val.tuple, v, &proc->arena);
+ lex_expected(l, TM_RPAREN | TM_COMMA);
+ Node *proj = node_new(proc, N_PROJ, proc->start);
+ proj->val.type = v.type;
+ proj->val.i = i++;
+ scope_bind(&proc->scope, name, proj, pos, proc);
+ }
+ lex_expected(l, TM_RPAREN);
+ lex_next(l);
+}
+
Proc *parse_proc(Lexer *l, Unit *u) {
DA_FIT(&u->procs, u->procs.len + 1);
Proc *proc = &u->procs.data[u->procs.len++];
lex_expect(l, TM_IDENT);
proc_init(proc, l->ident);
- lex_expect(l, TM_LBRACE);
- lex_next(l);
scope_push(&proc->scope, proc);
+ lex_expect(l, TM_LPAREN | TM_LBRACE);
+ if (l->tok == TOK_LPAREN) {
+ parse_args_list(l, proc);
+ }
+ lex_expected(l, TM_LBRACE);
+ lex_next(l);
while (l->tok != TOK_RBRACE) {
lex_expected_not(l, TM_EOF);
parse_stmt(l, proc);
@@ -119,39 +159,6 @@ Proc *parse_proc(Lexer *l, Unit *u) {
return proc;
}
-int type_check(Node *n) {
- /*fprintf(stderr, "::\n");
- for (int i = 0; i < n->in.len; i++) {
- fprintf(stderr, "%d: %d/%d\n", i,
- n->in.data[i]->val.type.lvl,
- n->in.data[i]->val.type.t);
- }*/
- switch (n->type) {
- case N_OP_NEG:
- n->val.type = (Type) { .lvl = T_TOP, .t = T_INT };
- return n->in.data[0]->val.type.t == T_INT;
- case N_OP_NOT:
- n->val.type = (Type) { .lvl = T_TOP, .t = n->in.data[0]->val.type.t };
- return n->in.data[0]->val.type.t == T_INT || n->in.data[0]->val.type.t == T_BOOL;
- case N_OP_ADD: case N_OP_SUB: case N_OP_MUL: case N_OP_DIV:
- case N_OP_AND: case N_OP_OR: case N_OP_XOR:
- case N_OP_SHL: case N_OP_SHR:
- n->val.type = (Type) { .lvl = T_TOP, .t = T_INT };
- return n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT;
- case N_CMP_LES: case N_CMP_GTR:
- case N_CMP_LTE: case N_CMP_GTE:
- n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL };
- return n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT;
- case N_CMP_EQL:
- case N_CMP_NEQ:
- n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL };
- return (n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT)
- || (n->in.data[0]->val.type.t == T_BOOL && n->in.data[1]->val.type.t == T_BOOL);
- default:
- return 1;
- }
-}
-
Node *parse_term(Lexer *l, Proc *p) {
Node *node = NULL;
NodeType op_after = N_START;
@@ -166,11 +173,7 @@ Node *parse_term(Lexer *l, Proc *p) {
default: return node;
}
if (post_op == N_START) return node;
- Node *r = node_new(p, post_op, node);
- if (!type_check(r)) {
- lex_error_at(l, r->src_pos, LE_ERROR, S("type mismatch"));
- }
- return node_peephole(r, p, l);
+ return node_peephole(node_new(p, post_op, node), p, l);
}
if (l->tok == TOK_LPAREN) {
lex_next(l);
@@ -242,9 +245,6 @@ Node *parse_expr(Lexer *l, Proc *p) {
}
Node *n = node_peephole(lhs, p, l);
n->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs };
- if (!type_check(n)) {
- lex_error_at(l, n->src_pos, LE_ERROR, S("type mismatch"));
- }
return n;
}
@@ -273,8 +273,17 @@ void parse_unit(Lexer *l) {
/* graph output */
-void node_print(Node *n) {
- if (n->type == N_LIT) {
+void node_print(Node *n, Proc *p) {
+ if (n->type == N_START) {
+ Str s = S("");
+ int c = n->val.tuple.len;
+ Value *v = n->val.tuple.data;
+ for (int i = 0; i < c; i++) {
+ if (i > 0) str_cat(&s, S(", "), &p->arena);
+ str_cat(&s, type_desc(&v[i].type, &p->arena), &p->arena);
+ }
+ printf("\t%d [label=\"start(%.*s)\"]\n", n->id, (int)s.n, s.s);
+ } else if (n->type == N_LIT) {
switch (n->val.type.t) {
case T_INT:
printf("\t%d [label=\"%ld\"]\n", n->id, n->val.i);
@@ -286,6 +295,8 @@ void node_print(Node *n) {
printf("\t%d [label=\"literal %d\"]\n", n->id, n->id);
break;
}
+ } else if (n->type == N_PROJ) {
+ printf("\t%d [label=\"PROJ(%ld)\", shape=record]\n", n->id, n->val.i);
} else {
printf("\t%d [label=\"%s\", shape=record]\n", n->id, node_type_name(n->type));
}
@@ -294,21 +305,24 @@ void node_print(Node *n) {
}
n->walked = 1;
for (int i = 0; i < n->out.len; i++) {
- if (n->out.data[i]->type == N_LIT) {
- printf("\t%d -> %d [style=dashed]\n", n->id, n->out.data[i]->id);
+ Node *o = n->out.data[i];
+ if (o->type == N_LIT) {
+ printf("\t%d -> %d [style=dashed]\n", n->id, o->id);
} else {
- printf("\t%d -> %d\n", n->id, n->out.data[i]->id);
+ int j;
+ for (j = 0; j < o->in.len && o->in.data[j] != n; j++);
+ printf("\t%d -> %d [label=%d]\n", n->id, o->id, j);
}
}
for (int i = 0; i < n->out.len; i++) {
- node_print(n->out.data[i]);
+ node_print(n->out.data[i], p);
}
}
void proc_print(Proc *p) {
if (p->start) {
printf("\t\"%.*s\" -> %d\n", (int)p->name.n, p->name.s, p->start->id);
- node_print(p->start);
+ node_print(p->start, p);
if (no_opt) {
for (NameBinding *b = p->scope.free_bind; b; b = b->prev) {
uint64_t id = (uintptr_t)b->node;