aboutsummaryrefslogtreecommitdiffstats
path: root/src/viz.c
blob: 8b5d4cf226b74d8ac9f746102cc22ba3d6167ef3 (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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
static const char* node_str[] = {
    [NODE_BUILTIN] = "BUILTIN",
    [NODE_NUMBER]  = "NUMBER",
    [NODE_BOOL]    = "BOOL",
    [NODE_STRING]  = "STRING",
    [NODE_SYMBOL]  = "SYMBOL",
    [NODE_TYPE]    = "TYPE",
    [NODE_DEF]     = "DEF",
    [NODE_SET]     = "SET",
    [NODE_FUN]     = "FUN",
    [NODE_BLOCK]   = "BLOCK",
    [NODE_IF]      = "IF",
};

void
viz_node(Node *node) {
    if (node == NULL) {
        return;
    }
    printf("%zu [width=2.5,shape=Mrecord,label=\"", node->id);
    printf("<top> %s -- [%4ld:%-4ld] ", node_str[node->type], node->line, node->col);
    if (node->expr_type != NULL) {
        printf("| T: ");
        sv_write(&node->expr_type->name);
    }
    switch (node->type) {
        case NODE_NUMBER: {
            printf("| Value: ");
            if (node->number.negative) {
                printf("-");
            }
            if (node->number.fractional != 0) {
                printf("%zu.%zu", node->number.integral, node->number.fractional);
            } else {
                printf("%zu", node->number.integral);
            }
            printf("\"];\n");
        } break;
        case NODE_SYMBOL:
        case NODE_TYPE:
        case NODE_STRING: {
            printf(" | Value: ");
            sv_write(&node->string);
            printf("\"];\n");
        } break;
        case NODE_BOOL: {
            printf(" | Value: ");
            if (node->boolean) {
                printf("true");
            } else {
                printf("false");
            }
            printf("\"];\n");
        } break;
        case NODE_BUILTIN: {
            printf(" | Name: %s", token_str[node->builtin.type]);
            printf(" | <args> Args: ");
            printf("\"];\n");
            size_t n_args = array_size(node->builtin.args);
            for (size_t i = 0; i < n_args; ++i) {
                viz_node(node->builtin.args[i]);
                printf("%zu:args:e->%zu:top:w;\n", node->id, node->builtin.args[i]->id);
            }
        } break;
        case NODE_DEF: {
            printf(" | Name: ");
            sv_write(&node->def.symbol->string);
            printf(" | Type: ");
            sv_write(&node->def.type->string);
            printf(" | <val> Expr: ");
            printf("\"];\n");
            viz_node(node->def.value);
            printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
        } break;
        case NODE_SET: {
            printf(" | Name: ");
            sv_write(&node->set.symbol->string);
            printf(" | <val> Expr: ");
            printf("\"];\n");
            viz_node(node->set.value);
            printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id);
        } break;
        case NODE_BLOCK: {
            printf(" | <expr> Exprs: ");
            printf("\"];\n");
            size_t n_expr = array_size(node->block.expr);
            for (size_t i = 0; i < n_expr; ++i) {
                viz_node(node->block.expr[i]);
                printf("%zu:expr:e->%zu:top:w;\n", node->id, node->block.expr[i]->id);
            }
        } break;
        case NODE_IF: {
            printf(" | <cond> Cond: ");
            printf(" | <t> ExprTrue:");
            if (node->ifexpr.expr_false != NULL) {
                printf(" | <f> ExprFalse: ");
            }
            printf("\"];\n");
            viz_node(node->ifexpr.cond);
            printf("%zu:cond:e->%zu:top:w;\n", node->id, node->ifexpr.cond->id);
            viz_node(node->ifexpr.expr_true);
            printf("%zu:t:e->%zu:top:w;\n", node->id, node->ifexpr.expr_true->id);
            if (node->ifexpr.expr_false != NULL) {
                viz_node(node->ifexpr.expr_false);
                printf("%zu:f:e->%zu:top:w;\n", node->id, node->ifexpr.expr_false->id);
            }
        } break;
        case NODE_FUN: {
            printf(" | Name: ");
            sv_write(&node->fun.name->string);
            printf(" | Type: ");
            printf("(");
            size_t n_params = array_size(node->fun.param_names);
            for (size_t i = 0; i < n_params; ++i) {
                printf(":");
                sv_write(&node->fun.param_types[i]->string);
                if (i < n_params - 1) {
                    printf(" ");
                }
            }
            printf("):");
            sv_write(&node->fun.return_type->string);
            if (n_params > 0) {
                printf(" | Parameters: (");
                for (size_t i = 0; i < n_params; ++i) {
                    sv_write(&node->fun.param_names[i]->string);
                    if (i < n_params - 1) {
                        printf(" ");
                    }
                }
                printf(")");
            }
            printf(" | <bod> Body: ");
            printf("\"];\n");
            viz_node(node->fun.body);
            printf("%zu:bod:e->%zu:top:w;\n", node->id, node->fun.body->id);
        } break;
    }
}

void
viz_ast(ParseTree *parse_tree) {
    if (parse_tree == NULL) {
        return;
    }
    printf("digraph ast {\n");
    printf("rankdir=LR;\n");
    printf("ranksep=\"0.95 equally\";\n");
    printf("nodesep=\"0.5 equally\";\n");
    printf("overlap=scale;\n");
    for (size_t i = 0; i < array_size(parse_tree->roots); ++i) {
        printf("subgraph %zu {\n", i);
        Node *root = parse_tree->roots[array_size(parse_tree->roots) - 1 - i];
        viz_node(root);
        printf("}\n");
    }
    printf("}\n");
}