From 1dd53ce54c2008e3a11a636a496853cf6f9a5d65 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 24 Jan 2020 09:11:53 +0100 Subject: Convert hash map to gc, implement more instructions and call command --- src/program.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 130 insertions(+), 32 deletions(-) (limited to 'src/program.c') diff --git a/src/program.c b/src/program.c index 3ec6f85..0a0027b 100644 --- a/src/program.c +++ b/src/program.c @@ -1,12 +1,26 @@ #include "../include/program.h" #include "../include/bytecode.h" +#include "../include/command.h" +#ifdef DEBUG +#define GC_DEBUG +#endif +#include #include #include +#include +#include + +#define return_if_error(expr) \ + { \ + if(!(expr)) { \ + result = TSL_PROGRAM_RESULT_ERR; \ + goto cleanup; \ + } \ + } void tsl_program_init(TslProgram *self) { + GC_INIT(); /* TODO: Remove this */ tsl_buffer_init(&self->function_bytecode_list); - tsl_hash_map_init(&self->variables); - self->stack_index = 0; } void tsl_program_deinit(TslProgram *self) { @@ -17,34 +31,31 @@ void tsl_program_deinit(TslProgram *self) { ++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; +static int program_output_temp(char *data, int size, void *userdata) { + (void)size; + (void)userdata; + fputs(data, stdout); + return 1; } 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) - + TslProgramResult result = TSL_PROGRAM_RESULT_OK; 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"); + + self->variables = GC_MALLOC_UNCOLLECTABLE(sizeof(TslHashMap)); + if(!self->variables) { + fprintf(stderr, "Error: Failed to allocate root object\n"); + return TSL_PROGRAM_RESULT_ERR; + } + tsl_hash_map_init(self->variables); + tsl_buffer_init(&self->stack_values); + + printf("###########################\n"); + /* TODO: Verify if these don't cause unaligned memory access on non-x86 platforms */ while(instruction != instruction_end) { TslOpcode opcode = *(TslOpcode*)instruction; @@ -54,46 +65,84 @@ TslProgramResult tsl_program_run(TslProgram *self) { TslInstructionType4 *instruction_type4 = (TslInstructionType4*)instruction; switch(opcode) { case TSL_OPCODE_LOADN: { + TslStackValue stack_value; + stack_value.data.number = instruction_type2->value; + stack_value.type = TSL_STACK_VALUE_TYPE_NUMBER; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadn %f\n", instruction_type2->value); - push(instruction_type2->value, TSL_TYPE_NUMBER, number); instruction += sizeof(TslInstructionType2); break; } case TSL_OPCODE_LOADB: { + TslStackValue stack_value; + stack_value.data.boolean = instruction_type3->value; + stack_value.type = TSL_STACK_VALUE_TYPE_BOOL; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); 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: { + #if 0 + TslString *str = GC_MALLOC(sizeof(TslString)); + char *str_data = GC_MALLOC_ATOMIC(instruction_type4->value.size + 1); + if(!str) { + fprintf(stderr, "Error: out of memory\n"); + return TSL_PROGRAM_RESULT_ERR; + } + if(!str_data) { + fprintf(stderr, "Error: out of memory\n"); + return TSL_PROGRAM_RESULT_ERR; + } + memcpy(str->data, instruction_type4->value.data, instruction_type4->value.size); + str->data[instruction_type4->value.size] = '\0'; + str->size = instruction_type4->value.size; + #endif + TslStackValue stack_value; + stack_value.data.str = instruction_type4->value; + stack_value.type = TSL_STACK_VALUE_TYPE_STRING; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loads \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data); instruction += sizeof(TslInstructionType4); break; } case TSL_OPCODE_LOADF: { + TslStackValue stack_value; + stack_value.data.integer = instruction_type1->value; + stack_value.type = TSL_STACK_VALUE_TYPE_FUNCTION; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadf %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; } case TSL_OPCODE_LOADV: { + TslStackValue stack_value; + stack_value.data.str = instruction_type4->value; + stack_value.type = TSL_STACK_VALUE_TYPE_VARIABLE; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data); instruction += sizeof(TslInstructionType4); break; } case TSL_OPCODE_LOADNULL: { + TslStackValue stack_value; + stack_value.type = TSL_STACK_VALUE_TYPE_NULL; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadnull\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_SETV: { - TslValue stack_value; - TslValue *value; + TslValue map_key; + TslValue *stack_value; + TslValue *map_value; + map_key.type = TSL_TYPE_STRING_VIEW; + map_key.data.string_view = instruction_type4->value; + stack_value = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue)); + map_value = tsl_hash_map_get_or_create(self->variables, &map_key); + return_if_error(map_value); + *map_value = *stack_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; } @@ -138,16 +187,65 @@ TslProgramResult tsl_program_run(TslProgram *self) { break; } case TSL_OPCODE_LOADCA: { + TslStackValue stack_value; + stack_value.data.str = instruction_type4->value; + stack_value.type = TSL_STACK_VALUE_TYPE_COMMAND_ARG; + return_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadca \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data); instruction += sizeof(TslInstructionType4); break; } case TSL_OPCODE_CALLC: { + TslStackValue *args_begin = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * instruction_type1->value); + TslStackValue *args_end = args_begin + instruction_type1->value; + TslStackValue *args = args_begin; + char *command_args[255]; + char temp_null_save[255]; + size_t arg_index = 0; + assert(instruction_type1->value > 0); + { + /* TODO: Support infinite amount of args */ + assert(args_end - args_begin < 255); + printf("Running command: "); + while(args != args_end) { + assert(args->type == TSL_STACK_VALUE_TYPE_COMMAND_ARG); + temp_null_save[arg_index] = args->data.str.data[args->data.str.size]; + args->data.str.data[args->data.str.size] = '\0'; + + command_args[arg_index] = args->data.str.data; + printf("%s ", command_args[arg_index]); + ++arg_index; + ++args; + } + command_args[arg_index] = NULL; + printf("\n"); + } + + tsl_command_exec(command_args, program_output_temp, NULL); + + { + args = args_begin; + arg_index = 0; + /* TODO: Support infinite amount of args */ + while(args != args_end) { + args->data.str.data[args->data.str.size] = temp_null_save[arg_index]; + ++arg_index; + ++args; + } + command_args[arg_index] = NULL; + } + printf("callc %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; } } } - return TSL_PROGRAM_RESULT_OK; + + cleanup: + assert(self->stack_values.size == 0); /* All push instructions (mostly load) haven't been handled yet. This is a bug in tsl */ + tsl_buffer_deinit(&self->stack_values); + GC_FREE(self->variables); /* Free the root object, resulting in all objects in the program being free'd */ + self->variables = NULL; + return result; } -- cgit v1.2.3