aboutsummaryrefslogtreecommitdiff
path: root/src/program.c
blob: 3ec6f856dc3d6a14a26a7273177225da81a0d160 (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
#include "../include/program.h"
#include "../include/bytecode.h"
#include <stdio.h>
#include <assert.h>

void tsl_program_init(TslProgram *self) {
    tsl_buffer_init(&self->function_bytecode_list);
    tsl_hash_map_init(&self->variables);
    self->stack_index = 0;
}

void tsl_program_deinit(TslProgram *self) {
    TslBytecode *bytecode_writer = tsl_buffer_begin(&self->function_bytecode_list);
    TslBytecode *bytecode_writer_end = tsl_buffer_end(&self->function_bytecode_list);
    while(bytecode_writer != bytecode_writer_end) {
        tsl_bytecode_deinit(bytecode_writer);
        ++bytecode_writer;
    }
    tsl_buffer_deinit(&self->function_bytecode_list);
    tsl_hash_map_deinit(&self->variables);
}

static uint64_t hash_string_view(const void *data, size_t size) {
    uint64_t result = 0xdec05eba;
    const uint8_t *p = data;
    while(size) {
        result = ((result << 5) + result) + *p;
        ++p;
        --size;
    }
    return result;
}

TslProgramResult tsl_program_run(TslProgram *self) {
    #define push(value, type_enum, value_field)                                 \
        do {                                                                    \
            if(self->stack_index == TSL_STACK_MAX_SIZE)                         \
                return TSL_PROGRAM_RESULT_ERR;                                  \
            self->stack_values[self->stack_index].data.value_field = (value);   \
            self->stack_values[self->stack_index].type = (type_enum);           \
            ++self->stack_index;                                                \
        } while(0)

    TslBytecode *file_scope_bytecode = tsl_buffer_begin(&self->function_bytecode_list);
    char *instruction = tsl_buffer_begin(&file_scope_bytecode->buffer);
    char *instruction_end = tsl_buffer_end(&file_scope_bytecode->buffer);
    printf("#############################\n");
    /* TODO: Verify if these don't cause unaligned memory access on non-x86 platforms */
    while(instruction != instruction_end) {
        TslOpcode opcode = *(TslOpcode*)instruction;
        TslInstructionType1 *instruction_type1 = (TslInstructionType1*)instruction;
        TslInstructionType2 *instruction_type2 = (TslInstructionType2*)instruction;
        TslInstructionType3 *instruction_type3 = (TslInstructionType3*)instruction;
        TslInstructionType4 *instruction_type4 = (TslInstructionType4*)instruction;
        switch(opcode) {
            case TSL_OPCODE_LOADN: {
                printf("loadn %f\n", instruction_type2->value);
                push(instruction_type2->value, TSL_TYPE_NUMBER, number);
                instruction += sizeof(TslInstructionType2);
                break;
            }
            case TSL_OPCODE_LOADB: {
                printf("loadb %s\n", instruction_type3->value ? "true" : "false");
                push(instruction_type3->value, TSL_TYPE_BOOL, boolean);
                instruction += sizeof(TslInstructionType3);
                break;
            }
            case TSL_OPCODE_LOADS: {
                printf("loads \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
                instruction += sizeof(TslInstructionType4);
                break;
            }
            case TSL_OPCODE_LOADF: {
                printf("loadf %d\n", instruction_type1->value);
                instruction += sizeof(TslInstructionType1);
                break;
            }
            case TSL_OPCODE_LOADV: {
                printf("loadv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
                instruction += sizeof(TslInstructionType4);
                break;
            }
            case TSL_OPCODE_LOADNULL: {
                printf("loadnull\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_SETV: {
                TslValue stack_value;
                TslValue *value;
                printf("setv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
                assert(self->stack_index > 0);
                stack_value = self->stack_values[--self->stack_index];
                if(!tsl_hash_map_get_or_create(&self->variables, &instruction_type4->value, sizeof(TslValue), hash_string_view, (void**)&value))
                    return TSL_PROGRAM_RESULT_ERR;
                *value = stack_value;
                instruction += sizeof(TslInstructionType4);
                break;
            }
            case TSL_OPCODE_LIST: {
                printf("list %d\n", instruction_type1->value);
                instruction += sizeof(TslInstructionType1);
                break;
            }
            case TSL_OPCODE_MAP: {
                printf("map %d\n", instruction_type1->value);
                instruction += sizeof(TslInstructionType1);
                break;
            }
            case TSL_OPCODE_MINDEX: {
                printf("mindex\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_CALLF: {
                printf("callf %d\n", instruction_type1->value);
                instruction += sizeof(TslInstructionType1);
                break;
            }
            case TSL_OPCODE_ADD: {
                printf("add\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_SUB: {
                printf("sub\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_MUL: {
                printf("mul\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_DIV: {
                printf("div\n");
                instruction += sizeof(TslInstructionType5);
                break;
            }
            case TSL_OPCODE_LOADCA: {
                printf("loadca \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
                instruction += sizeof(TslInstructionType4);
                break;
            }
            case TSL_OPCODE_CALLC: {
                printf("callc %d\n", instruction_type1->value);
                instruction += sizeof(TslInstructionType1);
                break;
            }
        }
    }
    return TSL_PROGRAM_RESULT_OK;
}