summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c82
1 files changed, 74 insertions, 8 deletions
diff --git a/main.c b/main.c
index ee759dd..f0af5e0 100644
--- a/main.c
+++ b/main.c
@@ -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));
}