#include "../include/program.h" #include "../include/bytecode.h" #include #include 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; }