diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 82 |
1 files changed, 74 insertions, 8 deletions
@@ -11,7 +11,7 @@ #include "dynarr.h" #include "ir.h" -int no_opt = 1; +int no_opt = 0; typedef struct { DYNARR(Proc) procs; @@ -119,16 +119,58 @@ 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; if (TMASK(l->tok) & (TM_MINUS | TM_PLUS | TM_NOT)) { - switch (l->tok) { - case TOK_MINUS: op_after = N_OP_NEG; break; - case TOK_NOT: op_after = N_OP_NOT; break; - default: break; - } + Token t = l->tok; lex_next(l); + node = parse_term(l, p); + NodeType post_op = N_START; + switch (t) { + case TOK_MINUS: post_op = N_OP_NEG; break; + case TOK_NOT: post_op = N_OP_NOT; break; + 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); } if (l->tok == TOK_LPAREN) { lex_next(l); @@ -143,6 +185,9 @@ Node *parse_term(Lexer *l, Proc *p) { lex_error(l, LE_ERROR, S("undeclared identifier")); } lex_next(l); + } else if (TMASK(l->tok) & (TM_TRUE | TM_FALSE)) { + node = node_new_lit_bool(p, l->tok == TOK_TRUE); + lex_next(l); } else { lex_expected(l, TM_LIT_NUM); int64_t val = 0; @@ -167,7 +212,9 @@ Node *parse_term(Lexer *l, Proc *p) { Node *parse_expr(Lexer *l, Proc *p) { LexSpan pos = l->pos; Node *lhs = parse_term(l, p); - if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH | TM_NOT | TM_AND | TM_XOR | TM_OR | TM_SHL | TM_SHR)) { + if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH + | TM_NOT | TM_AND | TM_XOR | TM_OR | TM_SHL | TM_SHR + | TM_EQL | TM_NEQ | TM_LES | TM_GTR | TM_LTE | TM_GTE)) { Token t = l->tok; lex_next(l); Node *rhs = parse_expr(l, p); @@ -183,12 +230,21 @@ Node *parse_expr(Lexer *l, Proc *p) { case TOK_XOR: nt = N_OP_XOR; break; case TOK_SHL: nt = N_OP_SHL; break; case TOK_SHR: nt = N_OP_SHR; break; + case TOK_EQL: nt = N_CMP_EQL; break; + case TOK_NEQ: nt = N_CMP_NEQ; break; + case TOK_LES: nt = N_CMP_LES; break; + case TOK_GTR: nt = N_CMP_GTR; break; + case TOK_LTE: nt = N_CMP_LTE; break; + case TOK_GTE: nt = N_CMP_GTE; break; default: break; } lhs = node_new(p, nt, lhs, rhs); } 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; } @@ -219,7 +275,17 @@ void parse_unit(Lexer *l) { void node_print(Node *n) { if (n->type == N_LIT) { - printf("\t%d [label=\"%ld\"]\n", n->id, n->val.i); + switch (n->val.type.t) { + case T_INT: + printf("\t%d [label=\"%ld\"]\n", n->id, n->val.i); + break; + case T_BOOL: + printf("\t%d [label=\"%s\"]\n", n->id, n->val.i ? "true" : "false"); + break; + default: + printf("\t%d [label=\"literal %d\"]\n", n->id, n->id); + break; + } } else { printf("\t%d [label=\"%s\", shape=record]\n", n->id, node_type_name(n->type)); } |
