aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-01-23 03:09:54 +0100
committerdec05eba <dec05eba@protonmail.com>2020-01-23 03:09:54 +0100
commitcc30a97ab90a8fa40707936d3d089d81c49559b6 (patch)
treec6544b785395cf12b8c9f4c65c3f8ebb9699232d
parentb7f056a73ad4053eb2284c54873dfb3888dcb430 (diff)
Add bytecode decoding.. starting on program execution now
-rw-r--r--Makefile5
-rw-r--r--README.md3
-rw-r--r--include/bytecode.h30
-rw-r--r--include/parser.h7
-rw-r--r--include/program.h22
-rw-r--r--include/std/buffer.h1
-rw-r--r--src/bytecode.c26
-rw-r--r--src/main.c18
-rw-r--r--src/parser.c86
-rw-r--r--src/program.c122
-rw-r--r--src/std/buffer.c11
11 files changed, 258 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index 15de48f..16e7513 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
CFLAGS = -Wall -Wextra -Werror -g3 -std=c89 -pedantic -fPIE
LIBS = -lgc
-OBJ = build/main.o build/tokenizer.o build/parser.o build/bytecode.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/buffer.o build/hash_map.o
CC = cc
all: build_dir $(OBJ)
@@ -24,6 +24,9 @@ build/tokenizer.o: src/tokenizer.c include/tokenizer.h
build/parser.o: src/parser.c include/parser.h
$(CC) -c src/parser.c -o build/parser.o $(CFLAGS)
+build/program.o: src/program.c include/program.h
+ $(CC) -c src/program.c -o build/program.o $(CFLAGS)
+
build/bytecode.o: src/bytecode.c include/bytecode.h
$(CC) -c src/bytecode.c -o build/bytecode.o $(CFLAGS)
diff --git a/README.md b/README.md
index 9f9d49f..bbf1212 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,5 @@ Written in ANSI C to allow embedding everywhere and a WTFPL license that allows
# TODO
* Remove dependency on `gc`. Write our own gc instead.
* Implement big int, which numbers should automatically switch to when they are too large to fit into double.
-* Use a list instead of a hash map for variable lookup, since the list will be small most of the time. \ No newline at end of file
+* Use a list instead of a hash map for variable lookup, since the list will be small most of the time.
+* Implement sandboxes similar to lua, by disabling use of import, file io and other functions. \ No newline at end of file
diff --git a/include/bytecode.h b/include/bytecode.h
index a194517..06ebf19 100644
--- a/include/bytecode.h
+++ b/include/bytecode.h
@@ -29,40 +29,42 @@ typedef enum {
} TslOpcode;
typedef struct {
- TslBuffer buffer;
-} TslBytecodeWriter;
+ TslBuffer /*TslInstruction*/ buffer;
+} TslBytecode;
typedef struct {
- TslOpcodeType opcode;
+ TslOpcode opcode;
int value;
} TslInstructionType1;
typedef struct {
- TslOpcodeType opcode;
+ TslOpcode opcode;
double value;
} TslInstructionType2;
typedef struct {
- TslOpcodeType opcode;
+ TslOpcode opcode;
TslBool value;
} TslInstructionType3;
typedef struct {
- TslOpcodeType opcode;
+ TslOpcode opcode;
TslStringView value;
} TslInstructionType4;
typedef struct {
- TslOpcodeType opcode;
+ TslOpcode opcode;
} TslInstructionType5;
-void tsl_bytecode_writer_init(TslBytecodeWriter *self);
-void tsl_bytecode_writer_deinit(TslBytecodeWriter *self);
+const char* tsl_opcode_to_string(TslOpcode opcode);
-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);
+void tsl_bytecode_init(TslBytecode *self);
+void tsl_bytecode_deinit(TslBytecode *self);
+
+int tsl_bytecode_add_ins1(TslBytecode *self, TslOpcode opcode, int value);
+int tsl_bytecode_add_ins2(TslBytecode *self, TslOpcode opcode, double value);
+int tsl_bytecode_add_ins3(TslBytecode *self, TslOpcode opcode, TslBool value);
+int tsl_bytecode_add_ins4(TslBytecode *self, TslOpcode opcode, TslStringView *value);
+int tsl_bytecode_add_ins5(TslBytecode *self, TslOpcode opcode);
#endif /* TSL_BYTECODE_H */
diff --git a/include/parser.h b/include/parser.h
index b915dfd..440fbac 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -2,12 +2,17 @@
#define TSL_PARSER_H
#include "tokenizer.h"
+#include "program.h"
typedef enum {
TSL_PARSE_RESULT_ERR,
TSL_PARSE_RESULT_OK
} TslParseResult;
-TslParseResult tsl_parse(const char *code, size_t code_size);
+/*
+ TODO: Make this function load a file instead of parsing memory.
+ This is needed because when using @import function instead tsl, it will load a file anyways.
+*/
+TslParseResult tsl_parse(const char *code, size_t code_size, TslProgram *program_output);
#endif /* TSL_PARSER_H */
diff --git a/include/program.h b/include/program.h
new file mode 100644
index 0000000..6135726
--- /dev/null
+++ b/include/program.h
@@ -0,0 +1,22 @@
+#ifndef TSL_PROGRAM_H
+#define TSL_PROGRAM_H
+
+#include "std/buffer.h"
+#include "std/hash_map.h"
+
+typedef struct {
+ TslBuffer /*TslBytecode*/ function_bytecode_list;
+ TslHashMap variables;
+} TslProgram;
+
+typedef enum {
+ TSL_PROGRAM_RESULT_ERR,
+ TSL_PROGRAM_RESULT_OK
+} TslProgramResult;
+
+void tsl_program_init(TslProgram *self);
+void tsl_program_deinit(TslProgram *self);
+
+TslProgramResult tsl_program_run(TslProgram *self);
+
+#endif /* TSL_PROGRAM_H */
diff --git a/include/std/buffer.h b/include/std/buffer.h
index b7224e9..3aad48b 100644
--- a/include/std/buffer.h
+++ b/include/std/buffer.h
@@ -21,5 +21,6 @@ int tsl_buffer_append(TslBuffer *self, const void *data, size_t size);
void tsl_buffer_pop(TslBuffer *self, size_t size);
void* tsl_buffer_begin(TslBuffer *self);
void* tsl_buffer_end(TslBuffer *self);
+void tsl_buffer_move(TslBuffer *dst, TslBuffer *src);
#endif /* TSL_BUFFER_H */
diff --git a/src/bytecode.c b/src/bytecode.c
index acdb2d9..b8342b4 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -2,7 +2,7 @@
#include <assert.h>
#include <stdio.h>
-static const char* opcode_to_string(TslOpcode opcode) {
+const char* tsl_opcode_to_string(TslOpcode opcode) {
switch(opcode) {
case TSL_OPCODE_LOADN: return "loadn";
case TSL_OPCODE_LOADB: return "loadb";
@@ -25,49 +25,49 @@ static const char* opcode_to_string(TslOpcode opcode) {
return "";
}
-void tsl_bytecode_writer_init(TslBytecodeWriter *self) {
+void tsl_bytecode_init(TslBytecode *self) {
tsl_buffer_init(&self->buffer);
}
-void tsl_bytecode_writer_deinit(TslBytecodeWriter *self) {
+void tsl_bytecode_deinit(TslBytecode *self) {
tsl_buffer_deinit(&self->buffer);
}
-int tsl_bytecode_writer_add_ins1(TslBytecodeWriter *self, TslOpcode opcode, int value) {
+int tsl_bytecode_add_ins1(TslBytecode *self, TslOpcode opcode, int value) {
TslInstructionType1 instruction;
instruction.opcode = opcode;
instruction.value = value;
- fprintf(stderr, "%s %d\n", opcode_to_string(opcode), value);
+ fprintf(stderr, "%s %d\n", tsl_opcode_to_string(opcode), value);
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
-int tsl_bytecode_writer_add_ins2(TslBytecodeWriter *self, TslOpcode opcode, double value) {
+int tsl_bytecode_add_ins2(TslBytecode *self, TslOpcode opcode, double value) {
TslInstructionType2 instruction;
instruction.opcode = opcode;
instruction.value = value;
- fprintf(stderr, "%s %f\n", opcode_to_string(opcode), value);
+ fprintf(stderr, "%s %f\n", tsl_opcode_to_string(opcode), value);
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
-int tsl_bytecode_writer_add_ins3(TslBytecodeWriter *self, TslOpcode opcode, TslBool value) {
+int tsl_bytecode_add_ins3(TslBytecode *self, TslOpcode opcode, TslBool value) {
TslInstructionType3 instruction;
instruction.opcode = opcode;
instruction.value = value;
- fprintf(stderr, "%s %s\n", opcode_to_string(opcode), value ? "true" : "false");
+ fprintf(stderr, "%s %s\n", tsl_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) {
+int tsl_bytecode_add_ins4(TslBytecode *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);
+ fprintf(stderr, "%s \"%.*s\"\n", tsl_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) {
+int tsl_bytecode_add_ins5(TslBytecode *self, TslOpcode opcode) {
TslInstructionType5 instruction;
instruction.opcode = opcode;
- fprintf(stderr, "%s\n", opcode_to_string(opcode));
+ fprintf(stderr, "%s\n", tsl_opcode_to_string(opcode));
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
diff --git a/src/main.c b/src/main.c
index b9d64a7..2166ff5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -53,9 +53,9 @@ static void usage() {
}
int main(int argc, char **argv) {
- int result;
- size_t filesize;
char *file_content;
+ size_t filesize;
+ TslProgram program;
if(argc != 2) {
usage();
@@ -65,7 +65,15 @@ int main(int argc, char **argv) {
file_content = file_get_content(argv[1], &filesize);
if(!file_content)
return 1;
- result = tsl_parse(file_content, filesize);
- free(file_content); /* Not needed, but it make valgrind happy */
- return result;
+
+ tsl_program_init(&program);
+ if(!tsl_parse(file_content, filesize, &program))
+ return 2;
+
+ if(!tsl_program_run(&program))
+ return 3;
+
+ free(file_content);
+ tsl_program_deinit(&program);
+ return 0;
}
diff --git a/src/parser.c b/src/parser.c
index 1dbfe48..608f670 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -12,7 +12,7 @@
typedef struct {
TslTokenizer tokenizer;
- TslBuffer /*TslBytecodeWriter*/ function_bytecode_list;
+ TslBuffer /*TslBytecode*/ function_bytecode_list;
TslBuffer /*int*/ function_bytecode_list_index;
} TslParser;
@@ -21,29 +21,30 @@ static int tsl_parser_get_current_function_index(TslParser *self) {
return *(int*)last_item;
}
-#define get_function_bytecode(self) ((TslBytecodeWriter*)tsl_buffer_begin(&self->function_bytecode_list) + tsl_parser_get_current_function_index(self))
+#define get_function_bytecode(self) ((TslBytecode*)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 int tsl_parser_init(TslParser *self, const char *code, size_t code_size) {
- TslBytecodeWriter bytecode_writer;
- int result = 1;
+ TslBytecode bytecode_writer;
+ int result1 = 1;
+ int result2 = 1;
size_t bytecode_index = 0;
tsl_tokenizer_init(&self->tokenizer, code, code_size);
- tsl_bytecode_writer_init(&bytecode_writer);
+ tsl_bytecode_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;
+ result1 = tsl_buffer_append(&self->function_bytecode_list, &bytecode_writer, sizeof(bytecode_writer));
+ result2 = tsl_buffer_append(&self->function_bytecode_list_index, &bytecode_index, sizeof(bytecode_index));
+ return result1 && result2;
}
static void tsl_parser_deinit(TslParser *self) {
- TslBytecodeWriter *bytecode_writer = tsl_buffer_begin(&self->function_bytecode_list);
- TslBytecodeWriter *bytecode_writer_end = tsl_buffer_end(&self->function_bytecode_list);
+ TslBytecode *bytecode_writer = tsl_buffer_begin(&self->function_bytecode_list);
+ TslBytecode *bytecode_writer_end = tsl_buffer_end(&self->function_bytecode_list);
while(bytecode_writer != bytecode_writer_end) {
- tsl_bytecode_writer_deinit(bytecode_writer);
+ tsl_bytecode_deinit(bytecode_writer);
++bytecode_writer;
}
tsl_buffer_deinit(&self->function_bytecode_list);
@@ -52,10 +53,10 @@ static void tsl_parser_deinit(TslParser *self) {
static TslParseResult tsl_parser_push_function(TslParser *self) {
int function_index;
- TslBytecodeWriter bytecode_writer;
- tsl_bytecode_writer_init(&bytecode_writer);
+ TslBytecode bytecode_writer;
+ tsl_bytecode_init(&bytecode_writer);
/* TODO: Use bitshift ? */
- function_index = self->function_bytecode_list.size / sizeof(TslBytecodeWriter);
+ function_index = self->function_bytecode_list.size / sizeof(TslBytecode);
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));
}
@@ -97,19 +98,19 @@ static TslParseResult tsl_parser_parse_map(TslParser *self, int *num_items) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
+ return_if_error(tsl_bytecode_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
parse_map_element_separator
} else if(token == TSL_TOKEN_BOOL) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
+ return_if_error(tsl_bytecode_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
parse_map_element_separator
} else if(token == TSL_TOKEN_NULL) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
+ return_if_error(tsl_bytecode_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
parse_map_element_separator
} else if(token == TSL_TOKEN_STRING) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADS, &self->tokenizer.string));
+ return_if_error(tsl_bytecode_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 */
@@ -139,19 +140,19 @@ static TslParseResult tsl_parser_parse_list(TslParser *self, int *num_items) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
+ return_if_error(tsl_bytecode_add_ins2(get_function_bytecode(self), TSL_OPCODE_LOADN, self->tokenizer.number_value));
parse_list_element_separator
} else if(token == TSL_TOKEN_BOOL) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
+ return_if_error(tsl_bytecode_add_ins3(get_function_bytecode(self), TSL_OPCODE_LOADB, self->tokenizer.bool_value));
parse_list_element_separator
} else if(token == TSL_TOKEN_NULL) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
+ return_if_error(tsl_bytecode_add_ins5(get_function_bytecode(self), TSL_OPCODE_LOADNULL));
parse_list_element_separator
} else if(token == TSL_TOKEN_STRING) {
++*num_items;
- return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADS, &self->tokenizer.string));
+ return_if_error(tsl_bytecode_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 */
@@ -200,7 +201,7 @@ 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_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET));
- return tsl_bytecode_writer_add_ins5(get_function_bytecode(self), TSL_OPCODE_MINDEX);
+ return tsl_bytecode_add_ins5(get_function_bytecode(self), TSL_OPCODE_MINDEX);
}
/* FUNC_CALL = '(' (RHS ',')* ')' */
@@ -239,7 +240,7 @@ static TslParseResult tsl_parser_parse_command(TslParser *self, int *num_args) {
TslCommandToken command_token = tsl_tokenizer_next_command_arg(&self->tokenizer, &command_arg);
if(command_token == TSL_COMMAND_TOKEN_ARG) {
++*num_args;
- return_if_error(tsl_bytecode_writer_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADCA, &command_arg));
+ return_if_error(tsl_bytecode_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 {
@@ -270,14 +271,14 @@ static TslParseResult tsl_parser_parse_rhs_sub(TslParser *self) {
} else if(token == TSL_TOKEN_LPAREN) {
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_if_error(tsl_bytecode_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 */
arithmetic_opcode = arithmetic_symbol_to_opcode(self->tokenizer.arithmetic_symbol);
/* TODO: Handle arithmetic expression precedence */
- return tsl_parser_parse_rhs(self) && tsl_bytecode_writer_add_ins5(get_function_bytecode(self), arithmetic_opcode);
+ return tsl_parser_parse_rhs(self) && tsl_bytecode_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
@@ -308,27 +309,27 @@ TslParseResult tsl_parser_parse_rhs(TslParser *self) {
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_if_error(tsl_bytecode_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_if_error(tsl_bytecode_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);
+ return tsl_bytecode_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);
+ return tsl_bytecode_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);
+ return tsl_bytecode_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);
+ tsl_bytecode_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);
+ tsl_bytecode_add_ins1(get_function_bytecode(self), TSL_OPCODE_LIST, num_items);
}
case TSL_TOKEN_FN: {
int function_index;
@@ -336,12 +337,12 @@ TslParseResult tsl_parser_parse_rhs(TslParser *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);
+ return tsl_bytecode_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);
+ tsl_bytecode_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));
@@ -361,10 +362,10 @@ TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token)
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_add_ins4(get_function_bytecode(self), TSL_OPCODE_SETV, &identifier));
+ return_if_error(tsl_bytecode_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_bytecode_add_ins4(get_function_bytecode(self), TSL_OPCODE_LOADV, &identifier));
return_if_error(tsl_parser_parse_rhs_sub(self));
}
} else if(token == end_token) {
@@ -377,11 +378,20 @@ TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token)
return TSL_PARSE_RESULT_OK;
}
-TslParseResult tsl_parse(const char *code, size_t code_size) {
+TslParseResult tsl_parse(const char *code, size_t code_size, TslProgram *program_output) {
TslParseResult result;
TslParser parser;
+
+ assert(code);
+ assert(program_output);
+
+ tsl_program_init(program_output);
return_if_error(tsl_parser_init(&parser, code, code_size));
+
result = tsl_parser_parse_expressions(&parser, TSL_TOKEN_END_OF_FILE);
+ if(result == TSL_PARSE_RESULT_OK)
+ tsl_buffer_move(&program_output->function_bytecode_list, &parser.function_bytecode_list);
+
tsl_parser_deinit(&parser);
return result;
}
diff --git a/src/program.c b/src/program.c
new file mode 100644
index 0000000..862931a
--- /dev/null
+++ b/src/program.c
@@ -0,0 +1,122 @@
+#include "../include/program.h"
+#include "../include/bytecode.h"
+#include <stdio.h>
+
+void tsl_program_init(TslProgram *self) {
+ tsl_buffer_init(&self->function_bytecode_list);
+ tsl_hash_map_init(&self->variables);
+}
+
+void tsl_program_deinit(TslProgram *self) {
+ TslBytecode *bytecode_writer = tsl_buffer_begin(&self->function_bytecode_list);
+ TslBytecode *bytecode_writer_end = tsl_buffer_end(&self->function_bytecode_list);
+ while(bytecode_writer != bytecode_writer_end) {
+ tsl_bytecode_deinit(bytecode_writer);
+ ++bytecode_writer;
+ }
+ tsl_buffer_deinit(&self->function_bytecode_list);
+ tsl_hash_map_deinit(&self->variables);
+}
+
+TslProgramResult tsl_program_run(TslProgram *self) {
+ 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");
+ /* TODO: Verify if these don't cause unaligned memory access on non-x86 platforms */
+ while(instruction != instruction_end) {
+ TslOpcode opcode = *(TslOpcode*)instruction;
+ TslInstructionType1 *instruction_type1 = (TslInstructionType1*)instruction;
+ TslInstructionType2 *instruction_type2 = (TslInstructionType2*)instruction;
+ TslInstructionType3 *instruction_type3 = (TslInstructionType3*)instruction;
+ TslInstructionType4 *instruction_type4 = (TslInstructionType4*)instruction;
+ switch(opcode) {
+ case TSL_OPCODE_LOADN: {
+ printf("loadn %f\n", instruction_type2->value);
+ instruction += sizeof(TslInstructionType2);
+ break;
+ }
+ case TSL_OPCODE_LOADB: {
+ printf("loadb %s\n", instruction_type3->value ? "true" : "false");
+ instruction += sizeof(TslInstructionType3);
+ break;
+ }
+ case TSL_OPCODE_LOADS: {
+ printf("loads \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
+ instruction += sizeof(TslInstructionType4);
+ break;
+ }
+ case TSL_OPCODE_LOADF: {
+ printf("loadf %d\n", instruction_type1->value);
+ instruction += sizeof(TslInstructionType1);
+ break;
+ }
+ case TSL_OPCODE_LOADV: {
+ printf("loadv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
+ instruction += sizeof(TslInstructionType4);
+ break;
+ }
+ case TSL_OPCODE_LOADNULL: {
+ printf("loadnull\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_SETV: {
+ printf("setv \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
+ instruction += sizeof(TslInstructionType4);
+ break;
+ }
+ case TSL_OPCODE_LIST: {
+ printf("list %d\n", instruction_type1->value);
+ instruction += sizeof(TslInstructionType1);
+ break;
+ }
+ case TSL_OPCODE_MAP: {
+ printf("map %d\n", instruction_type1->value);
+ instruction += sizeof(TslInstructionType1);
+ break;
+ }
+ case TSL_OPCODE_MINDEX: {
+ printf("mindex\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_CALLF: {
+ printf("callf %d\n", instruction_type1->value);
+ instruction += sizeof(TslInstructionType1);
+ break;
+ }
+ case TSL_OPCODE_ADD: {
+ printf("add\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_SUB: {
+ printf("sub\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_MUL: {
+ printf("mul\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_DIV: {
+ printf("div\n");
+ instruction += sizeof(TslInstructionType5);
+ break;
+ }
+ case TSL_OPCODE_LOADCA: {
+ printf("loadca \"%.*s\"\n", (int)instruction_type4->value.size, instruction_type4->value.data);
+ instruction += sizeof(TslInstructionType4);
+ break;
+ }
+ case TSL_OPCODE_CALLC: {
+ printf("callc %d\n", instruction_type1->value);
+ instruction += sizeof(TslInstructionType1);
+ break;
+ }
+ }
+ }
+ return TSL_PROGRAM_RESULT_OK;
+}
diff --git a/src/std/buffer.c b/src/std/buffer.c
index dd7d0f6..343173a 100644
--- a/src/std/buffer.c
+++ b/src/std/buffer.c
@@ -12,6 +12,8 @@ void tsl_buffer_init(TslBuffer *self) {
void tsl_buffer_deinit(TslBuffer *self) {
free(self->data);
+ self->size = 0;
+ self->capacity = 0;
}
static int tsl_buffer_ensure_capacity(TslBuffer *self, size_t new_size) {
@@ -57,3 +59,12 @@ void* tsl_buffer_begin(TslBuffer *self) {
void* tsl_buffer_end(TslBuffer *self) {
return (char*)self->data + self->size;
}
+
+void tsl_buffer_move(TslBuffer *dst, TslBuffer *src) {
+ dst->data = src->data;
+ dst->size = src->size;
+ dst->capacity = src->capacity;
+ src->data = NULL;
+ src->size = 0;
+ src->capacity = 0;
+}