summaryrefslogtreecommitdiff
path: root/uscript/us_debug.c
blob: 102ea634921797edccb53bce0547354575e8c76a (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
#include "us_debug.h"

#include <assert.h>

#include "dyn_arr.h"
#include "vm.h"

static
char *bc_names[] = {
#define BC(name) "BC_" #name,
#include "xbytecode.h"
#undef BC
};

int print_instruction(struct us_proto *proto, int idx)
{
        enum bytecode instruction = proto->bytecode[idx];
        fprintf(stderr, "%04d %-15s ", idx, bc_names[instruction]);
        switch (instruction) {
        case BC_LOAD: {
                int const_idx = proto->bytecode[idx + 1];
                char *const_str = val_to_str(proto->constants[const_idx], NULL);
                fprintf(
                        stderr,
                        "%d (%s)\n",
                        const_idx,
                        const_str
                );
                mem_free(const_str);
                return idx + 2;
        }
        case BC_LOAD_FUNC: {
                int const_idx = proto->bytecode[idx + 1];
                assert(proto->constants[const_idx].type == VAL_PROTO);
                struct us_proto *p = get_proto(proto->constants[const_idx]);
                int upvalc = p->upvalc;
                fprintf(
                        stderr,
                        "%.*s() %d\n",
                        (int)p->name->len, p->name->chars,
                        upvalc
                );
                return idx + 2 + upvalc * 2;
        }
        case BC_SMALL_INT:
        case BC_ARR:
        case BC_MAP:
        case BC_GET_UPVAL:
        case BC_SET_UPVAL:
        case BC_GET_LOCAL:
        case BC_SET_LOCAL:
        case BC_CALL: {
                fprintf(
                        stderr,
                        "%d\n",
                        proto->bytecode[idx + 1]
                );
                return idx + 2;
        }
        case BC_GET_GLOBAL:
        case BC_SET_GLOBAL: {
                u16 loc = (u16)(proto->bytecode[idx + 1] << 8) | proto->bytecode[idx + 2];
                fprintf(stderr, "%d\n", loc);
                return idx + 3;
        }
        case BC_JMP:
        case BC_FALSEY_JMP:
        case BC_LOOP: {
                u16 jmp = (u16)(proto->bytecode[idx + 1] << 8) | proto->bytecode[idx + 2];
                int dst = idx + jmp + 3;
                if (instruction == BC_LOOP) {
                        dst = idx + 3 - jmp;
                }
                fprintf(
                        stderr,
                        "-> %04d\n",
                        dst
                );
                return idx + 3;
        }
        case BC_FALSE:
        case BC_TRUE:
        case BC_NADA:
        case BC_PUSH_INDEX:
        case BC_GET_INDEX:
        case BC_SET_INDEX:
        case BC_POP:
        case BC_POP_UPVAL:
        case BC_ADD:
        case BC_SUB:
        case BC_MULT:
        case BC_DIV:
        case BC_MOD:
        case BC_GT:
        case BC_GTE:
        case BC_LT:
        case BC_LTE:
        case BC_NEG:
        case BC_NOT:
        case BC_EQL:
        case BC_NEQL:
        case BC_CONCAT:
        case BC_RET:
                putc('\n', stderr);
                return idx + 1;
        }

        // unreachable
        return idx + 1;
}

void print_func(struct us_proto *func)
{
        fprintf(stderr, "%s():\n", func->name->chars);
        for (int i = 0; i < da_len(func->bytecode);) {
                putc('\t', stderr);
                i = print_instruction(func, i);
        }
}