diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 29 | ||||
| -rw-r--r-- | src/array.h | 32 | ||||
| -rw-r--r-- | src/lexer.c | 84 | ||||
| -rw-r--r-- | src/lexer.h | 27 | ||||
| -rw-r--r-- | src/main.c | 22 | ||||
| -rw-r--r-- | src/parser.c | 319 | ||||
| -rw-r--r-- | src/parser.h | 8 | ||||
| -rw-r--r-- | src/stack.c | 29 | ||||
| -rw-r--r-- | src/stack.h | 12 | ||||
| -rw-r--r-- | src/string_view.c | 6 | ||||
| -rw-r--r-- | src/string_view.h | 11 | ||||
| -rw-r--r-- | src/utils.c | 10 | ||||
| -rw-r--r-- | src/utils.h | 4 | ||||
| -rw-r--r-- | src/vm.c | 366 | ||||
| -rw-r--r-- | src/vm.h | 90 |
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 */ @@ -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 */ @@ -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; + } + } + } } @@ -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 */ |
