aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--example.tsl11
-rw-r--r--include/forward_decl.h8
-rw-r--r--include/program.h5
-rw-r--r--include/std_gc/hash_map.h3
-rw-r--r--include/std_gc/list.h21
-rw-r--r--include/value.h27
-rw-r--r--src/program.c248
-rw-r--r--src/std_gc/hash_map.c31
-rw-r--r--src/std_gc/list.c67
-rw-r--r--src/value.c19
11 files changed, 372 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index 5e14b47..f6ec581 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
CFLAGS = -Wall -Wextra -Werror -g3 -std=c89 -pedantic -fPIE -DDEBUG
LIBS = -lgc
-OBJ = build/main.o build/tokenizer.o build/parser.o build/program.o build/bytecode.o build/value.o build/command.o build/buffer.o build/hash_map.o
+OBJ = build/main.o build/tokenizer.o build/parser.o build/program.o build/bytecode.o build/value.o build/command.o build/buffer.o build/hash_map.o build/list.o
CC = cc
all: build_dir $(OBJ)
@@ -41,3 +41,6 @@ build/buffer.o: src/std/buffer.c include/std/buffer.h
build/hash_map.o: src/std_gc/hash_map.c include/std_gc/hash_map.h
$(CC) -c src/std_gc/hash_map.c -o build/hash_map.o $(CFLAGS)
+
+build/list.o: src/std_gc/list.c include/std_gc/list.h
+ $(CC) -c src/std_gc/list.c -o build/list.o $(CFLAGS)
diff --git a/example.tsl b/example.tsl
index 18253a8..e85b779 100644
--- a/example.tsl
+++ b/example.tsl
@@ -25,6 +25,12 @@ value4 = "hello world"
# setv "value5"
value5 = ["hello", "world", 5]
+# loadv "value5"
+# loadn 0
+# mindex
+# setv "list_index_value"
+list_index_value = value5[0]
+
# loads "hello"
# loads "world"
# loads "value"
@@ -46,6 +52,7 @@ value8 = fn (value) {}
# loads "sayHello"
# loadf 3
# map 4
+# setv "value9"
value9 = {
"hello": "world",
"sayHello": fn() {
@@ -54,13 +61,13 @@ value9 = {
}
# loadv "value9"
-# loadm "hello"
+# loads "hello"
# mindex
# setv "str"
str = value9["hello"]
# loadv "value9"
-# loadm "sayHello"
+# loads "sayHello"
# mindex
# callf 0
value9["sayHello"]()
diff --git a/include/forward_decl.h b/include/forward_decl.h
new file mode 100644
index 0000000..cc7ec12
--- /dev/null
+++ b/include/forward_decl.h
@@ -0,0 +1,8 @@
+#ifndef TSL_FORWARD_DECL_H
+#define TSL_FORWARD_DECL_H
+
+typedef struct TslValue TslValue;
+
+struct ____tsl_dummy { int dd; };
+
+#endif /* TSL_FORWARD_DECL_H */
diff --git a/include/program.h b/include/program.h
index 5c4737b..bbd3f37 100644
--- a/include/program.h
+++ b/include/program.h
@@ -10,9 +10,12 @@ typedef enum {
TSL_STACK_VALUE_TYPE_NUMBER,
TSL_STACK_VALUE_TYPE_BOOL,
TSL_STACK_VALUE_TYPE_STRING,
+ TSL_STACK_VALUE_TYPE_NULL,
TSL_STACK_VALUE_TYPE_FUNCTION,
TSL_STACK_VALUE_TYPE_VARIABLE,
- TSL_STACK_VALUE_TYPE_NULL,
+ TSL_STACK_VALUE_TYPE_LIST,
+ TSL_STACK_VALUE_TYPE_MAP,
+ TSL_STACK_VALUE_TYPE_INDEX,
TSL_STACK_VALUE_TYPE_COMMAND_ARG
} TslStackValueType;
diff --git a/include/std_gc/hash_map.h b/include/std_gc/hash_map.h
index e67dd75..e1a016d 100644
--- a/include/std_gc/hash_map.h
+++ b/include/std_gc/hash_map.h
@@ -1,8 +1,9 @@
#ifndef TSL_HASH_MAP_H
#define TSL_HASH_MAP_H
-#include "../value.h"
+#include "../forward_decl.h"
#include <stdint.h>
+#include <stddef.h>
/* TODO: Optimize small hash map by using the members of the struct instead of allocating on heap */
typedef struct {
diff --git a/include/std_gc/list.h b/include/std_gc/list.h
new file mode 100644
index 0000000..469f585
--- /dev/null
+++ b/include/std_gc/list.h
@@ -0,0 +1,21 @@
+#ifndef TSL_LIST_H
+#define TSL_LIST_H
+
+#include "../forward_decl.h"
+#include <stddef.h>
+
+typedef struct {
+ void *data;
+ size_t size;
+ size_t capacity;
+} TslList;
+
+void tsl_list_init(TslList *self);
+int tsl_list_append(TslList *self, const TslValue *data);
+int tsl_list_set_capacity_hint(TslList *self, size_t capacity);
+TslValue* tsl_list_begin(TslList *self);
+TslValue* tsl_list_end(TslList *self);
+/* Returns NULL if index is out of bounds of the list */
+TslValue* tsl_list_get(TslList *self, double index);
+
+#endif /* TSL_LIST_H */
diff --git a/include/value.h b/include/value.h
index e26cc4a..d9c6354 100644
--- a/include/value.h
+++ b/include/value.h
@@ -1,9 +1,12 @@
#ifndef TSL_VALUE_H
#define TSL_VALUE_H
+#include "forward_decl.h"
#include <stddef.h>
#include <stdint.h>
#include "string_view.h"
+#include "std_gc/list.h"
+#include "std_gc/hash_map.h"
typedef enum {
TSL_TYPE_NULL,
@@ -13,6 +16,7 @@ typedef enum {
TSL_TYPE_BOOL,
TSL_TYPE_LIST,
TSL_TYPE_MAP,
+ TSL_TYPE_FUNCTION,
TSL_TYPE_USERDATA
} TslType;
@@ -29,32 +33,29 @@ typedef struct {
size_t size;
} TslString;
-/* TODO: Implement this */
-typedef struct {
- void *data;
- size_t size;
-} TslList;
-
-/* TODO: Implement this */
-typedef struct {
- void *data;
-} TslMap;
+/* This is an index to the function */
+typedef int TslFunction;
-typedef struct {
+struct TslValue {
union {
TslNumber number;
TslString *string;
TslStringView string_view;
TslBool boolean;
+ TslBool null;
TslList *list;
- TslMap *map;
+ TslHashMap *map;
+ TslFunction function;
void *userdata;
} data;
uint8_t type;
-} TslValue;
+};
uint64_t tsl_value_hash(const TslValue *value);
/* Returns 1 if equal, otherwise returns 0 */
int tsl_value_equals(const TslValue *lhs, const TslValue *rhs);
+/* This should be called before setting/modifying the data of the value */
+void tsl_value_clear(TslValue *self);
+
#endif /* TSL_VALUE_H */
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;
diff --git a/src/std_gc/hash_map.c b/src/std_gc/hash_map.c
index 1960ffc..4d4c026 100644
--- a/src/std_gc/hash_map.c
+++ b/src/std_gc/hash_map.c
@@ -1,4 +1,5 @@
#include "../../include/std_gc/hash_map.h"
+#include "../../include/value.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
@@ -127,9 +128,6 @@ static int tsl_hash_map_ensure_bucket_capacity_for_one_new_item(TslHashMap *self
}
}
- if(old_capacity == 0)
- return 1;
-
tsl_hash_map_reorder_nodes(self, old_capacity);
return 1;
}
@@ -169,23 +167,26 @@ TslValue* tsl_hash_map_get(TslHashMap *self, const TslValue *key) {
TslValue* tsl_hash_map_get_or_create(TslHashMap *self, const TslValue *key) {
uint64_t hash;
size_t index;
- TslHashMapNode **bucket;
- TslHashMapNode *node;
TslValue *value;
- if(self->buckets_capacity == 0) {
- if(!tsl_hash_map_ensure_bucket_capacity_for_one_new_item(self))
- return NULL;
- }
+ TslHashMapNode **bucket;
hash = tsl_value_hash(key);
+ if(self->buckets_capacity > 0) {
+ size_t index = tsl_hash_map_get_index(self, hash);
+ TslHashMapNode **bucket = (TslHashMapNode**)self->buckets_data + index;
+ TslHashMapNode *node = *bucket;
+ while(node) {
+ if(hash == node->hash && tsl_value_equals(key, &node->key))
+ return &node->value;
+ node = node->next;
+ }
+ }
+
+ if(!tsl_hash_map_ensure_bucket_capacity_for_one_new_item(self))
+ return NULL;
+
index = tsl_hash_map_get_index(self, hash);
bucket = (TslHashMapNode**)self->buckets_data + index;
- node = *bucket;
- while(node) {
- if(hash == node->hash && tsl_value_equals(key, &node->key))
- return &node->value;
- node = node->next;
- }
if(!tsl_hash_map_append_bucket(bucket, hash, key, NULL, &value))
return NULL;
diff --git a/src/std_gc/list.c b/src/std_gc/list.c
new file mode 100644
index 0000000..5b7c7b6
--- /dev/null
+++ b/src/std_gc/list.c
@@ -0,0 +1,67 @@
+#include "../../include/std_gc/list.h"
+#include "../../include/value.h"
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#ifdef DEBUG
+#define GC_DEBUG
+#endif
+#include <gc.h>
+
+void tsl_list_init(TslList *self) {
+ self->data = NULL;
+ self->size = 0;
+ self->capacity = 0;
+}
+
+static int tsl_list_ensure_capacity(TslList *self, size_t new_size) {
+ void *new_ptr;
+ size_t new_capacity = self->capacity;
+ if(new_size <= self->capacity)
+ return 1;
+
+ if(new_capacity == 0)
+ new_capacity = 8;
+
+ while(new_capacity < new_size) {
+ new_capacity <<= 1;
+ }
+
+ new_ptr = GC_REALLOC(self->data, new_capacity);
+ if(!new_ptr) {
+ fprintf(stderr, "Error: buffer append failed. Reason: out of memory\n");
+ return 0;
+ }
+
+ self->data = new_ptr;
+ self->capacity = new_capacity;
+ return 1;
+}
+
+int tsl_list_append(TslList *self, const TslValue *data) {
+ if(!tsl_list_ensure_capacity(self, self->size + sizeof(TslValue)))
+ return 0;
+ memcpy((char*)self->data + self->size, data, sizeof(TslValue));
+ self->size += sizeof(TslValue);
+ return 1;
+}
+
+int tsl_list_set_capacity_hint(TslList *self, size_t capacity) {
+ return tsl_list_ensure_capacity(self, capacity);
+}
+
+TslValue* tsl_list_begin(TslList *self) {
+ return self->data;
+}
+
+TslValue* tsl_list_end(TslList *self) {
+ return (TslValue*)((char*)self->data + self->size);
+}
+
+TslValue* tsl_list_get(TslList *self, double index) {
+ /* TODO: Verify if overflow check is needed */
+ intptr_t index_i = index;
+ if(index_i >= 0 && index_i < (intptr_t)self->size / (intptr_t)sizeof(TslValue))
+ return (TslValue*)self->data + index_i;
+ return NULL;
+}
diff --git a/src/value.c b/src/value.c
index 690527f..c08048a 100644
--- a/src/value.c
+++ b/src/value.c
@@ -12,19 +12,23 @@ static uint64_t hash_range(const uint8_t *data, size_t size) {
}
uint64_t tsl_value_hash(const TslValue *key) {
- switch(key->type) {
+ switch((TslType)key->type) {
case TSL_TYPE_NULL:
return 0;
case TSL_TYPE_NUMBER:
return *(uint64_t*)&key->data.number;
case TSL_TYPE_STRING:
return hash_range(key->data.string->data, key->data.string->size);
+ case TSL_TYPE_STRING_VIEW:
+ return hash_range((uint8_t*)key->data.string_view.data, key->data.string_view.size);
case TSL_TYPE_BOOL:
return key->data.boolean;
case TSL_TYPE_LIST:
return (uint64_t)key->data.list;
case TSL_TYPE_MAP:
return (uint64_t)key->data.map;
+ case TSL_TYPE_FUNCTION:
+ return key->data.function;
case TSL_TYPE_USERDATA:
return (uint64_t)key->data.userdata;
}
@@ -36,10 +40,23 @@ int tsl_value_equals(const TslValue *lhs, const TslValue *rhs) {
if(lhs->type == TSL_TYPE_STRING) {
return lhs->data.string->size == rhs->data.string->size
&& memcmp(lhs->data.string->data, rhs->data.string->data, lhs->data.string->size) == 0;
+ } else if(lhs->type == TSL_TYPE_STRING_VIEW) {
+ return lhs->data.string_view.size == rhs->data.string_view.size
+ && memcmp(lhs->data.string_view.data, rhs->data.string_view.data, lhs->data.string_view.size) == 0;
} else {
return *(uint64_t*)&lhs->data == *(uint64_t*)&rhs->data;
}
+ } else if(lhs->type == TSL_TYPE_STRING && rhs->type == TSL_TYPE_STRING_VIEW) {
+ return lhs->data.string->size == rhs->data.string_view.size
+ && memcmp(lhs->data.string->data, rhs->data.string_view.data, lhs->data.string->size) == 0;
+ } else if(lhs->type == TSL_TYPE_STRING_VIEW && rhs->type == TSL_TYPE_STRING) {
+ return lhs->data.string_view.size == rhs->data.string->size
+ && memcmp(lhs->data.string_view.data, rhs->data.string->data, lhs->data.string_view.size) == 0;
} else {
return 0;
}
}
+
+void tsl_value_clear(TslValue *self) {
+ memset(self, 0, sizeof(TslValue));
+}