aboutsummaryrefslogtreecommitdiff
path: root/src/program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/program.c')
-rw-r--r--src/program.c248
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;