aboutsummaryrefslogtreecommitdiff
path: root/src/program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/program.c')
-rw-r--r--src/program.c162
1 files changed, 130 insertions, 32 deletions
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 <gc.h>
#include <stdio.h>
#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
}