diff options
Diffstat (limited to 'src/program.c')
-rw-r--r-- | src/program.c | 248 |
1 files changed, 209 insertions, 39 deletions
diff --git a/src/program.c b/src/program.c index 0a0027b..dc7fe8d 100644 --- a/src/program.c +++ b/src/program.c @@ -1,6 +1,7 @@ #include "../include/program.h" #include "../include/bytecode.h" #include "../include/command.h" +#include "../include/std_gc/list.h" #ifdef DEBUG #define GC_DEBUG #endif @@ -10,7 +11,7 @@ #include <stdlib.h> #include <string.h> -#define return_if_error(expr) \ +#define cleanup_if_error(expr) \ { \ if(!(expr)) { \ result = TSL_PROGRAM_RESULT_ERR; \ @@ -18,6 +19,12 @@ } \ } +#define return_if_error(expr) \ + { \ + if(!(expr)) \ + return TSL_PROGRAM_RESULT_ERR; \ + } + void tsl_program_init(TslProgram *self) { GC_INIT(); /* TODO: Remove this */ tsl_buffer_init(&self->function_bytecode_list); @@ -40,6 +47,156 @@ static int program_output_temp(char *data, int size, void *userdata) { return 1; } +static TslProgramResult tsl_value_create_from_stack_value(TslProgram *self, TslStackValue *src, TslValue *dst) { + tsl_value_clear(dst); + switch(src->type) { + case TSL_STACK_VALUE_TYPE_NUMBER: { + dst->data.number = src->data.number; + dst->type = TSL_TYPE_NUMBER; + break; + } + case TSL_STACK_VALUE_TYPE_BOOL: { + dst->data.boolean = src->data.boolean; + dst->type = TSL_TYPE_BOOL; + break; + } + case TSL_STACK_VALUE_TYPE_STRING: { + TslString *str = GC_MALLOC_ATOMIC(sizeof(TslString)); + str->data = GC_MALLOC_ATOMIC(src->data.str.size + 1); + if(!str) { + GC_FREE(str); + GC_FREE(str->data); + fprintf(stderr, "Error: out of memory\n"); + return TSL_PROGRAM_RESULT_ERR; + } + if(!str->data) { + GC_FREE(str); + GC_FREE(str->data); + fprintf(stderr, "Error: out of memory\n"); + return TSL_PROGRAM_RESULT_ERR; + } + + memcpy(str->data, src->data.str.data, src->data.str.size); + str->data[src->data.str.size] = '\0'; + str->size = src->data.str.size; + + dst->data.string = str; + dst->type = TSL_TYPE_STRING; + break; + } + case TSL_STACK_VALUE_TYPE_FUNCTION: { + dst->data.function = src->data.integer; + dst->type = TSL_TYPE_FUNCTION; + break; + } + case TSL_STACK_VALUE_TYPE_VARIABLE: { + TslValue *var; + TslValue map_key; + map_key.type = TSL_TYPE_STRING_VIEW; + map_key.data.string_view = src->data.str; + + var = tsl_hash_map_get(self->variables, &map_key); + if(!var) { + fprintf(stderr, "Error: Trying to access a non-existing variable \"%.*s\"\n", (int)src->data.str.size, src->data.str.data); + return TSL_PROGRAM_RESULT_ERR; + } + + *dst = *var; + break; + } + case TSL_STACK_VALUE_TYPE_LIST: { + TslStackValue *items_begin = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * src->data.integer); + TslStackValue *items_end = items_begin + src->data.integer; + TslStackValue *item = items_end - 1; + TslValue *list_item; + dst->data.list = GC_MALLOC(sizeof(TslList)); + return_if_error(dst->data.list); + + tsl_list_init(dst->data.list); + return_if_error(tsl_list_set_capacity_hint(dst->data.list, sizeof(TslValue) * src->data.integer)); + dst->data.list->size = sizeof(TslValue) * src->data.integer; + list_item = tsl_list_end(dst->data.list) - sizeof(TslValue); + + while(item != items_begin - 1) { + return_if_error(tsl_value_create_from_stack_value(self, item, list_item)); + --list_item; + --item; + } + + dst->type = TSL_TYPE_LIST; + break; + } + case TSL_STACK_VALUE_TYPE_MAP: { + TslStackValue *items_begin = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * src->data.integer); + TslStackValue *items_end = items_begin + src->data.integer; + TslStackValue *item = items_end - 1; + + dst->data.map = GC_MALLOC(sizeof(TslHashMap)); + return_if_error(dst->data.map); + tsl_hash_map_init(dst->data.map); + + assert(src->data.integer % 2 == 0); + while(item != items_begin - 1) { + TslValue map_key; + TslValue map_value; + return_if_error(tsl_value_create_from_stack_value(self, item, &map_value)); + return_if_error(tsl_value_create_from_stack_value(self, item - 1, &map_key)); + return_if_error(tsl_hash_map_insert(dst->data.map, &map_key, &map_value)); + item -= 2; + } + + dst->type = TSL_TYPE_MAP; + break; + } + case TSL_STACK_VALUE_TYPE_INDEX: { + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * 2); + TslValue var; + TslValue key; + + return_if_error(tsl_value_create_from_stack_value(self, args + 1, &key)); + return_if_error(tsl_value_create_from_stack_value(self, args, &var)); + + if(var.type == TSL_TYPE_LIST) { + TslValue *list_item; + if(key.type != TSL_TYPE_NUMBER) { + /* TODO: Print type as string */ + fprintf(stderr, "Error: Unable to index list %s using a variable of type %d. The index has to be a number\n", "TODO", key.type); + return TSL_PROGRAM_RESULT_ERR; + } + + list_item = tsl_list_get(var.data.list, key.data.number); + if(list_item) { + *dst = *list_item; + } else { + dst->type = TSL_TYPE_NULL; + } + } else if(var.type == TSL_TYPE_MAP) { + TslValue *map_value = tsl_hash_map_get(var.data.map, &key); + if(map_value) { + *dst = *map_value; + } else { + dst->type = TSL_TYPE_NULL; + } + } else { + /* TODO: Print type as string */ + fprintf(stderr, "Error: Unable to index data of type %d. Expected list or map\n", var.type); + return TSL_PROGRAM_RESULT_ERR; + } + break; + } + case TSL_STACK_VALUE_TYPE_NULL: { + dst->type = TSL_TYPE_NULL; + break; + } + case TSL_STACK_VALUE_TYPE_COMMAND_ARG: { + assert(0 && "This is a bug in the compiler. Unable to convert command arg to tsl value"); + abort(); + break; + } + } + return TSL_PROGRAM_RESULT_OK; +} + TslProgramResult tsl_program_run(TslProgram *self) { TslProgramResult result = TSL_PROGRAM_RESULT_OK; TslBytecode *file_scope_bytecode = tsl_buffer_begin(&self->function_bytecode_list); @@ -68,7 +225,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadn %f\n", instruction_type2->value); instruction += sizeof(TslInstructionType2); break; @@ -77,31 +234,16 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadb %s\n", instruction_type3->value ? "true" : "false"); 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))); + cleanup_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; @@ -110,7 +252,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadf %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; @@ -119,7 +261,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_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; @@ -127,61 +269,89 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("loadnull\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_SETV: { + TslStackValue *stack_value = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue)); 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; + cleanup_if_error(map_value); + + cleanup_if_error(tsl_value_create_from_stack_value(self, stack_value, map_value)); printf("setv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data); instruction += sizeof(TslInstructionType4); break; } case TSL_OPCODE_LIST: { + TslStackValue stack_value; + stack_value.data.integer = instruction_type1->value; + stack_value.type = TSL_STACK_VALUE_TYPE_LIST; + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("list %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; } case TSL_OPCODE_MAP: { + TslStackValue stack_value; + stack_value.data.integer = instruction_type1->value; + stack_value.type = TSL_STACK_VALUE_TYPE_MAP; + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("map %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; } case TSL_OPCODE_MINDEX: { + TslStackValue stack_value; + stack_value.type = TSL_STACK_VALUE_TYPE_INDEX; + cleanup_if_error(tsl_buffer_append(&self->stack_values, &stack_value, sizeof(stack_value))); printf("mindex\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_CALLF: { + /* + 1, since the first arg is the function index and the other args are the args for the function */ + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * (1 + instruction_type1->value)); + (void)args; + /* TODO: Implement this */ printf("callf %d\n", instruction_type1->value); instruction += sizeof(TslInstructionType1); break; } case TSL_OPCODE_ADD: { + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * 2); + (void)args; + /* TODO: Implement this */ printf("add\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_SUB: { + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * 2); + (void)args; + /* TODO: Implement this */ printf("sub\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_MUL: { + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * 2); + (void)args; + /* TODO: Implement this */ printf("mul\n"); instruction += sizeof(TslInstructionType5); break; } case TSL_OPCODE_DIV: { + TslStackValue *args = tsl_buffer_pop(&self->stack_values, sizeof(TslStackValue) * 2); + (void)args; + /* TODO: Implement this */ printf("div\n"); instruction += sizeof(TslInstructionType5); break; @@ -190,7 +360,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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))); + cleanup_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; @@ -198,7 +368,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { 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; + TslStackValue *arg = args_begin; char *command_args[255]; char temp_null_save[255]; size_t arg_index = 0; @@ -207,15 +377,15 @@ TslProgramResult tsl_program_run(TslProgram *self) { /* 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'; + while(arg != args_end) { + assert(arg->type == TSL_STACK_VALUE_TYPE_COMMAND_ARG); + temp_null_save[arg_index] = arg->data.str.data[arg->data.str.size]; + arg->data.str.data[arg->data.str.size] = '\0'; - command_args[arg_index] = args->data.str.data; + command_args[arg_index] = arg->data.str.data; printf("%s ", command_args[arg_index]); ++arg_index; - ++args; + ++arg; } command_args[arg_index] = NULL; printf("\n"); @@ -224,13 +394,13 @@ TslProgramResult tsl_program_run(TslProgram *self) { tsl_command_exec(command_args, program_output_temp, NULL); { - args = args_begin; + arg = 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]; + while(arg != args_end) { + arg->data.str.data[arg->data.str.size] = temp_null_save[arg_index]; ++arg_index; - ++args; + ++arg; } command_args[arg_index] = NULL; } @@ -243,7 +413,7 @@ TslProgramResult tsl_program_run(TslProgram *self) { } cleanup: - assert(self->stack_values.size == 0); /* All push instructions (mostly load) haven't been handled yet. This is a bug in tsl */ + assert(self->stack_values.size == 0); /* All push instructions (mostly load) haven't been handled yet. This is a bug in the compiler */ 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; |