summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c29
-rw-r--r--src/array.h32
-rw-r--r--src/lexer.c84
-rw-r--r--src/lexer.h27
-rw-r--r--src/main.c22
-rw-r--r--src/parser.c319
-rw-r--r--src/parser.h8
-rw-r--r--src/stack.c29
-rw-r--r--src/stack.h12
-rw-r--r--src/string_view.c6
-rw-r--r--src/string_view.h11
-rw-r--r--src/utils.c10
-rw-r--r--src/utils.h4
-rw-r--r--src/vm.c366
-rw-r--r--src/vm.h90
15 files changed, 531 insertions, 518 deletions
diff --git a/src/array.c b/src/array.c
index 876ba11..6bdfa72 100644
--- a/src/array.c
+++ b/src/array.c
@@ -15,15 +15,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <assert.h>
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include "array.h"
-void *
+void*
array_new(size_t item_size)
{
- array_header_t *h = malloc((item_size * ARRAY_INITIAL_CAPACITY) + sizeof(array_header_t));
+ array_header_t* h =
+ malloc((item_size * ARRAY_INITIAL_CAPACITY) + sizeof(array_header_t));
if (h == NULL) {
return NULL;
}
@@ -33,25 +34,25 @@ array_new(size_t item_size)
return h + sizeof(array_header_t);
}
-array_header_t *
-array_get_header(void *arr)
+array_header_t*
+array_get_header(void* arr)
{
- return (array_header_t *) arr - sizeof(array_header_t);
+ return (array_header_t*)arr - sizeof(array_header_t);
}
-void *
-array_grow(void *arr)
+void*
+array_grow(void* arr)
{
- array_header_t *h = array_get_header(arr);
- h->capacity *= 2;
- h = realloc(h, sizeof(array_header_t) + (h->capacity * h->item_size));
- return h + sizeof(array_header_t);
+ array_header_t* h = array_get_header(arr);
+ h->capacity *= 2;
+ h = realloc(h, sizeof(array_header_t) + (h->capacity * h->item_size));
+ return h + sizeof(array_header_t);
}
size_t
-array_length(void *arr)
+array_length(void* arr)
{
assert(arr);
- array_header_t *header = array_get_header(arr);
+ array_header_t* header = array_get_header(arr);
return header->length;
}
diff --git a/src/array.h b/src/array.h
index 5119e7e..a98b92a 100644
--- a/src/array.h
+++ b/src/array.h
@@ -20,32 +20,34 @@
#define ARRAY_INITIAL_CAPACITY 4
-#define array(T) (T *)array_new(sizeof(T))
-
-#define array_append(arr, item) do { \
- array_header_t *h = array_get_header(arr); \
- if (h->capacity < h->length + 1) { \
- arr = array_grow(arr); \
- } \
- arr[h->length++] = item; \
+#define array(T) (T*)array_new(sizeof(T))
+
+#define array_append(arr, item) \
+ do { \
+ array_header_t* h = array_get_header(arr); \
+ if (h->capacity < h->length + 1) { \
+ arr = array_grow(arr); \
+ } \
+ arr[h->length++] = item; \
} while (0)
-typedef struct array_header {
+typedef struct array_header
+{
size_t capacity;
size_t item_size;
size_t length;
} array_header_t;
-void *
+void*
array_new(size_t item_size);
-array_header_t *
-array_get_header(void *arr);
+array_header_t*
+array_get_header(void* arr);
-void *
-array_grow(void *arr);
+void*
+array_grow(void* arr);
size_t
-array_length(void *arr);
+array_length(void* arr);
#endif /* ARRAY_H */
diff --git a/src/lexer.c b/src/lexer.c
index 19265c8..9258ec3 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -14,40 +14,40 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include "lexer.h"
+#include "array.h"
+#include "string_view.h"
+#include "utils.h"
#include <assert.h>
+#include <ctype.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stdbool.h>
-#include <ctype.h>
-#include "utils.h"
-#include "array.h"
-#include "string_view.h"
-#include "lexer.h"
void
-lexer_init(lexer_t *lexer, char *file_name)
+lexer_init(lexer_t* lexer, char* file_name)
{
assert(lexer);
- char *program = read_file_contents(file_name);
+ char* program = read_file_contents(file_name);
if (program == NULL) {
fprintf(stderr, "Unable to read file <%s>\n", file_name);
exit(EXIT_FAILURE);
}
lexer->file_name = file_name;
- lexer->loc = (lex_loc_t) { 0 };
+ lexer->loc = (lex_loc_t){ 0 };
lexer->source = string_view_from_cstr(program);
}
bool
-lexer_is_eof(lexer_t *lexer)
+lexer_is_eof(lexer_t* lexer)
{
return !(lexer->loc.offset < lexer->source.size);
}
char
-lexer_current_char(lexer_t *lexer)
+lexer_current_char(lexer_t* lexer)
{
return lexer->source.chars[lexer->loc.offset];
}
@@ -59,7 +59,7 @@ _isspace(char c)
}
char
-lexer_next_char(lexer_t *lexer)
+lexer_next_char(lexer_t* lexer)
{
assert(lexer->loc.offset < lexer->source.size);
char previous_char = lexer_current_char(lexer);
@@ -73,10 +73,10 @@ lexer_next_char(lexer_t *lexer)
}
void
-lexer_next_token(lexer_t *lexer, token_t *token)
+lexer_next_token(lexer_t* lexer, token_t* token)
{
if (lexer_is_eof(lexer)) {
- *token = (token_t) { .kind = TOKEN_EOF };
+ *token = (token_t){ .kind = TOKEN_EOF };
return;
}
@@ -88,14 +88,16 @@ lexer_next_token(lexer_t *lexer, token_t *token)
}
if (lexer_is_eof(lexer)) {
- *token = (token_t) { .kind = TOKEN_EOF };
+ *token = (token_t){ .kind = TOKEN_EOF };
return;
}
if (c == '\n') {
token->kind = TOKEN_EOS;
token->loc = lexer->loc;
- token->value = (string_view_t) { .size = 1, .chars = lexer->source.chars + lexer->loc.offset };
+ token->value =
+ (string_view_t){ .size = 1,
+ .chars = lexer->source.chars + lexer->loc.offset };
lexer_next_char(lexer);
return;
}
@@ -223,46 +225,34 @@ lexer_next_token(lexer_t *lexer, token_t *token)
if (c == ':') {
token->kind = TOKEN_COLON;
- token->value = (string_view_t) { .size = 1, .chars = lexer->source.chars + lexer->loc.offset};
+ token->value =
+ (string_view_t){ .size = 1,
+ .chars = lexer->source.chars + lexer->loc.offset };
token->loc = lexer->loc;
lexer_next_char(lexer);
return;
}
}
-static char *token_to_cstr_table[] = {
- [TOKEN_KW_PUSH] = "push",
- [TOKEN_KW_DUP] = "dup",
- [TOKEN_KW_COPY] = "copy",
- [TOKEN_KW_SWAP] = "swap",
- [TOKEN_KW_DROP] = "drop",
- [TOKEN_KW_SLIDE] = "slide",
- [TOKEN_KW_ADD] = "add",
- [TOKEN_KW_SUB] = "sub",
- [TOKEN_KW_MUL] = "mul",
- [TOKEN_KW_DIV] = "div",
- [TOKEN_KW_MOD] = "mod",
- [TOKEN_KW_STORE] = "store",
- [TOKEN_KW_LOAD] = "load",
- [TOKEN_KW_CALL] = "call",
- [TOKEN_KW_RET] = "ret",
- [TOKEN_KW_JMP] = "jmp",
- [TOKEN_KW_JMPZ] = "jz",
- [TOKEN_KW_JMPN] = "jn",
- [TOKEN_KW_PRINTI] = "printi",
- [TOKEN_KW_PRINTC] = "printc",
- [TOKEN_KW_READI] = "readi",
- [TOKEN_KW_READC] = "readc",
- [TOKEN_KW_END] = "end",
- [TOKEN_IDENT] = "identifier",
- [TOKEN_EOS] = "<eos>",
- [TOKEN_NUMBER] = "number",
- [TOKEN_COLON] = ":",
- [TOKEN_UNKOWN] = "<unkown>",
+static char* token_to_cstr_table[] = {
+ [TOKEN_KW_PUSH] = "push", [TOKEN_KW_DUP] = "dup",
+ [TOKEN_KW_COPY] = "copy", [TOKEN_KW_SWAP] = "swap",
+ [TOKEN_KW_DROP] = "drop", [TOKEN_KW_SLIDE] = "slide",
+ [TOKEN_KW_ADD] = "add", [TOKEN_KW_SUB] = "sub",
+ [TOKEN_KW_MUL] = "mul", [TOKEN_KW_DIV] = "div",
+ [TOKEN_KW_MOD] = "mod", [TOKEN_KW_STORE] = "store",
+ [TOKEN_KW_LOAD] = "load", [TOKEN_KW_CALL] = "call",
+ [TOKEN_KW_RET] = "ret", [TOKEN_KW_JMP] = "jmp",
+ [TOKEN_KW_JMPZ] = "jz", [TOKEN_KW_JMPN] = "jn",
+ [TOKEN_KW_PRINTI] = "printi", [TOKEN_KW_PRINTC] = "printc",
+ [TOKEN_KW_READI] = "readi", [TOKEN_KW_READC] = "readc",
+ [TOKEN_KW_END] = "end", [TOKEN_IDENT] = "identifier",
+ [TOKEN_EOS] = "<eos>", [TOKEN_NUMBER] = "number",
+ [TOKEN_COLON] = ":", [TOKEN_UNKOWN] = "<unkown>",
[TOKEN_EOF] = "<eof>",
};
-char *
+char*
token_to_cstr(token_kind_t kind)
{
return token_to_cstr_table[kind];
diff --git a/src/lexer.h b/src/lexer.h
index b9c5b48..d03e621 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -18,8 +18,8 @@
#define LEXER_H
#include "string_view.h"
-
-typedef enum token_kind {
+typedef enum token_kind
+{
TOKEN_KW_PUSH,
TOKEN_KW_DUP,
TOKEN_KW_COPY,
@@ -51,40 +51,43 @@ typedef enum token_kind {
TOKEN_EOF
} token_kind_t;
-typedef struct lex_loc {
+typedef struct lex_loc
+{
size_t offset;
size_t lineoffset;
size_t lineno;
} lex_loc_t;
-typedef struct token {
+typedef struct token
+{
token_kind_t kind;
string_view_t value;
lex_loc_t loc;
} token_t;
-typedef struct lexer {
- char *file_name;
+typedef struct lexer
+{
+ char* file_name;
string_view_t source;
lex_loc_t loc;
} lexer_t;
void
-lexer_init(lexer_t *lexer, char *file_name);
+lexer_init(lexer_t* lexer, char* file_name);
bool
-lexer_is_eof(lexer_t *lexer);
+lexer_is_eof(lexer_t* lexer);
char
-lexer_current_char(lexer_t *lexer);
+lexer_current_char(lexer_t* lexer);
char
-lexer_next_char(lexer_t *lexer);
+lexer_next_char(lexer_t* lexer);
void
-lexer_next_token(lexer_t *lexer, token_t *token);
+lexer_next_token(lexer_t* lexer, token_t* token);
-char *
+char*
token_to_cstr(token_kind_t kind);
#endif /* LEXER_H */
diff --git a/src/main.c b/src/main.c
index d58027f..5c38510 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,30 +14,30 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
-#include <stdlib.h>
#include "array.h"
#include "lexer.h"
#include "parser.h"
+#include <stdio.h>
+#include <stdlib.h>
int
-main(int argc, char **argv)
+main(int argc, char** argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s file.wsa\n", argv[0]);
return EXIT_FAILURE;
}
- vm_t vm;
- vm_init(&vm);
+ vm_t vm;
+ vm_init(&vm);
- char *file_name = argv[1];
+ char* file_name = argv[1];
- parser_t parser;
- parser_init(&parser, file_name);
+ parser_t parser;
+ parser_init(&parser, file_name);
- inst_t *insts = parser_parse(&parser);
- vm_run(&vm, insts);
+ inst_t* insts = parser_parse(&parser);
+ vm_run(&vm, insts);
- return EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
diff --git a/src/parser.c b/src/parser.c
index 0eef4b7..673ad1d 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -20,170 +20,181 @@
#include <string.h>
#include "array.h"
-#include "parser.h"
#include "lexer.h"
+#include "parser.h"
#include "string_view.h"
void
-parser_init(parser_t *parser, char *file_name)
+parser_init(parser_t* parser, char* file_name)
{
- assert(parser && file_name);
+ assert(parser && file_name);
lexer_init(&parser->lexer, file_name);
}
void
-parser_next_expected_token(parser_t *parser, token_t *token, token_kind_t kind)
+parser_next_expected_token(parser_t* parser, token_t* token, token_kind_t kind)
{
- lexer_next_token(&parser->lexer, token);
- if (token->kind != kind) {
- fprintf(
- stderr,
- "%s:%zu:%zu: parser error: expected token <%s> but got <%s>.\n",
- parser->lexer.file_name,
- token->loc.lineno + 1,
- token->loc.offset - token->loc.lineoffset + 1,
- token_to_cstr(kind),
- token_to_cstr(token->kind));
- exit(EXIT_FAILURE);
- }
+ lexer_next_token(&parser->lexer, token);
+ if (token->kind != kind) {
+ fprintf(stderr,
+ "%s:%zu:%zu: parser error: expected token <%s> but got <%s>.\n",
+ parser->lexer.file_name,
+ token->loc.lineno + 1,
+ token->loc.offset - token->loc.lineoffset + 1,
+ token_to_cstr(kind),
+ token_to_cstr(token->kind));
+ exit(EXIT_FAILURE);
+ }
}
-inst_t *
-parser_parse(parser_t *parser) {
- inst_t *insts = array(inst_t);
-
- token_t token = { 0 };
- int label_count = 0;
-
- lexer_next_token(&parser->lexer, &token);
- while (token.kind != TOKEN_EOF) {
- switch (token.kind) {
- case TOKEN_KW_PUSH: {
- parser_next_expected_token(parser, &token, TOKEN_NUMBER);
-
- char value[token.value.size + 1];
- value[token.value.size] = '\0';
- memcpy(value, token.value.chars, token.value.size);
-
- array_append(insts, ((inst_t) { .type = INST_PUSH, .operand = atoi(value) }));
-
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_ADD: {
- array_append(insts, ((inst_t) { .type = INST_ADD }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_DUP: {
- array_append(insts, ((inst_t) { .type = INST_DUP }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_SWAP: {
- array_append(insts, ((inst_t) { .type = INST_SWAP }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_SUB: {
- array_append(insts, ((inst_t) { .type = INST_SUB }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_MUL: {
- array_append(insts, ((inst_t) { .type = INST_MUL }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_STORE: {
- array_append(insts, ((inst_t) { .type = INST_STORE }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_LOAD: {
- array_append(insts, ((inst_t) { .type = INST_LOAD }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_RET: {
- array_append(insts, ((inst_t) { .type = INST_RET }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_IDENT: {
- array_append(insts, ((inst_t) { .type = INST_LABEL, .operand = label_count++ }));
- parser_next_expected_token(parser, &token, TOKEN_COLON);
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_JMP: {
- parser_next_expected_token(parser, &token, TOKEN_NUMBER);
-
- char value[token.value.size + 1];
- value[token.value.size] = '\0';
- memcpy(value, token.value.chars, token.value.size);
-
- array_append(insts, ((inst_t) { .type = INST_JMP, .operand = atoi(value) }));
-
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_JMPZ: {
- parser_next_expected_token(parser, &token, TOKEN_NUMBER);
-
- char value[token.value.size + 1];
- value[token.value.size] = '\0';
- memcpy(value, token.value.chars, token.value.size);
-
- array_append(insts, ((inst_t) { .type = INST_JMPZ, .operand = atoi(value) }));
-
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_CALL: {
- parser_next_expected_token(parser, &token, TOKEN_NUMBER);
-
- char value[token.value.size + 1];
- value[token.value.size] = '\0';
- memcpy(value, token.value.chars, token.value.size);
-
- array_append(insts, ((inst_t) { .type = INST_CALL, .operand = atoi(value) }));
-
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_READI: {
- array_append(insts, ((inst_t) { .type = INST_READI }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_READC: {
- array_append(insts, ((inst_t) { .type = INST_READC }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_PRINTI: {
- array_append(insts, ((inst_t) { .type = INST_PRINTI }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_PRINTC: {
- array_append(insts, ((inst_t) { .type = INST_PRINTC }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_KW_END: {
- array_append(insts, ((inst_t) { .type = INST_END }));
- parser_next_expected_token(parser, &token, TOKEN_EOS);
- break;
- }
- case TOKEN_EOS: {
- break;
- }
- default: break;
- }
- lexer_next_token(&parser->lexer, &token);
- }
-
- return insts;
+inst_t*
+parser_parse(parser_t* parser)
+{
+ inst_t* insts = array(inst_t);
+
+ token_t token = { 0 };
+ int label_count = 0;
+
+ lexer_next_token(&parser->lexer, &token);
+ while (token.kind != TOKEN_EOF) {
+ switch (token.kind) {
+ case TOKEN_KW_PUSH: {
+ parser_next_expected_token(parser, &token, TOKEN_NUMBER);
+
+ char value[token.value.size + 1];
+ value[token.value.size] = '\0';
+ memcpy(value, token.value.chars, token.value.size);
+
+ array_append(
+ insts,
+ ((inst_t){ .type = INST_PUSH, .operand = atoi(value) }));
+
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_ADD: {
+ array_append(insts, ((inst_t){ .type = INST_ADD }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_DUP: {
+ array_append(insts, ((inst_t){ .type = INST_DUP }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_SWAP: {
+ array_append(insts, ((inst_t){ .type = INST_SWAP }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_SUB: {
+ array_append(insts, ((inst_t){ .type = INST_SUB }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_MUL: {
+ array_append(insts, ((inst_t){ .type = INST_MUL }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_STORE: {
+ array_append(insts, ((inst_t){ .type = INST_STORE }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_LOAD: {
+ array_append(insts, ((inst_t){ .type = INST_LOAD }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_RET: {
+ array_append(insts, ((inst_t){ .type = INST_RET }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_IDENT: {
+ array_append(
+ insts,
+ ((inst_t){ .type = INST_LABEL, .operand = label_count++ }));
+ parser_next_expected_token(parser, &token, TOKEN_COLON);
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_JMP: {
+ parser_next_expected_token(parser, &token, TOKEN_NUMBER);
+
+ char value[token.value.size + 1];
+ value[token.value.size] = '\0';
+ memcpy(value, token.value.chars, token.value.size);
+
+ array_append(
+ insts,
+ ((inst_t){ .type = INST_JMP, .operand = atoi(value) }));
+
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_JMPZ: {
+ parser_next_expected_token(parser, &token, TOKEN_NUMBER);
+
+ char value[token.value.size + 1];
+ value[token.value.size] = '\0';
+ memcpy(value, token.value.chars, token.value.size);
+
+ array_append(
+ insts,
+ ((inst_t){ .type = INST_JMPZ, .operand = atoi(value) }));
+
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_CALL: {
+ parser_next_expected_token(parser, &token, TOKEN_NUMBER);
+
+ char value[token.value.size + 1];
+ value[token.value.size] = '\0';
+ memcpy(value, token.value.chars, token.value.size);
+
+ array_append(
+ insts,
+ ((inst_t){ .type = INST_CALL, .operand = atoi(value) }));
+
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_READI: {
+ array_append(insts, ((inst_t){ .type = INST_READI }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_READC: {
+ array_append(insts, ((inst_t){ .type = INST_READC }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_PRINTI: {
+ array_append(insts, ((inst_t){ .type = INST_PRINTI }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_PRINTC: {
+ array_append(insts, ((inst_t){ .type = INST_PRINTC }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_KW_END: {
+ array_append(insts, ((inst_t){ .type = INST_END }));
+ parser_next_expected_token(parser, &token, TOKEN_EOS);
+ break;
+ }
+ case TOKEN_EOS: {
+ break;
+ }
+ default:
+ break;
+ }
+ lexer_next_token(&parser->lexer, &token);
+ }
+
+ return insts;
}
diff --git a/src/parser.h b/src/parser.h
index da9e341..c1990c2 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -22,13 +22,13 @@
typedef struct parser
{
- lexer_t lexer;
+ lexer_t lexer;
} parser_t;
void
-parser_init(parser_t *parser, char *file_name);
+parser_init(parser_t* parser, char* file_name);
-inst_t *
-parser_parse(parser_t *parser);
+inst_t*
+parser_parse(parser_t* parser);
#endif /* PARSER_H */
diff --git a/src/stack.c b/src/stack.c
index 5121f6b..c83b429 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -14,24 +14,25 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <stdio.h>
#include "stack.h"
+#include <stdio.h>
-void stack_push(stack_t *stack, int value)
+void
+stack_push(stack_t* stack, int value)
{
- if (stack->size >= stack->capacity) {
- perror("stack overflow");
- exit(EXIT_FAILURE);
- }
- stack->data[stack->size++] = value;
+ if (stack->size >= stack->capacity) {
+ perror("stack overflow");
+ exit(EXIT_FAILURE);
+ }
+ stack->data[stack->size++] = value;
}
-int stack_pop(stack_t *stack)
+int
+stack_pop(stack_t* stack)
{
- if (stack->size <= 0) {
- perror("stack_pop: Stack already empty");
- exit(EXIT_FAILURE);
- }
- return stack->data[--stack->size];
+ if (stack->size <= 0) {
+ perror("stack_pop: Stack already empty");
+ exit(EXIT_FAILURE);
+ }
+ return stack->data[--stack->size];
}
-
diff --git a/src/stack.h b/src/stack.h
index 70f7e93..c366ca8 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -20,12 +20,14 @@
typedef struct stack
{
- size_t capacity;
- size_t size;
- int *data;
+ size_t capacity;
+ size_t size;
+ int* data;
} stack_t;
-void stack_push(stack_t *stack, int value);
-int stack_pop(stack_t *stack);
+void
+stack_push(stack_t* stack, int value);
+int
+stack_pop(stack_t* stack);
#endif /* STACK_H */
diff --git a/src/string_view.c b/src/string_view.c
index 275e9bb..efb1329 100644
--- a/src/string_view.c
+++ b/src/string_view.c
@@ -14,13 +14,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <string.h>
#include "string_view.h"
+#include <string.h>
string_view_t
-string_view_from_cstr(char *cstr)
+string_view_from_cstr(char* cstr)
{
- return (string_view_t) { .size = strlen(cstr), .chars = cstr };
+ return (string_view_t){ .size = strlen(cstr), .chars = cstr };
}
bool
diff --git a/src/string_view.h b/src/string_view.h
index 38142b0..0f0a72b 100644
--- a/src/string_view.h
+++ b/src/string_view.h
@@ -16,19 +16,20 @@
*/
#ifndef STRING_VIEW_H
#define STRING_VIEW_H
-#include <stddef.h>
#include <stdbool.h>
+#include <stddef.h>
#define PRIsv "%.*s"
-#define PRIsvARG(sv) (int) (sv).size, (sv).chars
+#define PRIsvARG(sv) (int)(sv).size, (sv).chars
-typedef struct string_view {
+typedef struct string_view
+{
size_t size;
- char *chars;
+ char* chars;
} string_view_t;
string_view_t
-string_view_from_cstr(char *cstr);
+string_view_from_cstr(char* cstr);
bool
string_view_eq(string_view_t s1, string_view_t s2);
diff --git a/src/utils.c b/src/utils.c
index fee048d..3bf3cc0 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -14,14 +14,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
-#include "utils.h"
-char *
-read_file_contents(char *file_path)
+char*
+read_file_contents(char* file_path)
{
- FILE *file;
+ FILE* file;
int file_size;
file = fopen(file_path, "r");
@@ -48,7 +48,7 @@ read_file_contents(char *file_path)
return NULL;
}
- char *file_content = (char *)calloc(file_size + 1, sizeof(char));
+ char* file_content = (char*)calloc(file_size + 1, sizeof(char));
if (file_content == NULL) {
fprintf(stderr, "Could not allocate mem for file_content\n");
fclose(file);
diff --git a/src/utils.h b/src/utils.h
index c50ff03..d88d200 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -17,7 +17,7 @@
#ifndef UTILS_H
#define UTILS_H
-char *
-read_file_contents(char *file_path);
+char*
+read_file_contents(char* file_path);
#endif /* UTILS_H */
diff --git a/src/vm.c b/src/vm.c
index 0c3e9d0..c321cff 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -14,201 +14,199 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include "vm.h"
+#include "array.h"
+#include "stack.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
-#include "array.h"
-#include "stack.h"
-#include "vm.h"
void
-vm_init(vm_t *vm)
+vm_init(vm_t* vm)
{
- assert(vm);
- vm->stack = (stack_t) {
- .capacity = STACK_CAPACITY,
- .size = 0,
- .data = calloc(sizeof(int), STACK_CAPACITY)
- };
- vm->call_stack = (stack_t) {
- .capacity = 3000,
- .size = 0,
- .data = calloc(sizeof(int), 3000)
- };
- vm->heap = calloc(sizeof(int), HEAP_CAPACITY);
- vm->labels = array(label_t);
+ assert(vm);
+ vm->stack = (stack_t){ .capacity = STACK_CAPACITY,
+ .size = 0,
+ .data = calloc(sizeof(int), STACK_CAPACITY) };
+ vm->call_stack = (stack_t){ .capacity = 3000,
+ .size = 0,
+ .data = calloc(sizeof(int), 3000) };
+ vm->heap = calloc(sizeof(int), HEAP_CAPACITY);
+ vm->labels = array(label_t);
}
void
-vm_run(vm_t *vm, inst_t *insts)
+vm_run(vm_t* vm, inst_t* insts)
{
- size_t program_size = array_length(insts);
+ size_t program_size = array_length(insts);
- // resolve lables
- for (size_t ip = 0; ip < program_size; ++ip) {
- if (insts[ip].type == INST_LABEL) {
- int name = insts[ip].operand;
- label_t label = { .name = name, .index = ip };
- array_append(vm->labels, label);
- }
- }
+ // resolve lables
+ for (size_t ip = 0; ip < program_size; ++ip) {
+ if (insts[ip].type == INST_LABEL) {
+ int name = insts[ip].operand;
+ label_t label = { .name = name, .index = ip };
+ array_append(vm->labels, label);
+ }
+ }
- // resolve jumps
- for (size_t ip = 0; ip < program_size; ++ip) {
- switch (insts[ip].type) {
- case INST_CALL:
- case INST_JMP:
- case INST_JMPN:
- case INST_JMPZ: {
- int label_name = insts[ip].operand;
- size_t i = 0;
- size_t labels_size = array_length(vm->labels);
- for (; i < labels_size; ++i) {
- if (vm->labels[i].name == label_name) {
- insts[ip].operand = vm->labels[i].index;
- break;
- }
- }
- assert(i < labels_size);
- }
- default: break;
- }
- }
+ // resolve jumps
+ for (size_t ip = 0; ip < program_size; ++ip) {
+ switch (insts[ip].type) {
+ case INST_CALL:
+ case INST_JMP:
+ case INST_JMPN:
+ case INST_JMPZ: {
+ int label_name = insts[ip].operand;
+ size_t i = 0;
+ size_t labels_size = array_length(vm->labels);
+ for (; i < labels_size; ++i) {
+ if (vm->labels[i].name == label_name) {
+ insts[ip].operand = vm->labels[i].index;
+ break;
+ }
+ }
+ assert(i < labels_size);
+ }
+ default:
+ break;
+ }
+ }
- // run
- for (size_t ip = 0; ip < program_size; ++ip) {
- switch (insts[ip].type) {
- case INST_PUSH: {
- stack_push(&vm->stack, insts[ip].operand);
- break;
- }
- case INST_DUP: {
- stack_push(&vm->stack, vm->stack.data[vm->stack.size - 1]);
- break;
- }
- case INST_COPY: {
- int operand = insts[ip].operand;
- stack_push(&vm->stack, vm->stack.data[vm->stack.size - 1 - operand]);
- break;
- }
- case INST_SWAP: {
- int a = stack_pop(&vm->stack);
- int b = stack_pop(&vm->stack);
- stack_push(&vm->stack, a);
- stack_push(&vm->stack, b);
- break;
- }
- case INST_DROP: {
- stack_pop(&vm->stack);
- break;
- }
- case INST_SLIDE: {
- int operand = insts[ip].operand;
- int top = stack_pop(&vm->stack);
- while (operand-- > 0) {
- stack_pop(&vm->stack);
- }
- stack_push(&vm->stack, top);
- break;
- }
- case INST_ADD: {
- int lhs = stack_pop(&vm->stack);
- int rhs = stack_pop(&vm->stack);
- stack_push(&vm->stack, lhs + rhs);
- break;
- }
- case INST_SUB: {
- int rhs = stack_pop(&vm->stack);
- int lhs = stack_pop(&vm->stack);
- stack_push(&vm->stack, lhs - rhs);
- break;
- }
- case INST_MUL: {
- int rhs = stack_pop(&vm->stack);
- int lhs = stack_pop(&vm->stack);
- stack_push(&vm->stack, lhs * rhs);
- break;
- }
- case INST_DIV: {
- int rhs = stack_pop(&vm->stack);
- int lhs = stack_pop(&vm->stack);
- stack_push(&vm->stack, lhs / rhs);
- break;
- }
- case INST_MOD: {
- int rhs = stack_pop(&vm->stack);
- int lhs = stack_pop(&vm->stack);
- stack_push(&vm->stack, lhs % rhs);
- break;
- }
- case INST_STORE: {
- int value = stack_pop(&vm->stack);
- int address = stack_pop(&vm->stack);
- vm->heap[address] = value;
- break;
- }
- case INST_LOAD: {
- int address = stack_pop(&vm->stack);
- stack_push(&vm->stack, vm->heap[address]);
- break;
- }
- case INST_CALL: {
- stack_push(&vm->call_stack, ip + 1);
- ip = insts[ip].operand;
- break;
- }
- case INST_RET: {
- ip = stack_pop(&vm->call_stack);
- break;
- }
- case INST_JMP: {
- ip = insts[ip].operand;
- break;
- }
- case INST_JMPZ: {
- int value = stack_pop(&vm->stack);
- if (value == 0) {
- ip = insts[ip].operand;
- }
- break;
- }
- case INST_JMPN: {
- int value = stack_pop(&vm->stack);
- if (value < 0) {
- ip = insts[ip].operand;
- }
- break;
- }
- case INST_PRINTI: {
- int value = stack_pop(&vm->stack);
- printf("%d", value);
- break;
- }
- case INST_PRINTC: {
- int value = stack_pop(&vm->stack);
- printf("%c", value);
- break;
- }
- case INST_READI: {
- int address = stack_pop(&vm->stack);
- scanf("%d", vm->heap + address);
- break;
- }
- case INST_READC: {
- int address = stack_pop(&vm->stack);
- vm->heap[address] = getchar();
- break;
- }
- case INST_END: {
- return;
- }
- case INST_LABEL: {
- break;
- }
- default: {
- assert(0 && "Unsupported instruction");
- break;
- }
- }
- }
+ // run
+ for (size_t ip = 0; ip < program_size; ++ip) {
+ switch (insts[ip].type) {
+ case INST_PUSH: {
+ stack_push(&vm->stack, insts[ip].operand);
+ break;
+ }
+ case INST_DUP: {
+ stack_push(&vm->stack, vm->stack.data[vm->stack.size - 1]);
+ break;
+ }
+ case INST_COPY: {
+ int operand = insts[ip].operand;
+ stack_push(&vm->stack,
+ vm->stack.data[vm->stack.size - 1 - operand]);
+ break;
+ }
+ case INST_SWAP: {
+ int a = stack_pop(&vm->stack);
+ int b = stack_pop(&vm->stack);
+ stack_push(&vm->stack, a);
+ stack_push(&vm->stack, b);
+ break;
+ }
+ case INST_DROP: {
+ stack_pop(&vm->stack);
+ break;
+ }
+ case INST_SLIDE: {
+ int operand = insts[ip].operand;
+ int top = stack_pop(&vm->stack);
+ while (operand-- > 0) {
+ stack_pop(&vm->stack);
+ }
+ stack_push(&vm->stack, top);
+ break;
+ }
+ case INST_ADD: {
+ int lhs = stack_pop(&vm->stack);
+ int rhs = stack_pop(&vm->stack);
+ stack_push(&vm->stack, lhs + rhs);
+ break;
+ }
+ case INST_SUB: {
+ int rhs = stack_pop(&vm->stack);
+ int lhs = stack_pop(&vm->stack);
+ stack_push(&vm->stack, lhs - rhs);
+ break;
+ }
+ case INST_MUL: {
+ int rhs = stack_pop(&vm->stack);
+ int lhs = stack_pop(&vm->stack);
+ stack_push(&vm->stack, lhs * rhs);
+ break;
+ }
+ case INST_DIV: {
+ int rhs = stack_pop(&vm->stack);
+ int lhs = stack_pop(&vm->stack);
+ stack_push(&vm->stack, lhs / rhs);
+ break;
+ }
+ case INST_MOD: {
+ int rhs = stack_pop(&vm->stack);
+ int lhs = stack_pop(&vm->stack);
+ stack_push(&vm->stack, lhs % rhs);
+ break;
+ }
+ case INST_STORE: {
+ int value = stack_pop(&vm->stack);
+ int address = stack_pop(&vm->stack);
+ vm->heap[address] = value;
+ break;
+ }
+ case INST_LOAD: {
+ int address = stack_pop(&vm->stack);
+ stack_push(&vm->stack, vm->heap[address]);
+ break;
+ }
+ case INST_CALL: {
+ stack_push(&vm->call_stack, ip + 1);
+ ip = insts[ip].operand;
+ break;
+ }
+ case INST_RET: {
+ ip = stack_pop(&vm->call_stack);
+ break;
+ }
+ case INST_JMP: {
+ ip = insts[ip].operand;
+ break;
+ }
+ case INST_JMPZ: {
+ int value = stack_pop(&vm->stack);
+ if (value == 0) {
+ ip = insts[ip].operand;
+ }
+ break;
+ }
+ case INST_JMPN: {
+ int value = stack_pop(&vm->stack);
+ if (value < 0) {
+ ip = insts[ip].operand;
+ }
+ break;
+ }
+ case INST_PRINTI: {
+ int value = stack_pop(&vm->stack);
+ printf("%d", value);
+ break;
+ }
+ case INST_PRINTC: {
+ int value = stack_pop(&vm->stack);
+ printf("%c", value);
+ break;
+ }
+ case INST_READI: {
+ int address = stack_pop(&vm->stack);
+ scanf("%d", vm->heap + address);
+ break;
+ }
+ case INST_READC: {
+ int address = stack_pop(&vm->stack);
+ vm->heap[address] = getchar();
+ break;
+ }
+ case INST_END: {
+ return;
+ }
+ case INST_LABEL: {
+ break;
+ }
+ default: {
+ assert(0 && "Unsupported instruction");
+ break;
+ }
+ }
+ }
}
diff --git a/src/vm.h b/src/vm.h
index 365b98e..143275f 100644
--- a/src/vm.h
+++ b/src/vm.h
@@ -22,59 +22,63 @@
#define STACK_CAPACITY 1024
#define HEAP_CAPACITY 1024
-typedef enum inst_type {
- // stack
- INST_PUSH,
- INST_DUP,
- INST_COPY,
- INST_SWAP,
- INST_DROP,
- INST_SLIDE,
- // arithmetics
- INST_ADD,
- INST_SUB,
- INST_MUL,
- INST_DIV,
- INST_MOD,
- // heap access
- INST_STORE,
- INST_LOAD,
- // Flow control
- INST_CALL,
- INST_RET,
- INST_LABEL,
- INST_JMP,
- INST_JMPZ,
- INST_JMPN,
- // I/O
- INST_PRINTI,
- INST_PRINTC,
- INST_READI,
- INST_READC,
- INST_END,
+typedef enum inst_type
+{
+ // stack
+ INST_PUSH,
+ INST_DUP,
+ INST_COPY,
+ INST_SWAP,
+ INST_DROP,
+ INST_SLIDE,
+ // arithmetics
+ INST_ADD,
+ INST_SUB,
+ INST_MUL,
+ INST_DIV,
+ INST_MOD,
+ // heap access
+ INST_STORE,
+ INST_LOAD,
+ // Flow control
+ INST_CALL,
+ INST_RET,
+ INST_LABEL,
+ INST_JMP,
+ INST_JMPZ,
+ INST_JMPN,
+ // I/O
+ INST_PRINTI,
+ INST_PRINTC,
+ INST_READI,
+ INST_READC,
+ INST_END,
} inst_type_t;
-typedef struct instr {
- inst_type_t type;
- int operand;
+typedef struct instr
+{
+ inst_type_t type;
+ int operand;
} inst_t;
-typedef struct label {
- int name;
- int index;
+typedef struct label
+{
+ int name;
+ int index;
} label_t;
-typedef struct vm {
- stack_t stack;
- stack_t call_stack;
- int *heap;
- label_t *labels;
+typedef struct vm
+{
+ stack_t stack;
+ stack_t call_stack;
+ int* heap;
+ label_t* labels;
} vm_t;
void
-vm_init(vm_t *vm);
+vm_init(vm_t* vm);
void
-vm_run(vm_t *vm, inst_t *insts);
+vm_run(vm_t* vm, inst_t* insts);
#endif /* VM_H */