summaryrefslogtreecommitdiff
path: root/type_checker.c
blob: f914c349ee926696663bfcb6b800caea865a8c6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "ast.h"
#include "scope.h"
#include <stdio.h>
#include <stdlib.h>

#define TYPE_PANIC(format, ...) {\
    fprintf(\
        stderr,\
        "ccc: type error: " format "\n" __VA_OPT__(,)\
        __VA_ARGS__);\
    exit(1);\
}

static struct scope* scope;

static void type_check_group(struct group_node* node);

static void type_check_expr(struct expr_node* node) {}

static void type_check_var_decl(struct var_decl_node* node) {}

static void type_check_return(struct return_node* node) {}

static void type_check_stmt(struct stmt_node* node) {
    switch (node->type) {
        case STMT_EMPTY:
            break;
        case STMT_EXPR:
            type_check_expr(&node->inner.expr);
            break;
        case STMT_VAR_DECL:
            type_check_var_decl(&node->inner.var_decl);
            break;
        case STMT_RETURN:
            type_check_return(&node->inner.return_);
            break;
        case STMT_GROUP:
            type_check_group(&node->inner.group);
            break;
    }
}

static void type_check_group(struct group_node* node) {
    if (node->scope->next_out != scope) TYPE_PANIC("scopes are borked");
    scope = node->scope;
    struct stmt_node* stmt = node->head;
    while (stmt != NULL) {
        type_check_stmt(stmt);
        stmt = stmt->next;
    }
}

static void type_check_fn_decl(struct fn_decl_node* node) {
    scope = node->scope;
    type_check_group(&node->body);
}

static void type_check_root(struct root_node* node) {
    switch (node->type) {
        case ROOT_FN_DECL:
            type_check_fn_decl(&node->inner.fn_decl);
            break;
    }
}

void type_check(struct ast* ast) {
    scope = ast->root_scope;

    struct root_node* node = ast->root_node;
    while (node != NULL) {
        type_check_root(node);
        node = node->next;
    }
}