From cc30a97ab90a8fa40707936d3d089d81c49559b6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 23 Jan 2020 03:09:54 +0100 Subject: Add bytecode decoding.. starting on program execution now --- Makefile | 5 ++- README.md | 3 +- include/bytecode.h | 30 +++++++------ include/parser.h | 7 ++- include/program.h | 22 ++++++++++ include/std/buffer.h | 1 + src/bytecode.c | 26 +++++------ src/main.c | 18 +++++--- src/parser.c | 86 ++++++++++++++++++++---------------- src/program.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/std/buffer.c | 11 +++++ 11 files changed, 258 insertions(+), 73 deletions(-) create mode 100644 include/program.h create mode 100644 src/program.c 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 #include -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 + +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; +} -- cgit v1.2.3