aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-01-22 19:14:06 +0100
committerdec05eba <dec05eba@protonmail.com>2020-01-22 19:14:06 +0100
commitb7f056a73ad4053eb2284c54873dfb3888dcb430 (patch)
tree6d036345c5214390781d0019b46bf446e2190478
parent840a3c6c5aa2400ce80d8ec7bb8b1a8d6e25770b (diff)
Correctly parse and produce bytecode for example
-rw-r--r--example.tsl33
-rw-r--r--include/bytecode.h43
-rw-r--r--include/std/buffer.h2
-rw-r--r--src/bytecode.c60
-rw-r--r--src/parser.c201
-rw-r--r--src/std/buffer.c6
-rw-r--r--src/std/hash_map.c9
7 files changed, 262 insertions, 92 deletions
diff --git a/example.tsl b/example.tsl
index 6f165ed..501ddaa 100644
--- a/example.tsl
+++ b/example.tsl
@@ -2,7 +2,7 @@
# setv "value1"
value1 = 1
-# loadn 1
+# loadn 2
# setv "value1"
value1 = 2
@@ -21,7 +21,7 @@ value4 = "hello world"
# loads "hello"
# loads "world"
# loadn 5
-# list "value5", 3
+# list 3
# setv "value5"
value5 = ["hello", "world", 5]
@@ -33,9 +33,19 @@ value5 = ["hello", "world", 5]
# setv "value6"
value6 = {"hello": "world", "value": 23}
-
+# loadf 1 // loadf1 begins at once, because the file body itself is function 0
+# setv "value7"
value7 = fn () {}
+
+# loadf 2
+# setv "value8"
value8 = fn (value) {}
+
+# loads "hello"
+# loads "world"
+# loads "sayHello"
+# loadf 3
+# map 4
value9 = {
"hello": "world",
"sayHello": fn() {
@@ -43,9 +53,26 @@ value9 = {
}
}
+# loadv "value9"
+# loadm "hello"
+# mindex
+# setv "str"
str = value9["hello"]
+
+# loadv "value9"
+# loadm "sayHello"
+# mindex
+# callf 0
value9["sayHello"]()
+# loadv "value1"
+# loadn 23
+# add
+# setv "value1"
value1 = value1 + 23
+# loadca "curl"
+# loadca "https://example.com"
+# callc 2
+# setv "response"
response = $(curl https://example.com) \ No newline at end of file
diff --git a/include/bytecode.h b/include/bytecode.h
index 6ce1dc9..a194517 100644
--- a/include/bytecode.h
+++ b/include/bytecode.h
@@ -9,9 +9,23 @@
typedef uint8_t TslOpcodeType;
typedef enum {
- TSL_OPCODE_LOAD_NUMBER,
- TSL_OPCODE_LOAD_BOOL,
- TSL_OPCODE_SETV
+ TSL_OPCODE_LOADN, /* load number */
+ TSL_OPCODE_LOADB, /* load bool */
+ TSL_OPCODE_LOADS, /* load string */
+ TSL_OPCODE_LOADF, /* load function */
+ TSL_OPCODE_LOADV, /* load variable */
+ TSL_OPCODE_LOADNULL, /* load null */
+ TSL_OPCODE_SETV, /* set variable to the value at the top of the stack */
+ TSL_OPCODE_LIST, /* create a list using values from the stack */
+ TSL_OPCODE_MAP, /* create a map using values from the stack */
+ TSL_OPCODE_MINDEX, /* map index. pop two values from stack, where the first value will be a map and the second a key */
+ TSL_OPCODE_CALLF, /* call the function at the top of the stack using the next N values at the top of the stack as arguments */
+ TSL_OPCODE_ADD,
+ TSL_OPCODE_SUB,
+ TSL_OPCODE_MUL,
+ TSL_OPCODE_DIV,
+ TSL_OPCODE_LOADCA, /* add command argument to stack */
+ TSL_OPCODE_CALLC /* run a program using N arguments from the stack, where the bottom value is the name of the program */
} TslOpcode;
typedef struct {
@@ -19,25 +33,36 @@ typedef struct {
} TslBytecodeWriter;
typedef struct {
- double number;
TslOpcodeType opcode;
+ int value;
} TslInstructionType1;
typedef struct {
- TslBool value;
TslOpcodeType opcode;
+ double value;
} TslInstructionType2;
typedef struct {
- TslStringView key;
TslOpcodeType opcode;
+ TslBool value;
} TslInstructionType3;
+typedef struct {
+ TslOpcodeType opcode;
+ TslStringView value;
+} TslInstructionType4;
+
+typedef struct {
+ TslOpcodeType opcode;
+} TslInstructionType5;
+
void tsl_bytecode_writer_init(TslBytecodeWriter *self);
void tsl_bytecode_writer_deinit(TslBytecodeWriter *self);
-int tsl_bytecode_writer_loadn(TslBytecodeWriter *self, double number);
-int tsl_bytecode_writer_loadb(TslBytecodeWriter *self, TslBool value);
-int tsl_bytecode_writer_setv(TslBytecodeWriter *self, TslStringView *key);
+int tsl_bytecode_writer_add_ins1(TslBytecodeWriter *self, TslOpcode opcode, int value);
+int tsl_bytecode_writer_add_ins2(TslBytecodeWriter *self, TslOpcode opcode, double value);
+int tsl_bytecode_writer_add_ins3(TslBytecodeWriter *self, TslOpcode opcode, TslBool value);
+int tsl_bytecode_writer_add_ins4(TslBytecodeWriter *self, TslOpcode opcode, TslStringView *value);
+int tsl_bytecode_writer_add_ins5(TslBytecodeWriter *self, TslOpcode opcode);
#endif /* TSL_BYTECODE_H */
diff --git a/include/std/buffer.h b/include/std/buffer.h
index db6474e..b7224e9 100644
--- a/include/std/buffer.h
+++ b/include/std/buffer.h
@@ -17,6 +17,8 @@ void tsl_buffer_init(TslBuffer *self);
void tsl_buffer_deinit(TslBuffer *self);
int tsl_buffer_append(TslBuffer *self, const void *data, size_t size);
+/* The buffer has to >= @size */
+void tsl_buffer_pop(TslBuffer *self, size_t size);
void* tsl_buffer_begin(TslBuffer *self);
void* tsl_buffer_end(TslBuffer *self);
diff --git a/src/bytecode.c b/src/bytecode.c
index d15df9e..acdb2d9 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -2,6 +2,29 @@
#include <assert.h>
#include <stdio.h>
+static const char* opcode_to_string(TslOpcode opcode) {
+ switch(opcode) {
+ case TSL_OPCODE_LOADN: return "loadn";
+ case TSL_OPCODE_LOADB: return "loadb";
+ case TSL_OPCODE_LOADS: return "loads";
+ case TSL_OPCODE_LOADF: return "loadf";
+ case TSL_OPCODE_LOADV: return "loadv";
+ case TSL_OPCODE_LOADNULL: return "loadnull";
+ case TSL_OPCODE_SETV: return "setv";
+ case TSL_OPCODE_LIST: return "list";
+ case TSL_OPCODE_MAP: return "map";
+ case TSL_OPCODE_MINDEX: return "mindex";
+ case TSL_OPCODE_CALLF: return "callf";
+ case TSL_OPCODE_ADD: return "add";
+ case TSL_OPCODE_SUB: return "sub";
+ case TSL_OPCODE_MUL: return "mul";
+ case TSL_OPCODE_DIV: return "div";
+ case TSL_OPCODE_LOADCA: return "loadca";
+ case TSL_OPCODE_CALLC: return "callc";
+ }
+ return "";
+}
+
void tsl_bytecode_writer_init(TslBytecodeWriter *self) {
tsl_buffer_init(&self->buffer);
}
@@ -10,26 +33,41 @@ void tsl_bytecode_writer_deinit(TslBytecodeWriter *self) {
tsl_buffer_deinit(&self->buffer);
}
-int tsl_bytecode_writer_loadn(TslBytecodeWriter *self, double number) {
+int tsl_bytecode_writer_add_ins1(TslBytecodeWriter *self, TslOpcode opcode, int value) {
TslInstructionType1 instruction;
- instruction.opcode = TSL_OPCODE_LOAD_NUMBER;
- instruction.number = number;
- fprintf(stderr, "loadn %f\n", number);
+ instruction.opcode = opcode;
+ instruction.value = value;
+ fprintf(stderr, "%s %d\n", opcode_to_string(opcode), value);
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
-int tsl_bytecode_writer_loadb(TslBytecodeWriter *self, TslBool value) {
+int tsl_bytecode_writer_add_ins2(TslBytecodeWriter *self, TslOpcode opcode, double value) {
TslInstructionType2 instruction;
- instruction.opcode = TSL_OPCODE_LOAD_BOOL;
+ instruction.opcode = opcode;
instruction.value = value;
- fprintf(stderr, "loadb %s\n", value ? "true" : "false");
+ fprintf(stderr, "%s %f\n", opcode_to_string(opcode), value);
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
-int tsl_bytecode_writer_setv(TslBytecodeWriter *self, TslStringView *key) {
+int tsl_bytecode_writer_add_ins3(TslBytecodeWriter *self, TslOpcode opcode, TslBool value) {
TslInstructionType3 instruction;
- instruction.opcode = TSL_OPCODE_SETV;
- instruction.key = *key;
- fprintf(stderr, "setv \"%.*s\"\n", (int)key->size, key->data);
+ instruction.opcode = opcode;
+ instruction.value = value;
+ fprintf(stderr, "%s %s\n", opcode_to_string(opcode), value ? "true" : "false");
+ return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
+}
+
+int tsl_bytecode_writer_add_ins4(TslBytecodeWriter *self, TslOpcode opcode, TslStringView *value) {
+ TslInstructionType4 instruction;
+ instruction.opcode = opcode;
+ instruction.value = *value;
+ fprintf(stderr, "%s \"%.*s\"\n", opcode_to_string(opcode), (int)value->size, value->data);
+ return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
+}
+
+int tsl_bytecode_writer_add_ins5(TslBytecodeWriter *self, TslOpcode opcode) {
+ TslInstructionType5 instruction;
+ instruction.opcode = opcode;
+ fprintf(stderr, "%s\n", opcode_to_string(opcode));
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
diff --git a/src/parser.c b/src/parser.c
index 39fff0c..1dbfe48 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1,8 +1,8 @@
#include "../include/parser.h"
#include "../include/bytecode.h"
-#include "../include/std/hash_map.h"
#include <stdio.h>
#include <assert.h>
+#include <stdlib.h>
#define return_if_error(expr) \
{ \
@@ -12,22 +12,56 @@
typedef struct {
TslTokenizer tokenizer;
- TslBytecodeWriter bytecode_writer;
- TslHashMap variables;
+ TslBuffer /*TslBytecodeWriter*/ function_bytecode_list;
+ TslBuffer /*int*/ function_bytecode_list_index;
} TslParser;
+static int tsl_parser_get_current_function_index(TslParser *self) {
+ char *last_item = (char*)tsl_buffer_end(&self->function_bytecode_list_index) - sizeof(int);
+ return *(int*)last_item;
+}
+
+#define get_function_bytecode(self) ((TslBytecodeWriter*)tsl_buffer_begin(&self->function_bytecode_list) + tsl_parser_get_current_function_index(self))
+
static TslParseResult tsl_parser_parse_rhs(TslParser *self);
static TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token);
-static void tsl_parser_init(TslParser *self, const char *code, size_t code_size) {
+static int tsl_parser_init(TslParser *self, const char *code, size_t code_size) {
+ TslBytecodeWriter bytecode_writer;
+ int result = 1;
+ size_t bytecode_index = 0;
tsl_tokenizer_init(&self->tokenizer, code, code_size);
- tsl_bytecode_writer_init(&self->bytecode_writer);
- tsl_hash_map_init(&self->variables);
+ tsl_bytecode_writer_init(&bytecode_writer);
+ tsl_buffer_init(&self->function_bytecode_list);
+ result = tsl_buffer_append(&self->function_bytecode_list, &bytecode_writer, sizeof(bytecode_writer));
+ tsl_buffer_init(&self->function_bytecode_list_index);
+ result = tsl_buffer_append(&self->function_bytecode_list_index, &bytecode_index, sizeof(bytecode_index));
+ return result;
}
static void tsl_parser_deinit(TslParser *self) {
- tsl_bytecode_writer_deinit(&self->bytecode_writer);
- tsl_hash_map_deinit(&self->variables);
+ TslBytecodeWriter *bytecode_writer = tsl_buffer_begin(&self->function_bytecode_list);
+ TslBytecodeWriter *bytecode_writer_end = tsl_buffer_end(&self->function_bytecode_list);
+ while(bytecode_writer != bytecode_writer_end) {
+ tsl_bytecode_writer_deinit(bytecode_writer);
+ ++bytecode_writer;
+ }
+ tsl_buffer_deinit(&self->function_bytecode_list);
+ tsl_buffer_deinit(&self->function_bytecode_list_index);
+}
+
+static TslParseResult tsl_parser_push_function(TslParser *self) {
+ int function_index;
+ TslBytecodeWriter bytecode_writer;
+ tsl_bytecode_writer_init(&bytecode_writer);
+ /* TODO: Use bitshift ? */
+ function_index = self->function_bytecode_list.size / sizeof(TslBytecodeWriter);
+ return_if_error(tsl_buffer_append(&self->function_bytecode_list, &bytecode_writer, sizeof(bytecode_writer)));
+ return tsl_buffer_append(&self->function_bytecode_list_index, &function_index, sizeof(function_index));
+}
+
+static void tsl_parser_pop_function(TslParser *self) {
+ tsl_buffer_pop(&self->function_bytecode_list_index, sizeof(int));
}
#if 0
@@ -43,10 +77,11 @@ static uint64_t hash_string_view(const void *data, size_t size) {
}
#endif
-static TslParseResult tsl_parser_parse_map(TslParser *self) {
+static TslParseResult tsl_parser_parse_map(TslParser *self, int *num_items) {
#define parse_map_element_separator \
return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON)); \
return_if_error(tsl_parser_parse_rhs(self)); \
+ ++*num_items; \
token = tsl_tokenizer_next(&self->tokenizer); \
if(token == TSL_TOKEN_COMMA) { \
continue; \
@@ -57,19 +92,24 @@ static TslParseResult tsl_parser_parse_map(TslParser *self) {
return TSL_PARSE_RESULT_ERR; \
}
+ *num_items = 0;
for(;;) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
- printf("rhs num: %f\n", self->tokenizer.number_value);
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
parse_map_element_separator
} else if(token == TSL_TOKEN_BOOL) {
- printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
parse_map_element_separator
} else if(token == TSL_TOKEN_NULL) {
- printf("rhs null\n");
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
parse_map_element_separator
} else if(token == TSL_TOKEN_STRING) {
- printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data);
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADS, &self->tokenizer.string));
parse_map_element_separator
} else if(token == TSL_TOKEN_RBRACE) {
/* '}' after trailing ',' or an empty map */
@@ -78,12 +118,10 @@ static TslParseResult tsl_parser_parse_map(TslParser *self) {
fprintf(stderr, "Error: Expected '}', got TODO\n");
return TSL_PARSE_RESULT_ERR;
}
-
- token = tsl_tokenizer_next(&self->tokenizer);
}
}
-static TslParseResult tsl_parser_parse_list(TslParser *self) {
+static TslParseResult tsl_parser_parse_list(TslParser *self, int *num_items) {
#define parse_list_element_separator \
token = tsl_tokenizer_next(&self->tokenizer); \
if(token == TSL_TOKEN_COMMA) { \
@@ -95,20 +133,25 @@ static TslParseResult tsl_parser_parse_list(TslParser *self) {
return TSL_PARSE_RESULT_ERR; \
}
+ *num_items = 0;
for(;;) {
/* TODO: Use tsl_parser_parse_rhs instead */
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
- printf("rhs num: %f\n", self->tokenizer.number_value);
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
parse_list_element_separator
} else if(token == TSL_TOKEN_BOOL) {
- printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
parse_list_element_separator
} else if(token == TSL_TOKEN_NULL) {
- printf("rhs null\n");
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
parse_list_element_separator
} else if(token == TSL_TOKEN_STRING) {
- printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data);
+ ++*num_items;
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADS, &self->tokenizer.string));
parse_list_element_separator
} else if(token == TSL_TOKEN_RBRACKET) {
/* ']' after trailing ',' or an empty list */
@@ -156,11 +199,13 @@ static TslParseResult tsl_parser_parse_fn(TslParser *self) {
static TslParseResult tsl_parser_parse_var_indexing(TslParser *self) {
return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACKET));
return_if_error(tsl_parser_parse_rhs(self));
- return tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET);
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET));
+ return tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_MINDEX);
}
/* FUNC_CALL = '(' (RHS ',')* ')' */
-static TslParseResult tsl_parser_parse_func_call(TslParser *self) {
+static TslParseResult tsl_parser_parse_func_call(TslParser *self, int *num_args) {
+ *num_args = 0;
return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN));
for(;;) {
TslToken token = tsl_tokenizer_peek(&self->tokenizer);
@@ -168,6 +213,7 @@ static TslParseResult tsl_parser_parse_func_call(TslParser *self) {
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_RPAREN */
return TSL_PARSE_RESULT_OK;
} else {
+ ++*num_args;
return_if_error(tsl_parser_parse_rhs(self));
token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_COMMA) {
@@ -184,14 +230,16 @@ static TslParseResult tsl_parser_parse_func_call(TslParser *self) {
/* TODO: Do not allow empty command */
/* TODO: Allow command inside another command */
-/* COMMAND = TODO */
-static TslParseResult tsl_parser_parse_command(TslParser *self) {
+/* COMMAND = '(' TSL_COMMAND_TOKEN_ARG* ')' */
+static TslParseResult tsl_parser_parse_command(TslParser *self, int *num_args) {
+ *num_args = 0;
return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN));
for(;;) {
TslStringView command_arg;
TslCommandToken command_token = tsl_tokenizer_next_command_arg(&self->tokenizer, &command_arg);
if(command_token == TSL_COMMAND_TOKEN_ARG) {
- printf("command arg: |%.*s|\n", (int)command_arg.size, command_arg.data);
+ ++*num_args;
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADCA, &command_arg));
} else if(command_token == TSL_COMMAND_TOKEN_END) {
return TSL_PARSE_RESULT_OK;
} else {
@@ -201,6 +249,18 @@ static TslParseResult tsl_parser_parse_command(TslParser *self) {
}
}
+static TslOpcode arithmetic_symbol_to_opcode(char arithmetic_symbol) {
+ switch(arithmetic_symbol) {
+ case '+': return TSL_OPCODE_ADD;
+ case '-': return TSL_OPCODE_SUB;
+ case '*': return TSL_OPCODE_MUL;
+ case '/': return TSL_OPCODE_DIV;
+ default:
+ fprintf(stderr, "Unexpected arithmetic symbol: %c\n", arithmetic_symbol);
+ abort();
+ }
+}
+
/* RHS_SUB = (VAR_INDEX|FUNC_CALL RHS_SUB?)|(TOKEN_ARITHMETIC RHS) */
static TslParseResult tsl_parser_parse_rhs_sub(TslParser *self) {
TslToken token = tsl_tokenizer_peek(&self->tokenizer);
@@ -208,13 +268,16 @@ static TslParseResult tsl_parser_parse_rhs_sub(TslParser *self) {
return_if_error(tsl_parser_parse_var_indexing(self));
return tsl_parser_parse_rhs_sub(self);
} else if(token == TSL_TOKEN_LPAREN) {
- return_if_error(tsl_parser_parse_func_call(self));
+ int num_args;
+ return_if_error(tsl_parser_parse_func_call(self, &num_args));
+ return_if_error(tsl_bytecode_writer_add_ins1(get_function_bytecode(self), TSL_OPCODE_CALLF, num_args));
return tsl_parser_parse_rhs_sub(self);
} else if(token == TSL_TOKEN_ARITHMETIC) {
+ TslOpcode arithmetic_opcode;
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_ARITHMETIC */
- printf("rhs sub arithmetic symbol: %c\n", self->tokenizer.arithmetic_symbol);
+ arithmetic_opcode = arithmetic_symbol_to_opcode(self->tokenizer.arithmetic_symbol);
/* TODO: Handle arithmetic expression precedence */
- return tsl_parser_parse_rhs(self);
+ return tsl_parser_parse_rhs(self) && tsl_bytecode_writer_add_ins5(get_function_bytecode(self), arithmetic_opcode);
}
/*
No sub expression found, possibly a new expression after this (a new expression on a new line), let that
@@ -242,41 +305,48 @@ static TslParseResult tsl_parser_parse_rhs_sub_arithmetic(TslParser *self) {
/* RHS = (IDENTIFIER|NUM|BOOL|NULL|STRING|MAP|LIST|('fn' FN)|('$' COMMAND)) RHS_SUB? */
TslParseResult tsl_parser_parse_rhs(TslParser *self) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
- if(token == TSL_TOKEN_IDENTIFIER) {
- TslStringView var_name = self->tokenizer.identifier;
- assert(0 && "TODO: Implement");
- printf("rhs var: %.*s\n", (int)var_name.size, var_name.data);
- return tsl_parser_parse_rhs_sub(self);
- } else if(token == TSL_TOKEN_NUM) {
- return_if_error(tsl_bytecode_writer_loadn(&self->bytecode_writer, self->tokenizer.number_value));
- printf("rhs num: %f\n", self->tokenizer.number_value);
- return tsl_parser_parse_rhs_sub_arithmetic(self);
- } else if(token == TSL_TOKEN_BOOL) {
- printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
- return tsl_bytecode_writer_loadb(&self->bytecode_writer, self->tokenizer.bool_value);
- } else if(token == TSL_TOKEN_NULL) {
- assert(0 && "TODO: Implement");
- printf("rhs null\n");
- } else if(token == TSL_TOKEN_STRING) {
- assert(0 && "TODO: Implement");
- printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data);
- } else if(token == TSL_TOKEN_LBRACE) {
- assert(0 && "TODO: Implement");
- return tsl_parser_parse_map(self);
- } else if(token == TSL_TOKEN_LBRACKET) {
- assert(0 && "TODO: Implement");
- return tsl_parser_parse_list(self);
- } else if(token == TSL_TOKEN_FN) {
- assert(0 && "TODO: Implement");
- return tsl_parser_parse_fn(self);
- } else if(token == TSL_TOKEN_DOLLAR_SIGN) {
- assert(0 && "TODO: Implement");
- return tsl_parser_parse_command(self);
- } else {
- fprintf(stderr, "Error: Expected variable, number, bool, null, map, list, function or command, got TODO (%d) (line: %d)\n", token, tsl_tokenizer_get_line_by_index(&self->tokenizer, self->tokenizer.prev_code_index));
- return TSL_PARSE_RESULT_ERR;
+ switch(token) {
+ case TSL_TOKEN_IDENTIFIER: {
+ TslStringView var_name = self->tokenizer.identifier;
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADV, &var_name));
+ return tsl_parser_parse_rhs_sub(self);
+ }
+ case TSL_TOKEN_NUM:
+ return_if_error(tsl_bytecode_writer_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
+ return tsl_parser_parse_rhs_sub_arithmetic(self);
+ case TSL_TOKEN_BOOL:
+ return tsl_bytecode_writer_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value);
+ case TSL_TOKEN_NULL:
+ return tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL);
+ case TSL_TOKEN_STRING:
+ return tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADS, &self->tokenizer.string);
+ case TSL_TOKEN_LBRACE: {
+ int num_items;
+ return tsl_parser_parse_map(self, &num_items) &&
+ tsl_bytecode_writer_add_ins1(get_function_bytecode(self), TSL_OPCODE_MAP, num_items);
+ }
+ case TSL_TOKEN_LBRACKET: {
+ int num_items;
+ return tsl_parser_parse_list(self, &num_items) &&
+ tsl_bytecode_writer_add_ins1(get_function_bytecode(self), TSL_OPCODE_LIST, num_items);
+ }
+ case TSL_TOKEN_FN: {
+ int function_index;
+ return_if_error(tsl_parser_push_function(self));
+ return_if_error(tsl_parser_parse_fn(self));
+ function_index = tsl_parser_get_current_function_index(self);
+ tsl_parser_pop_function(self);
+ return tsl_bytecode_writer_add_ins1(get_function_bytecode(self), TSL_OPCODE_LOADF, function_index);
+ }
+ case TSL_TOKEN_DOLLAR_SIGN: {
+ int num_args;
+ return tsl_parser_parse_command(self, &num_args) &&
+ tsl_bytecode_writer_add_ins1(get_function_bytecode(self), TSL_OPCODE_CALLC, num_args);
+ }
+ default:
+ fprintf(stderr, "Error: Expected variable, number, bool, null, map, list, function or command, got TODO (%d) (line: %d)\n", token, tsl_tokenizer_get_line_by_index(&self->tokenizer, self->tokenizer.prev_code_index));
+ return TSL_PARSE_RESULT_ERR;
}
- return TSL_PARSE_RESULT_OK;
}
/*
@@ -288,12 +358,13 @@ TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token)
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_IDENTIFIER) {
TslStringView identifier = self->tokenizer.identifier;
- printf("identifier: %.*s\n", (int)identifier.size, identifier.data);
if(tsl_tokenizer_peek(&self->tokenizer) == TSL_TOKEN_EQUAL) {
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_EQUAL */
return_if_error(tsl_parser_parse_rhs(self));
- return_if_error(tsl_bytecode_writer_setv(&self->bytecode_writer, &identifier));
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_SETV, &identifier));
+ /* TODO: Assert if there are load bytecode opcodes not followed by set */
} else {
+ return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADV, &identifier));
return_if_error(tsl_parser_parse_rhs_sub(self));
}
} else if(token == end_token) {
@@ -309,7 +380,7 @@ TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token)
TslParseResult tsl_parse(const char *code, size_t code_size) {
TslParseResult result;
TslParser parser;
- tsl_parser_init(&parser, code, code_size);
+ return_if_error(tsl_parser_init(&parser, code, code_size));
result = tsl_parser_parse_expressions(&parser, TSL_TOKEN_END_OF_FILE);
tsl_parser_deinit(&parser);
return result;
diff --git a/src/std/buffer.c b/src/std/buffer.c
index e311c8f..dd7d0f6 100644
--- a/src/std/buffer.c
+++ b/src/std/buffer.c
@@ -2,6 +2,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
void tsl_buffer_init(TslBuffer *self) {
self->data = NULL;
@@ -44,6 +45,11 @@ int tsl_buffer_append(TslBuffer *self, const void *data, size_t size) {
return 1;
}
+void tsl_buffer_pop(TslBuffer *self, size_t size) {
+ assert(self->size >= size);
+ self->size -= size;
+}
+
void* tsl_buffer_begin(TslBuffer *self) {
return self->data;
}
diff --git a/src/std/hash_map.c b/src/std/hash_map.c
index 968a5ea..7ba1daf 100644
--- a/src/std/hash_map.c
+++ b/src/std/hash_map.c
@@ -43,10 +43,6 @@ void tsl_hash_map_deinit(TslHashMap *self) {
/* TODO: Remove if (data) and if (output) */
static int tsl_hash_map_append_bucket(TslHashMapNode **head_node, uint64_t hash, const TslStringView *key, size_t size, const void *data, void **output) {
TslHashMapNode *next_node;
- /*
- TODO: Instead of allocating space for the data, allow the user to pass a pointer in the insert
- method and use that directly.
- */
uint8_t *node_data = malloc(sizeof(hash) + sizeof(key->size) + key->size + sizeof(size) + size);
if(output)
*output = node_data;
@@ -65,8 +61,13 @@ static int tsl_hash_map_append_bucket(TslHashMapNode **head_node, uint64_t hash,
}
memcpy(node_data, &hash, sizeof(hash));
+ /* TODO: Instead of allocating space for the key, use the key data pointer and size directly. */
memcpy(node_data + sizeof(hash), &key->size, sizeof(key->size));
memcpy(node_data + sizeof(hash) + sizeof(key->size), key->data, key->size);
+ /*
+ TODO: Instead of allocating space for the data, allow the user to pass a pointer in the insert
+ method and use that directly.
+ */
memcpy(node_data + sizeof(hash) + sizeof(key->size) + key->size, &size, sizeof(size));
if(data)
memcpy(node_data + sizeof(hash) + sizeof(key->size) + key->size + sizeof(size), data, size);