aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-01-22 03:03:37 +0100
committerdec05eba <dec05eba@protonmail.com>2020-01-22 03:03:37 +0100
commita724ddbe1c8c53acd8b2836e437237cf17c57043 (patch)
tree212de4293dbb01400d0251f1478484e8eee60f70
parent88244bd3070399ba62d79bae6dfdf8b09ff8406d (diff)
Use macro return_if_error instead of if-statement everywhere
-rw-r--r--Makefile4
-rw-r--r--include/parser.h8
-rw-r--r--src/bytecode.c4
-rw-r--r--src/parser.c198
-rw-r--r--src/std/hash_map.c5
5 files changed, 111 insertions, 108 deletions
diff --git a/Makefile b/Makefile
index 399128b..15de48f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-CFLAGS = -Wall -Wextra -g3 -ansi -pedantic -fPIE
-LIBS = -Wl,-Bdynamic -lcurl
+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
CC = cc
diff --git a/include/parser.h b/include/parser.h
index d130597..b915dfd 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -3,7 +3,11 @@
#include "tokenizer.h"
-/* Returns 0 on success */
-int tsl_parse(const char *code, size_t code_size);
+typedef enum {
+ TSL_PARSE_RESULT_ERR,
+ TSL_PARSE_RESULT_OK
+} TslParseResult;
+
+TslParseResult tsl_parse(const char *code, size_t code_size);
#endif /* TSL_PARSER_H */
diff --git a/src/bytecode.c b/src/bytecode.c
index a0b5406..9406852 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1,5 +1,6 @@
#include "../include/bytecode.h"
#include <assert.h>
+#include <stdio.h>
void tsl_bytecode_writer_init(TslBytecodeWriter *self) {
tsl_buffer_init(&self->buffer);
@@ -17,6 +18,7 @@ void tsl_bytecode_writer_reset_register_counter(TslBytecodeWriter *self) {
TslRegister tsl_bytecode_writer_get_unique_register(TslBytecodeWriter *self) {
if(self->register_counter < INT16_MAX)
return self->register_counter++;
+ fprintf(stderr, "Error: Too many variables in the same scope\n");
return -1;
}
@@ -28,7 +30,7 @@ int tsl_bytecode_writer_load_number(TslBytecodeWriter *self, TslRegister dst, do
return tsl_buffer_append(&self->buffer, &instruction, sizeof(instruction));
}
-tsl_bytecode_writer_mov_reg(TslBytecodeWriter *self, TslRegister dst, TslRegister src) {
+int tsl_bytecode_writer_mov_reg(TslBytecodeWriter *self, TslRegister dst, TslRegister src) {
TslInstructionType2 instruction;
instruction.opcode = TSL_OPCODE_MOV_REG;
instruction.dst_reg = dst;
diff --git a/src/parser.c b/src/parser.c
index be3461c..bad630e 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -2,6 +2,13 @@
#include "../include/bytecode.h"
#include "../include/std/hash_map.h"
#include <stdio.h>
+#include <assert.h>
+
+#define return_if_error(expr) \
+ { \
+ if(!(expr)) \
+ return TSL_PARSE_RESULT_ERR;\
+ }
typedef struct {
TslTokenizer tokenizer;
@@ -9,8 +16,8 @@ typedef struct {
TslHashMap variables;
} TslParser;
-static int tsl_parser_parse_rhs(TslParser *self);
-static int tsl_parser_parse_expressions(TslParser *self, TslToken end_token);
+static TslParseResult tsl_parser_parse_rhs(TslParser *self, TslRegister *reg_result);
+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) {
tsl_tokenizer_init(&self->tokenizer, code, code_size);
@@ -23,6 +30,7 @@ static void tsl_parser_deinit(TslParser *self) {
tsl_hash_map_deinit(&self->variables);
}
+#if 0
static uint64_t hash_string_view(const void *data, size_t size) {
uint64_t result = 0xdec05eba;
const uint8_t *p = data;
@@ -33,27 +41,27 @@ static uint64_t hash_string_view(const void *data, size_t size) {
}
return result;
}
+#endif
-static int tsl_parser_parse_map(TslParser *self) {
- #define parse_map_element_separator \
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON)) \
- return -1; \
- if(tsl_parser_parse_rhs(self) != 0) \
- return -1; \
- token = tsl_tokenizer_next(&self->tokenizer); \
- if(token == TSL_TOKEN_COMMA) { \
- continue; \
- } else if(token == TSL_TOKEN_RBRACE) { \
- return 0; \
- } else { \
- fprintf(stderr, "Error: Expected ',' or '}', got TODO\n"); \
- return -1; \
+static TslParseResult tsl_parser_parse_map(TslParser *self) {
+ TslRegister src_reg;
+ #define parse_map_element_separator \
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_COLON)); \
+ return_if_error(tsl_parser_parse_rhs(self, &src_reg)); \
+ token = tsl_tokenizer_next(&self->tokenizer); \
+ if(token == TSL_TOKEN_COMMA) { \
+ continue; \
+ } else if(token == TSL_TOKEN_RBRACE) { \
+ return TSL_PARSE_RESULT_OK; \
+ } else { \
+ fprintf(stderr, "Error: Expected ',' or '}', got TODO\n"); \
+ return TSL_PARSE_RESULT_ERR; \
}
for(;;) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
- printf("rhs num: %ld\n", self->tokenizer.number_value);
+ printf("rhs num: %f\n", 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");
@@ -62,37 +70,37 @@ static int tsl_parser_parse_map(TslParser *self) {
printf("rhs null\n");
parse_map_element_separator
} else if(token == TSL_TOKEN_STRING) {
- printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
+ printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data);
parse_map_element_separator
} else if(token == TSL_TOKEN_RBRACE) {
/* '}' after trailing ',' or an empty map */
- return 0;
+ return TSL_PARSE_RESULT_OK;
} else {
fprintf(stderr, "Error: Expected '}', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
token = tsl_tokenizer_next(&self->tokenizer);
}
}
-static int tsl_parser_parse_list(TslParser *self) {
+static TslParseResult tsl_parser_parse_list(TslParser *self) {
#define parse_list_element_separator \
token = tsl_tokenizer_next(&self->tokenizer); \
if(token == TSL_TOKEN_COMMA) { \
continue; \
} else if(token == TSL_TOKEN_RBRACKET) { \
- return 0; \
+ return TSL_PARSE_RESULT_OK; \
} else { \
fprintf(stderr, "Error: Expected ',' or ']', got TODO\n"); \
- return -1; \
+ return TSL_PARSE_RESULT_ERR; \
}
for(;;) {
/* TODO: Use tsl_parser_parse_rhs instead */
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_NUM) {
- printf("rhs num: %ld\n", self->tokenizer.number_value);
+ printf("rhs num: %f\n", 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");
@@ -101,36 +109,34 @@ static int tsl_parser_parse_list(TslParser *self) {
printf("rhs null\n");
parse_list_element_separator
} else if(token == TSL_TOKEN_STRING) {
- printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
+ printf("rhs string: |%.*s|\n", (int)self->tokenizer.string.size, self->tokenizer.string.data);
parse_list_element_separator
} else if(token == TSL_TOKEN_RBRACKET) {
/* ']' after trailing ',' or an empty list */
- return 0;
+ return TSL_PARSE_RESULT_OK;
} else {
fprintf(stderr, "Error: Expected '}', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
}
}
/* FN_BODY = '{' EXPRS '}' */
-static int tsl_parser_parse_fn_body(TslParser *self) {
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACE))
- return -1;
+static TslParseResult tsl_parser_parse_fn_body(TslParser *self) {
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACE));
return tsl_parser_parse_expressions(self, TSL_TOKEN_RBRACE);
}
/* FN = '(' (IDENTIFIER ',')* ')' FN_BODY */
-static int tsl_parser_parse_fn(TslParser *self) {
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN))
- return -1;
-
+static TslParseResult tsl_parser_parse_fn(TslParser *self) {
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN));
for(;;) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_RPAREN) {
return tsl_parser_parse_fn_body(self);
} else if(token == TSL_TOKEN_IDENTIFIER) {
TslStringView param_name = self->tokenizer.identifier;
+ printf("function parameter: |%.*s|\n", (int)param_name.size, param_name.data);
token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_COMMA) {
continue;
@@ -138,50 +144,42 @@ static int tsl_parser_parse_fn(TslParser *self) {
return tsl_parser_parse_fn_body(self);
} else {
fprintf(stderr, "Error: Expected ',' or ')', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
} else {
fprintf(stderr, "Error: Expected parameter name or ')', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
}
}
/* VAR_INDEX = '[' RHS ']' */
-static int tsl_parser_parse_var_indexing(TslParser *self) {
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACKET))
- return -1;
-
- if(tsl_parser_parse_rhs(self) != 0)
- return -1;
-
- if(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET))
- return 0;
- else
- return -1;
+static TslParseResult tsl_parser_parse_var_indexing(TslParser *self) {
+ TslRegister src_reg;
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LBRACKET));
+ return_if_error(tsl_parser_parse_rhs(self, &src_reg));
+ return tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_RBRACKET);
}
/* FUNC_CALL = '(' (RHS ',')* ')' */
-static int tsl_parser_parse_func_call(TslParser *self) {
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN))
- return -1;
-
+static TslParseResult tsl_parser_parse_func_call(TslParser *self) {
+ return_if_error(tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN));
for(;;) {
TslToken token = tsl_tokenizer_peek(&self->tokenizer);
if(token == TSL_TOKEN_RPAREN) {
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_RPAREN */
- return 0;
+ return TSL_PARSE_RESULT_OK;
} else {
- if(tsl_parser_parse_rhs(self) != 0)
- return -1;
+ TslRegister src_reg;
+ return_if_error(tsl_parser_parse_rhs(self, &src_reg));
token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_COMMA) {
continue;
} else if(token == TSL_TOKEN_RPAREN) {
- return 0;
+ return TSL_PARSE_RESULT_OK;
} else {
fprintf(stderr, "Error: Expected ',' or ')', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
}
}
@@ -190,140 +188,144 @@ static int tsl_parser_parse_func_call(TslParser *self) {
/* TODO: Do not allow empty command */
/* TODO: Allow command inside another command */
/* COMMAND = TODO */
-static int tsl_parser_parse_command(TslParser *self) {
- if(!tsl_tokenizer_accept(&self->tokenizer, TSL_TOKEN_LPAREN))
- return -1;
-
+static TslParseResult tsl_parser_parse_command(TslParser *self) {
+ 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);
} else if(command_token == TSL_COMMAND_TOKEN_END) {
- return 0;
+ return TSL_PARSE_RESULT_OK;
} else {
fprintf(stderr, "Error: Expected command argument or ')', got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
}
}
/* RHS_SUB = (VAR_INDEX|FUNC_CALL RHS_SUB?)|(TOKEN_ARITHMETIC RHS) */
-static int tsl_parser_parse_rhs_sub(TslParser *self) {
+static TslParseResult tsl_parser_parse_rhs_sub(TslParser *self) {
TslToken token = tsl_tokenizer_peek(&self->tokenizer);
if(token == TSL_TOKEN_LBRACKET) {
- if(tsl_parser_parse_var_indexing(self) != 0)
- return -1;
+ return_if_error(tsl_parser_parse_var_indexing(self));
return tsl_parser_parse_rhs_sub(self);
} else if(token == TSL_TOKEN_LPAREN) {
- if(tsl_parser_parse_func_call(self) != 0)
- return -1;
+ return_if_error(tsl_parser_parse_func_call(self));
return tsl_parser_parse_rhs_sub(self);
} else if(token == TSL_TOKEN_ARITHMETIC) {
+ TslRegister src_reg;
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_ARITHMETIC */
printf("rhs sub arithmetic symbol: %c\n", self->tokenizer.arithmetic_symbol);
/* TODO: Handle arithmetic expression precedence */
- return tsl_parser_parse_rhs(self);
+ return tsl_parser_parse_rhs(self, &src_reg);
}
/*
No sub expression found, possibly a new expression after this (a new expression on a new line), let that
part of the code handle error if there is any instead.
*/
- return 0;
+ return TSL_PARSE_RESULT_OK;
}
/* RHS_SUB_ARITHMETIC = TOKEN_ARITHMETIC RHS */
-static int tsl_parser_parse_rhs_sub_arithmetic(TslParser *self) {
+static TslParseResult tsl_parser_parse_rhs_sub_arithmetic(TslParser *self) {
TslToken token = tsl_tokenizer_peek(&self->tokenizer);
if(token == TSL_TOKEN_ARITHMETIC) {
+ TslRegister src_reg;
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_ARITHMETIC */
printf("rhs sub arithmetic symbol: %c\n", self->tokenizer.arithmetic_symbol);
/* TODO: Handle arithmetic expression precedence */
- return tsl_parser_parse_rhs(self);
+ return tsl_parser_parse_rhs(self, &src_reg);
}
/*
No sub expression found, possibly a new expression after this (a new expression on a new line), let that
part of the code handle error if there is any instead.
*/
- return 0;
+ return TSL_PARSE_RESULT_OK;
}
/* RHS = (IDENTIFIER|NUM|BOOL|NULL|STRING|MAP|LIST|('fn' FN)|('$' COMMAND)) RHS_SUB? */
-int tsl_parser_parse_rhs(TslParser *self) {
+TslParseResult tsl_parser_parse_rhs(TslParser *self, TslRegister *reg_result) {
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) {
- TslRegister dst_reg = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer);
- if(dst_reg == -1) {
+ *reg_result = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer);
+ if(*reg_result == -1) {
fprintf(stderr, "Error: Too many registers used\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
- if(!tsl_bytecode_writer_load_number(&self->bytecode_writer, dst_reg, self->tokenizer.number_value))
- return -1;
-
+ return_if_error(tsl_bytecode_writer_load_number(&self->bytecode_writer, *reg_result, 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) {
+ assert(0 && "TODO: Implement");
printf("rhs bool: %s\n", self->tokenizer.bool_value ? "true" : "false");
} else if(token == TSL_TOKEN_NULL) {
+ assert(0 && "TODO: Implement");
printf("rhs null\n");
} else if(token == TSL_TOKEN_STRING) {
- printf("rhs string: |%.*s|\n", self->tokenizer.string.size, self->tokenizer.string.data);
+ 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 -1;
+ return TSL_PARSE_RESULT_ERR;
}
- return 0;
+ return TSL_PARSE_RESULT_OK;
}
/*
EXPR = IDENTIFIER ('=' RHS)|RHS_SUB
EXPRS = EXPR*
*/
-int tsl_parser_parse_expressions(TslParser *self, TslToken end_token) {
+TslParseResult tsl_parser_parse_expressions(TslParser *self, TslToken end_token) {
for(;;) {
TslToken token = tsl_tokenizer_next(&self->tokenizer);
if(token == TSL_TOKEN_IDENTIFIER) {
TslStringView identifier = self->tokenizer.identifier;
- printf("identifier: %.*s\n", identifier.size, identifier.data);
+ printf("identifier: %.*s\n", (int)identifier.size, identifier.data);
if(tsl_tokenizer_peek(&self->tokenizer) == TSL_TOKEN_EQUAL) {
- void *existing_variable = tsl_hash_map_get(&self->variables, &identifier, hash_string_view);
- if(!existing_variable) {
- fprintf(stderr, "Variable declaration: %.*s\n", identifier.size, identifier.data);
- if(!tsl_hash_map_insert(&self->variables, &identifier, "a", 1, hash_string_view))
- return -1;
- }
+ TslRegister dst_reg;
+ TslRegister src_reg;
+
tsl_tokenizer_consume_peek(&self->tokenizer); /* consume previous TSL_TOKEN_EQUAL */
- if(tsl_parser_parse_rhs(self) != 0)
- return -1;
+ return_if_error(tsl_parser_parse_rhs(self, &src_reg));
+
+ dst_reg = tsl_bytecode_writer_get_unique_register(&self->bytecode_writer);
+ if(dst_reg < 0)
+ return TSL_PARSE_RESULT_ERR;
+ return_if_error(tsl_bytecode_writer_mov_reg(&self->bytecode_writer, dst_reg, src_reg));
} else {
- if(tsl_parser_parse_rhs_sub(self) != 0)
- return -1;
+ return_if_error(tsl_parser_parse_rhs_sub(self));
}
} else if(token == end_token) {
break;
} else {
fprintf(stderr, "Error: Expected identifier, got TODO\n");
- return -1;
+ return TSL_PARSE_RESULT_ERR;
}
}
- return 0;
+ return TSL_PARSE_RESULT_OK;
}
-int tsl_parse(const char *code, size_t code_size) {
- int result;
+TslParseResult tsl_parse(const char *code, size_t code_size) {
+ TslParseResult result;
TslParser parser;
tsl_parser_init(&parser, code, code_size);
result = tsl_parser_parse_expressions(&parser, TSL_TOKEN_END_OF_FILE);
diff --git a/src/std/hash_map.c b/src/std/hash_map.c
index 44d36db..968a5ea 100644
--- a/src/std/hash_map.c
+++ b/src/std/hash_map.c
@@ -10,11 +10,6 @@ struct TslHashMapNode {
TslHashMapNode *next;
};
-static void hash_map_node_init(TslHashMapNode *self) {
- self->data = NULL;
- self->next = NULL;
-}
-
static void hash_map_node_get(TslHashMapNode *self, uint64_t *hash, TslStringView *key, size_t *size, uint8_t **data) {
memcpy(hash, (uint8_t*)self->data, sizeof(uint64_t));
memcpy(&key->size, (uint8_t*)self->data + sizeof(uint64_t), sizeof(key->size));