From f7ff3393f0bf2d210cf1aade2a22581e6cebaf16 Mon Sep 17 00:00:00 2001 From: Ugric Date: Sun, 13 Jul 2025 03:34:31 +0100 Subject: [PATCH] add if statement and declaration --- Makefile | 2 +- src/hash_data/hash_data.c | 4 +- src/hash_data/hash_data.h | 3 +- src/lexer/lexer.c | 4 +- src/main.c | 41 ++++++----- src/parser/assignable/access/access.c | 38 +++++++--- src/parser/assignable/assign/assign.c | 17 +++-- src/parser/assignable/call/call.c | 57 ++++++++++++--- src/parser/declaration/declaration.c | 80 +++++++++++++++++---- src/parser/declaration/declaration.h | 2 + src/parser/dictionary/dictionary.c | 70 ++++++++++++++---- src/parser/function/function.h | 2 + src/parser/if/if.c | 35 +++++++-- src/parser/list/list.c | 34 +++++++-- src/parser/operations/operations.c | 19 +++-- src/parser/parser.c | 27 +++---- src/parser/parser.h | 2 +- src/runtime/declaration/declaration.c | 18 +++++ src/runtime/declaration/declaration.h | 8 +++ src/runtime/objects/functions/functions.c | 4 +- src/runtime/objects/functions/functions.h | 2 +- src/runtime/objects/literals/literals.c | 25 +++++++ src/runtime/objects/literals/literals.h | 12 ++++ src/runtime/objects/null/null.c | 14 ---- src/runtime/objects/null/null.h | 10 --- src/runtime/runtime.c | 86 +++++++++++++++++------ src/runtime/runtime.h | 13 +++- src/translator/bytecode_spec.md | 35 ++++++++- src/translator/declaration/declaration.c | 10 +-- src/translator/function/function.c | 1 + src/translator/identifier/identifier.c | 2 + src/translator/if/if.c | 45 ++++++++++++ src/translator/if/if.h | 7 ++ src/translator/translator.c | 14 +++- src/translator/translator.h | 6 +- testing.ar | 3 + 36 files changed, 587 insertions(+), 165 deletions(-) create mode 100644 src/runtime/declaration/declaration.c create mode 100644 src/runtime/declaration/declaration.h create mode 100644 src/runtime/objects/literals/literals.c create mode 100644 src/runtime/objects/literals/literals.h delete mode 100644 src/runtime/objects/null/null.c delete mode 100644 src/runtime/objects/null/null.h create mode 100644 src/translator/if/if.c create mode 100644 src/translator/if/if.h create mode 100644 testing.ar diff --git a/Makefile b/Makefile index 6331bef..5afeb6f 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LEXER_C = src/lexer/lex.yy.c LEXER_H = src/lexer/lex.yy.h CFILES = external/xxhash/xxhash.c external/cwalk/src/cwalk.c external/libdye/src/dye.c $(shell find src -name '*.c') -CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function -Iexternal/cwalk/include -Iexternal/libdye/include +CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function -Werror=unused-result -Iexternal/cwalk/include -Iexternal/libdye/include BINARY = bin/argon all: $(BINARY) diff --git a/src/hash_data/hash_data.c b/src/hash_data/hash_data.c index 2ff32b5..6c36091 100644 --- a/src/hash_data/hash_data.c +++ b/src/hash_data/hash_data.c @@ -1,10 +1,12 @@ #include #include +#include #include #include "siphash/siphash.h" #include "hash_data.h" uint8_t siphash_key[16]; +const uint8_t siphash_key_fixed_for_translator[16] = {218, 19, 245, 136, 128, 160, 122, 81, 249, 147, 111, 230, 174, 145, 125 ,218}; uint8_t empty_siphash_key[16]; void generate_siphash_key(uint8_t hash_key[16]) { @@ -15,7 +17,7 @@ void generate_siphash_key(uint8_t hash_key[16]) { close(fd); } -uint64_t siphash64_bytes(const void *data, size_t len,uint8_t hash_key[16]) { +uint64_t siphash64_bytes(const void *data, size_t len,const uint8_t hash_key[16]) { uint8_t out[8]; if (siphash(data, len, hash_key, out, sizeof(out)) != 0) return 0; diff --git a/src/hash_data/hash_data.h b/src/hash_data/hash_data.h index dbd74c5..f8e6dcd 100644 --- a/src/hash_data/hash_data.h +++ b/src/hash_data/hash_data.h @@ -4,8 +4,9 @@ #include extern uint8_t siphash_key[16]; +extern const uint8_t siphash_key_fixed_for_translator[16]; extern uint8_t empty_siphash_key[16]; void generate_siphash_key(uint8_t siphash_key[16]); -uint64_t siphash64_bytes(const void *data, size_t len,uint8_t siphash_key[16]); +uint64_t siphash64_bytes(const void *data, size_t len,const uint8_t hash_key[16]); #endif //HASH_DATA_H \ No newline at end of file diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 5d8869b..9f314db 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -8,9 +8,7 @@ ArErr lexer(LexerState state) { int ch; while ((ch = fgetc(state.file)) != EOF) { if (ch == 0 || (ch < 0x20 && ch != '\n' && ch != '\r' && ch != '\t')) { - fprintf(stderr, "%s:%zu:%zu error: disallowed character\n", state.path, - line, column); - exit(1); + return create_err(line, column, 1, state.path, "Syntax Error", "disallowed character"); } if (ch == '\n') { diff --git a/src/main.c b/src/main.c index 343b2b7..b755c64 100644 --- a/src/main.c +++ b/src/main.c @@ -86,8 +86,10 @@ const uint32_t version_number = 0; int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { bool translated_inited = false; FILE *bytecode_file = fopen(joined_paths, "rb"); - if (!bytecode_file) + if (!bytecode_file) { + printf("cache doesnt exist... compiling from source.\n"); return 1; + } char file_identifier_from_cache[sizeof(FILE_IDENTIFIER)] = {0}; if (fread(&file_identifier_from_cache, 1, sizeof(file_identifier_from_cache) - 1, @@ -165,42 +167,45 @@ int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) { darray_resize(&translated_dest->source_locations, sourceLocationSize); - if (fread(translated_dest->source_locations.data, sizeof(SourceLocation), sourceLocationSize, bytecode_file) != - sourceLocationSize) { + if (fread(translated_dest->source_locations.data, sizeof(SourceLocation), + sourceLocationSize, bytecode_file) != sourceLocationSize) { goto FAILED; } translated_dest->registerCount = register_count; + printf("cache exists and is valid, so will be used.\n"); fclose(bytecode_file); return 0; FAILED: - if (translated_inited) free_translator(translated_dest); + printf("cache is invalid... compiling from source.\n"); + if (translated_inited) + free_translator(translated_dest); fclose(bytecode_file); return 1; } -Execution execute(char *absolute_path, Stack *stack) { +Execution execute(char *path, Stack *stack) { clock_t start, end; double time_spent, total_time_spent = 0; const char *basename_ptr; size_t basename_length; - cwk_path_get_basename(absolute_path, &basename_ptr, &basename_length); + cwk_path_get_basename(path, &basename_ptr, &basename_length); if (!basename_ptr) return (Execution){create_err(0, 0, 0, NULL, "Path Error", - "path has no basename '%s'", absolute_path), + "path has no basename '%s'", path), (Stack){NULL, NULL}}; char basename[FILENAME_MAX]; memcpy(basename, basename_ptr, basename_length); size_t parent_directory_length; - cwk_path_get_dirname(absolute_path, &parent_directory_length); + cwk_path_get_dirname(path, &parent_directory_length); char parent_directory[FILENAME_MAX]; - memcpy(parent_directory, absolute_path, parent_directory_length); + memcpy(parent_directory, path, parent_directory_length); parent_directory[parent_directory_length] = '\0'; char cache_folder_path[FILENAME_MAX]; @@ -213,10 +218,10 @@ Execution execute(char *absolute_path, Stack *stack) { cwk_path_change_extension(cache_file_path, BYTECODE_EXTENTION, cache_file_path, sizeof(cache_file_path)); - FILE *file = fopen(absolute_path, "r"); + FILE *file = fopen(path, "r"); if (!file) { return (Execution){create_err(0, 0, 0, NULL, "File Error", - "Unable to open file '%s'", absolute_path), + "Unable to open file '%s'", path), (Stack){NULL, NULL}}; } @@ -240,7 +245,7 @@ Execution execute(char *absolute_path, Stack *stack) { DArray tokens; darray_init(&tokens, sizeof(Token)); - LexerState state = {absolute_path, file, 0, 0, &tokens}; + LexerState state = {path, file, 0, 0, &tokens}; start = clock(); ArErr err = lexer(state); if (err.exists) { @@ -259,7 +264,7 @@ Execution execute(char *absolute_path, Stack *stack) { darray_init(&ast, sizeof(ParsedValue)); start = clock(); - err = parser(absolute_path, &ast, &tokens, false); + err = parser(path, &ast, &tokens, false); if (err.exists) { free_translator(&translated); darray_free(&tokens, free_token); @@ -312,8 +317,8 @@ Execution execute(char *absolute_path, Stack *stack) { } start = clock(); - RuntimeState state = init_runtime_state(translated, absolute_path); - Stack main_scope = create_scope(stack); + RuntimeState state = init_runtime_state(translated, path); + Stack *main_scope = create_scope(stack); ArErr err = runtime(translated, state, main_scope); free(state.registers); end = clock(); @@ -323,7 +328,7 @@ Execution execute(char *absolute_path, Stack *stack) { printf("total time taken: %f seconds\n", total_time_spent); free_translator(&translated); - return (Execution){err, main_scope}; + return (Execution){err, *main_scope}; } int main(int argc, char *argv[]) { @@ -339,9 +344,11 @@ int main(int argc, char *argv[]) { cwk_path_get_absolute(CWD, path_non_absolute, path, sizeof(path)); free(CWD); Execution resp = execute(path, NULL); + if (runtime_hash_table) + hashmap_free(runtime_hash_table, NULL); if (resp.err.exists) { output_err(resp.err); - return -1; + return 1; } return 0; } \ No newline at end of file diff --git a/src/parser/assignable/access/access.c b/src/parser/assignable/access/access.c index f0e66ac..8823c34 100644 --- a/src/parser/assignable/access/access.c +++ b/src/parser/assignable/access/access.c @@ -19,7 +19,12 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, free(to_access); darray_init(&parsedAccess->access, sizeof(ParsedValue)); if (first_token->type == TOKEN_DOT) { - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } Token *token = darray_get(tokens, *index); ParsedValueReturn parsedString = parse_string(token, false); if (parsedString.err.exists) { @@ -35,7 +40,12 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, Token *token = first_token; while (true) { skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } ParsedValueReturn parsedAccessValue = parse_token(file, tokens, index, true); if (parsedAccessValue.err.exists) { @@ -45,22 +55,30 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, } else if (!parsedAccessValue.value) { free_parsed(parsedValue); free(parsedValue); - return (ParsedValueReturn){ - create_err(token->line, token->column, token->length, file, - "Syntax Error", "expected value"), - NULL}; + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, + "Syntax Error", "expected value"), + NULL}; } darray_push(&parsedAccess->access, parsedAccessValue.value); free(parsedAccessValue.value); skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RBRACKET) { break; } else if (token->type != TOKEN_COLON) { - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, + "Syntax Error", "expected colon"), + NULL}; } (*index)++; } diff --git a/src/parser/assignable/assign/assign.c b/src/parser/assignable/assign/assign.c index fe2b399..ef241fb 100644 --- a/src/parser/assignable/assign/assign.c +++ b/src/parser/assignable/assign/assign.c @@ -31,14 +31,12 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens, } break; default:; - ArErr err = create_err(token->line, token->column, - token->length, file, "Syntax Error", - "can't assign to %s", - ValueTypeNames[assign_to->type]); + ArErr err = create_err(token->line, token->column, token->length, file, + "Syntax Error", "can't assign to %s", + ValueTypeNames[assign_to->type]); free_parsed(assign_to); free(assign_to); - return (ParsedValueReturn){err, - NULL}; + return (ParsedValueReturn){err, NULL}; } ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign)); assign->to = assign_to; @@ -47,7 +45,12 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens, parsedValue->type = AST_ASSIGN; parsedValue->data = assign; (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); ParsedValueReturn from = parse_token(file, tokens, index, true); if (from.err.exists) { diff --git a/src/parser/assignable/call/call.c b/src/parser/assignable/call/call.c index a6c661d..9324a78 100644 --- a/src/parser/assignable/call/call.c +++ b/src/parser/assignable/call/call.c @@ -15,12 +15,26 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, parsedValue->type = AST_CALL; darray_init(&call->args, sizeof(ParsedValue)); (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } Token *token = darray_get(tokens, *index); if (token->type != TOKEN_RPAREN) { while ((*index) < tokens->size) { skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } ParsedValueReturn parsedArg = parse_token(file, tokens, index, true); if (parsedArg.err.exists) { free_parsed(to_call); @@ -41,19 +55,46 @@ ParsedValueReturn parse_call(char *file, DArray *tokens, size_t *index, } darray_push(&call->args, parsedArg.value); free(parsedArg.value); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RPAREN) { break; } else if (token->type != TOKEN_COMMA) { - fprintf(stderr, "%s:%zu:%zu error: expected comma\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, + "Syntax Error", "expected comma"), + NULL}; } (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(to_call); + free(to_call); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } } } (*index)++; diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index d43272e..edc3e21 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -12,7 +12,10 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + return (ParsedValueReturn){err, NULL}; + } Token *token = darray_get(tokens, *index); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); @@ -25,6 +28,8 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { darray_push(declarations, &_declaration); ParsedSingleDeclaration *declaration = darray_get(declarations, declarations->size - 1); + declaration->line = token->line; + declaration->column = token->column; bool isFunction = false; DArray parameters; declaration->from = parse_null(); @@ -49,19 +54,34 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { struct hashmap *parameters_hashmap = createHashmap(); darray_init(¶meters, sizeof(char *)); (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(¶meters, free_parameter); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RPAREN) { (*index)++; - if ((*index) >= tokens->size) + if ((*index) >= tokens->size) { + declaration->from = create_parsed_function( + declaration->name, parameters, declaration->from); return (ParsedValueReturn){no_err, parsedValue}; + } token = darray_get(tokens, *index); } else { while ((*index) < tokens->size) { skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type != TOKEN_IDENTIFIER) { + darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){ @@ -75,6 +95,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { uint64_t hash = siphash64_bytes(token->value, token->length, siphash_key); if (hashmap_lookup(parameters_hashmap, hash) != NULL) { + darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){ @@ -90,9 +111,21 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { 0); darray_push(¶meters, ¶meter_name); (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(¶meters, free_parameter); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(¶meters, free_parameter); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RPAREN) { (*index)++; @@ -101,6 +134,7 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { token = darray_get(tokens, *index); break; } else if (token->type != TOKEN_COMMA) { + darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){ @@ -109,25 +143,37 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { NULL}; } (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(¶meters, free_parameter); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } } } hashmap_free(parameters_hashmap, NULL); } if (token->type == TOKEN_ASSIGN) { (*index)++; - error_if_finished(file, tokens, index); - - free(declaration->from); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } ParsedValueReturn from = parse_token(file, tokens, index, true); if (from.err.exists) { + darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return from; } + free(declaration->from); declaration->from = from.value; if (!declaration->from) { + darray_free(¶meters, free_parameter); free_parsed(parsedValue); free(parsedValue); return (ParsedValueReturn){create_err(token->line, token->column, @@ -153,9 +199,19 @@ ParsedValueReturn parse_declaration(char *file, DArray *tokens, size_t *index) { break; } (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); } return (ParsedValueReturn){no_err, parsedValue}; diff --git a/src/parser/declaration/declaration.h b/src/parser/declaration/declaration.h index 39ceab2..2871625 100644 --- a/src/parser/declaration/declaration.h +++ b/src/parser/declaration/declaration.h @@ -6,6 +6,8 @@ typedef struct { char * name; ParsedValue * from; + uint64_t line; + uint64_t column; } ParsedSingleDeclaration; // Function declaration for parsing an identifier diff --git a/src/parser/dictionary/dictionary.c b/src/parser/dictionary/dictionary.c index 142729c..9a7ad85 100644 --- a/src/parser/dictionary/dictionary.c +++ b/src/parser/dictionary/dictionary.c @@ -15,12 +15,22 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { darray_init(dictionary, sizeof(ParsedValue)); (*index)++; skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } Token *token = darray_get(tokens, *index); if (token->type != TOKEN_RBRACE) { while (true) { skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } size_t keyIndex = *index; Token *keyToken = darray_get(tokens, *index); ParsedValueReturn key; @@ -43,7 +53,12 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { NULL}; } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); ParsedValueReturn value; bool tobreak = false; @@ -51,7 +66,12 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { case TOKEN_COLON: (*index)++; skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } value = parse_token(file, tokens, index, true); if (value.err.exists) { free_parsed(parsedValue); @@ -70,14 +90,30 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { NULL}; } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + free_parsed(key.value); + free(key.value); + free_parsed(value.value); + free(value.value); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RBRACE) { tobreak = true; } else if (token->type != TOKEN_COMMA) { - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + free_parsed(parsedValue); + free(parsedValue); + free_parsed(key.value); + free(key.value); + free_parsed(value.value); + free(value.value); + return (ParsedValueReturn){ + create_err(token->line, token->column, token->length, file, + "Syntax Error", "expected comma"), + NULL}; } break; case TOKEN_RBRACE: @@ -87,9 +123,14 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { value = parse_token(file, tokens, &keyIndex, true); break; default: - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + free_parsed(parsedValue); + free(parsedValue); + free_parsed(key.value); + free(key.value); + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, + "Syntax Error", "unexpected token"), + NULL}; } ParsedDictionaryEntry entry = {key.value, value.value}; darray_push(dictionary, &entry); @@ -97,7 +138,12 @@ ParsedValueReturn parse_dictionary(char *file, DArray *tokens, size_t *index) { break; } (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } } } (*index)++; diff --git a/src/parser/function/function.h b/src/parser/function/function.h index 8c18ec7..013f23a 100644 --- a/src/parser/function/function.h +++ b/src/parser/function/function.h @@ -14,4 +14,6 @@ ParsedValue *create_parsed_function(char *name, DArray parameters, void free_function(void *ptr); +void free_parameter(void *ptr); + #endif // FUNCTION_H \ No newline at end of file diff --git a/src/parser/if/if.c b/src/parser/if/if.c index 162b909..94de757 100644 --- a/src/parser/if/if.c +++ b/src/parser/if/if.c @@ -3,6 +3,7 @@ #include "../../memory.h" #include "../parser.h" #include +#include #include #include @@ -18,7 +19,10 @@ void free_conditional(void *ptr) { ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index) { (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + return (ParsedValueReturn){err, NULL}; + } DArray *parsed_if = checked_malloc(sizeof(DArray)); darray_init(parsed_if, sizeof(ParsedConditional)); @@ -32,15 +36,22 @@ ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index) { if (!expect_conditional) { if (token->type != TOKEN_NEW_LINE) break; // no more branches - (*index)++; + size_t current_index = *index; + skip_newlines_and_indents(tokens, index); if ((*index) >= tokens->size) break; token = darray_get(tokens, *index); if (token->type == TOKEN_ELSE || token->type == TOKEN_ELSE_IF) { (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(parsed_if, free_conditional); + free(parsed_if); + return (ParsedValueReturn){err, NULL}; + } } else { + *index = current_index; break; // no more branches } } @@ -60,7 +71,12 @@ ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index) { } (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(parsed_if, free_conditional); + free(parsed_if); + return (ParsedValueReturn){err, NULL}; + } skip_newlines_and_indents(tokens, index); condition = parse_token(file, tokens, index, true); if (condition.err.exists) { @@ -92,7 +108,16 @@ ParsedValueReturn parse_if(char *file, DArray *tokens, size_t *index) { } (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + if (condition.value) { + free_parsed(condition.value); + free(condition.value); + } + darray_free(parsed_if, free_conditional); + free(parsed_if); + return (ParsedValueReturn){err, NULL}; + } } // Parse the body diff --git a/src/parser/list/list.c b/src/parser/list/list.c index da695b7..dd4979e 100644 --- a/src/parser/list/list.c +++ b/src/parser/list/list.c @@ -14,7 +14,12 @@ ParsedValueReturn parse_list(char *file, DArray *tokens, size_t *index) { darray_init(list, sizeof(ParsedValue)); (*index)++; skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } Token *token = darray_get(tokens, *index); if (token->type != TOKEN_RBRACKET) { while (true) { @@ -27,19 +32,34 @@ ParsedValueReturn parse_list(char *file, DArray *tokens, size_t *index) { } darray_push(list, parsedItem.value); free(parsedItem.value); - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } skip_newlines_and_indents(tokens, index); - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } token = darray_get(tokens, *index); if (token->type == TOKEN_RBRACKET) { break; } else if (token->type != TOKEN_COMMA) { - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){create_err(token->line, token->column, token->length, file, "Syntax Error", "expected comma"), NULL}; } (*index)++; - error_if_finished(file, tokens, index); + err = error_if_finished(file, tokens, index); + if (err.exists) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){err, NULL}; + } } } (*index)++; diff --git a/src/parser/operations/operations.c b/src/parser/operations/operations.c index ac936be..7e0459b 100644 --- a/src/parser/operations/operations.c +++ b/src/parser/operations/operations.c @@ -55,7 +55,7 @@ ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) { } ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, - ParsedValue *first_parsed_value) { + ParsedValue *first_parsed_value) { DArray to_operate_on; darray_init(&to_operate_on, sizeof(ParsedValue)); darray_push(&to_operate_on, first_parsed_value); @@ -77,7 +77,12 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, break; darray_push(&operations, &token->type); (*index)++; - error_if_finished(file, tokens, index); + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + darray_free(&to_operate_on, free_parsed); + darray_free(&operations, NULL); + return (ParsedValueReturn){err, NULL}; + } ParsedValueReturn parsedValue = parse_token_full(file, tokens, index, true, false); if (parsedValue.err.exists) { @@ -87,10 +92,10 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, } else if (!parsedValue.value) { darray_free(&to_operate_on, free_parsed); darray_free(&operations, NULL); - return (ParsedValueReturn){ - create_err(token->line, token->column, token->length, file, - "Syntax Error", "expected value"), - NULL}; + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "expected value"), + NULL}; } darray_push(&to_operate_on, parsedValue.value); free(parsedValue.value); @@ -100,7 +105,7 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, memcpy(parsedValue, &output, sizeof(ParsedValue)); darray_free(&to_operate_on, NULL); darray_free(&operations, NULL); - return (ParsedValueReturn){no_err,parsedValue}; + return (ParsedValueReturn){no_err, parsedValue}; } void free_operation(void *ptr) { diff --git a/src/parser/parser.c b/src/parser/parser.c index 9e5bdb6..ea2b36d 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -27,13 +27,13 @@ const char *ValueTypeNames[] = { "access", "call", "declaration", "null", "boolean", "do wrap", "operations", "list", "dictionary", "function"}; -void error_if_finished(char *file, DArray *tokens, size_t *index) { +ArErr error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { Token *token = darray_get(tokens, tokens->size - 1); - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + return create_err(token->line, token->column, token->length, file, + "Syntax Error", "more code was expected"); } + return no_err; } size_t skip_newlines_and_indents(DArray *tokens, size_t *index) { @@ -94,8 +94,9 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index, token = darray_get(tokens, (*index) + 1); if (token->type != TOKEN_NEW_LINE) { return (ParsedValueReturn){ - create_err(token_indent->line, token_indent->column, token_indent->length, file, - "Syntax Error", "unexpected indent"), + create_err(token_indent->line, token_indent->column, + token_indent->length, file, "Syntax Error", + "unexpected indent"), NULL}; } } @@ -122,9 +123,11 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index, output = parse_dictionary(file, tokens, index); break; default: - fprintf(stderr, "%s:%zu:%zu error: syntax error\n", file, token->line, - token->column); - exit(EXIT_FAILURE); + return (ParsedValueReturn){create_err(token->line, + token->column, + token->length, file, + "Syntax Error", "unexpected token"), + NULL}; } // LHS required @@ -179,14 +182,12 @@ ArErr parser(char *file, DArray *parsed, DArray *tokens, bool inline_flag) { ParsedValueReturn parsed_code = parse_token(file, tokens, &index, inline_flag); if (parsed_code.err.exists) { - printf("%zu\n", old_index); return parsed_code.err; } else if (parsed_code.value) { if (expecting_new_line) { Token *token = darray_get(tokens, old_index); - fprintf(stderr, "%s:%zu:%zu error: expected a new line\n", file, - token->line, token->column); - exit(EXIT_FAILURE); + return create_err(token->line, token->column, token->length, file, + "Syntax Error", "expected new line"); } expecting_new_line = true; darray_push(parsed, parsed_code.value); diff --git a/src/parser/parser.h b/src/parser/parser.h index 13c3283..7eb94f3 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -67,7 +67,7 @@ ParsedValueReturn parse_token(char *file, DArray *tokens, size_t *index, void free_parsed(void *ptr); -void error_if_finished(char *file, DArray *tokens, size_t *index); +__attribute__((warn_unused_result)) ArErr error_if_finished(char *file, DArray *tokens, size_t *index); size_t skip_newlines_and_indents(DArray *tokens, size_t *index); diff --git a/src/runtime/declaration/declaration.c b/src/runtime/declaration/declaration.c new file mode 100644 index 0000000..182997a --- /dev/null +++ b/src/runtime/declaration/declaration.c @@ -0,0 +1,18 @@ +#include "declaration.h" + +ArErr runtime_declaration(Translated *translated, RuntimeState *state, + struct Stack *stack) { + int64_t length = pop_bytecode(translated, state); + int64_t offset = pop_bytecode(translated, state); + int64_t prehash = pop_bytecode(translated, state); + int64_t from_register = pop_byte(translated, state); + int64_t source_location_index = pop_bytecode(translated, state); + uint64_t hash = runtime_hash(arena_get(&translated->constants, offset), length, prehash); + ArgonObject * exists = hashmap_lookup_GC(stack->scope, hash); + if (exists) { + SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); + return create_err(source_location->line, source_location->column, source_location->length, state->path, "Runtime Error", "Identifier '%.*s' has already been declared in the current scope", length, arena_get(&translated->constants, offset)); + } + hashmap_insert_GC(stack->scope, hash, arena_get(&translated->constants, offset), state->registers[from_register], 0); + return no_err; +} \ No newline at end of file diff --git a/src/runtime/declaration/declaration.h b/src/runtime/declaration/declaration.h new file mode 100644 index 0000000..601fc16 --- /dev/null +++ b/src/runtime/declaration/declaration.h @@ -0,0 +1,8 @@ +#ifndef runtime_declaration_H +#define runtime_declaration_H +#include "../runtime.h" + +ArErr runtime_declaration(Translated *translated, RuntimeState *state, + struct Stack *stack); + +#endif // runtime_declaration_H \ No newline at end of file diff --git a/src/runtime/objects/functions/functions.c b/src/runtime/objects/functions/functions.c index 202e853..46e38a7 100644 --- a/src/runtime/objects/functions/functions.c +++ b/src/runtime/objects/functions/functions.c @@ -12,7 +12,7 @@ void init_function_type() { } void load_argon_function(Translated *translated, RuntimeState *state, - struct Stack stack) { + struct Stack *stack) { ArgonObject *object = init_child_argon_object(ARGON_FUNCTION_TYPE); object->type = TYPE_FUNCTION; uint64_t offset = pop_bytecode(translated, state); @@ -35,6 +35,6 @@ void load_argon_function(Translated *translated, RuntimeState *state, darray_armem_init(&object->value.argon_fn.bytecode, sizeof(uint64_t)); darray_armem_resize(&object->value.argon_fn.bytecode, length/object->value.argon_fn.bytecode.element_size); memcpy(object->value.argon_fn.bytecode.data, arena_get(&translated->constants, offset), length); - object->value.argon_fn.stack = stack; + object->value.argon_fn.stack = *stack; state->registers[0]=object; } \ No newline at end of file diff --git a/src/runtime/objects/functions/functions.h b/src/runtime/objects/functions/functions.h index 244f748..372a31a 100644 --- a/src/runtime/objects/functions/functions.h +++ b/src/runtime/objects/functions/functions.h @@ -4,6 +4,6 @@ void init_function_type(); -ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack stack); +ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack *stack); #endif // FUNCTION_H \ No newline at end of file diff --git a/src/runtime/objects/literals/literals.c b/src/runtime/objects/literals/literals.c new file mode 100644 index 0000000..ab7d3e6 --- /dev/null +++ b/src/runtime/objects/literals/literals.c @@ -0,0 +1,25 @@ +#include "../object.h" +#include +#include "literals.h" + +ArgonObject *ARGON_NULL_TYPE = NULL; +ArgonObject *ARGON_NULL = NULL; + +ArgonObject *ARGON_BOOL_TYPE = NULL; +ArgonObject *ARGON_TRUE = NULL; +ArgonObject *ARGON_FALSE = NULL; + +void init_literals() { + ARGON_NULL_TYPE = init_argon_class("NULL_TYPE"); + + ARGON_NULL = init_child_argon_object(ARGON_NULL_TYPE); + ARGON_NULL->type=TYPE_NULL; + + ARGON_BOOL_TYPE = init_argon_class("Bool"); + + ARGON_FALSE = init_child_argon_object(ARGON_BOOL_TYPE); + ARGON_FALSE->type=TYPE_BOOL; + + ARGON_TRUE = init_child_argon_object(ARGON_BOOL_TYPE); + ARGON_TRUE->type=TYPE_BOOL; +} \ No newline at end of file diff --git a/src/runtime/objects/literals/literals.h b/src/runtime/objects/literals/literals.h new file mode 100644 index 0000000..189d035 --- /dev/null +++ b/src/runtime/objects/literals/literals.h @@ -0,0 +1,12 @@ +#ifndef RUNTIME_LITERALS_H +#define RUNTIME_LITERALS_H +#include "../object.h" + +extern ArgonObject *ARGON_NULL; +extern ArgonObject *ARGON_FALSE; +extern ArgonObject *ARGON_TRUE; + +void init_literals(); + + +#endif // RUNTIME_LITERALS_H \ No newline at end of file diff --git a/src/runtime/objects/null/null.c b/src/runtime/objects/null/null.c deleted file mode 100644 index ce3b7d9..0000000 --- a/src/runtime/objects/null/null.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "../../internals/hashmap/hashmap.h" -#include "../object.h" -#include -#include "null.h" - -ArgonObject *ARGON_NULL_TYPE = NULL; -ArgonObject *ARGON_NULL = NULL; - -void init_null() { - ARGON_NULL_TYPE = init_argon_class("NULL_TYPE"); - - ARGON_NULL = init_child_argon_object(ARGON_NULL_TYPE); - ARGON_NULL->type=TYPE_NULL; -} \ No newline at end of file diff --git a/src/runtime/objects/null/null.h b/src/runtime/objects/null/null.h deleted file mode 100644 index 904e3bc..0000000 --- a/src/runtime/objects/null/null.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NULL_H -#define NULL_H -#include "../object.h" - -extern ArgonObject *ARGON_NULL; - -void init_null(); - - -#endif // NULL_H \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 877c37c..ace1975 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -2,8 +2,9 @@ #include "../err.h" #include "../hash_data/hash_data.h" #include "../translator/translator.h" +#include "declaration/declaration.h" #include "objects/functions/functions.h" -#include "objects/null/null.h" +#include "objects/literals/literals.h" #include "objects/object.h" #include "objects/string/string.h" #include "objects/type/type.h" @@ -29,7 +30,7 @@ void init_types() { init_type(); init_function_type(); - init_null(); + init_literals(); init_string_type(); init_base_field(); @@ -64,33 +65,50 @@ void load_const(Translated *translated, RuntimeState *state) { state->registers[to_register] = object; } +struct hashmap *runtime_hash_table = NULL; + +uint64_t runtime_hash(const void *data, size_t len, uint64_t prehash) { + if (!runtime_hash_table) { + runtime_hash_table = createHashmap(); + } else { + void *result = hashmap_lookup(runtime_hash_table, prehash); + if (result) { + return (uint64_t)result; + } + } + uint64_t hash = siphash64_bytes(data, len, siphash_key); + hashmap_insert(runtime_hash_table, prehash, 0, (void *)hash, 0); + return hash; +} + ArErr load_variable(Translated *translated, RuntimeState *state, - struct Stack stack) { + struct Stack *stack) { int64_t length = pop_bytecode(translated, state); int64_t offset = pop_bytecode(translated, state); + int64_t prehash = pop_bytecode(translated, state); int64_t source_location_index = pop_bytecode(translated, state); - char *name = checked_malloc(length); - memcpy(name, arena_get(&translated->constants, offset), length); - uint64_t hash = siphash64_bytes(name, length, siphash_key); - struct Stack *current_stack = &stack; + uint64_t hash = + runtime_hash(arena_get(&translated->constants, offset), length, prehash); + struct Stack *current_stack = stack; while (current_stack) { ArgonObject *result = hashmap_lookup_GC(current_stack->scope, hash); if (result) { state->registers[0] = result; - free(name); return no_err; } current_stack = current_stack->prev; } - SourceLocation *source_location = darray_get(&translated->source_locations, source_location_index); - ArErr err = create_err(source_location->line, source_location->column, length, state->path, "Name Error", "name '%.*s' is not defined", - (int)length, name); - free(name); + SourceLocation *source_location = + darray_get(&translated->source_locations, source_location_index); + ArErr err = create_err(source_location->line, source_location->column, + source_location->length, state->path, "Name Error", + "name '%.*s' is not defined", (int)length, + arena_get(&translated->constants, offset)); return err; } ArErr run_instruction(Translated *translated, RuntimeState *state, - struct Stack stack) { + struct Stack **stack) { OperationType opcode = pop_byte(translated, state); switch (opcode) { case OP_LOAD_NULL: @@ -100,10 +118,32 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, load_const(translated, state); break; case OP_LOAD_FUNCTION: - load_argon_function(translated, state, stack); + load_argon_function(translated, state, *stack); break; case OP_IDENTIFIER: - return load_variable(translated, state, stack); + return load_variable(translated, state, *stack); + case OP_DECLARE: + return runtime_declaration(translated, state, *stack); + case OP_BOOL:; + uint8_t to_register = pop_byte(translated, state); + state->registers[to_register] = ARGON_TRUE; + break; + case OP_JUMP_IF_FALSE:; + uint8_t from_register = pop_byte(translated, state); + uint64_t to = pop_bytecode(translated, state); + if (state->registers[from_register] == ARGON_FALSE) { + state->head = to; + } + break; + case OP_JUMP: + state->head = pop_bytecode(translated, state); + break; + case OP_NEW_SCOPE: + *stack = create_scope(*stack); + break; + case OP_POP_SCOPE: + *stack = (*stack)->prev; + break; default: return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", opcode); @@ -113,19 +153,21 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, RuntimeState init_runtime_state(Translated translated, char *path) { return (RuntimeState){ - checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0, - path}; + checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0, path, + ARGON_NULL}; } -Stack create_scope(Stack *prev) { - struct hashmap_GC *scope = createHashmap_GC(); - return (Stack){scope, prev}; +Stack *create_scope(Stack *prev) { + Stack *stack = ar_alloc(sizeof(Stack)); + stack->scope = createHashmap_GC(); + stack->prev = prev; + return stack; } -ArErr runtime(Translated translated, RuntimeState state, Stack stack) { +ArErr runtime(Translated translated, RuntimeState state, Stack *stack) { state.head = 0; while (state.head < translated.bytecode.size) { - ArErr err = run_instruction(&translated, &state, stack); + ArErr err = run_instruction(&translated, &state, &stack); if (err.exists) { return err; } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 17d9ee6..6ffe84e 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -8,19 +8,26 @@ typedef struct { ArgonObject **registers; size_t head; char*path; + ArgonObject * return_value; } RuntimeState; void init_types(); +extern struct hashmap * runtime_hash_table; + +uint64_t runtime_hash(const void *data, size_t len, uint64_t prehash); + +uint8_t pop_byte(Translated *translated, RuntimeState *state); + uint64_t pop_bytecode(Translated *translated, RuntimeState *state); ArErr run_instruction(Translated *translated, RuntimeState *state, - struct Stack stack); + struct Stack **stack); RuntimeState init_runtime_state(Translated translated, char *path); -Stack create_scope(Stack *prev); +Stack *create_scope(Stack *prev); -ArErr runtime(Translated translated, RuntimeState state, Stack stack); +ArErr runtime(Translated translated, RuntimeState state, Stack *stack); #endif // RUNTIME_H \ No newline at end of file diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index 8c5177f..a5542b2 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -21,7 +21,9 @@ this operation takes 3 operands. 1. the length of the variable name. 2. the offset in the constant buffer of the variable name. -3. the register of the given value (*) +3. the fixed hash of the variable name. +4. the register of the given value (*) +5. the index of the source location. ## OP_LOAD_NULL @@ -50,4 +52,33 @@ initilises a function to a given register. 1. the length of the identifer. 2. the offset of the identifier. -3. the index of the source location. +3. the fixed hash of the variable name. +4. the index of the source location. + +## OP_BOOL + +converts a value in a given register into true or false depending on the result from \_\_bool\_\_ + +1. the register to read and write to. (*) + +## OP_JUMP_IF_FALSE + +jumps when a the value in the given register is false. + +1. the register to read. (*) +1. the index to jump to. + +## OP_JUMP_IF_FALSE + +jumps unconditionally to an index. + +1. the index to jump to. + + +## OP_NEW_SCOPE + +creates a new stack + +## OP_POP_SCOPE + +pops the top scope off the current \ No newline at end of file diff --git a/src/translator/declaration/declaration.c b/src/translator/declaration/declaration.c index ba86a92..221b44c 100644 --- a/src/translator/declaration/declaration.c +++ b/src/translator/declaration/declaration.c @@ -1,6 +1,7 @@ #include "declaration.h" #include "../../parser/declaration/declaration.h" #include "../translator.h" +#include "../../hash_data/hash_data.h" #include #include #include @@ -20,11 +21,12 @@ size_t translate_parsed_declaration(Translated *translated, push_instruction_byte(translated, OP_DECLARE); push_instruction_code(translated, length); push_instruction_code(translated, offset); + push_instruction_code(translated, siphash64_bytes(singleDeclaration->name, length, siphash_key_fixed_for_translator)); push_instruction_byte(translated, 0); - } - if (delcarations.size != 1) { - push_instruction_byte(translated, OP_LOAD_NULL); - push_instruction_byte(translated, 0); + SourceLocation source_locations = {singleDeclaration->line, + singleDeclaration->column, length}; + push_instruction_code(translated, translated->source_locations.size); + darray_push(&translated->source_locations, &source_locations); } return first; } \ No newline at end of file diff --git a/src/translator/function/function.c b/src/translator/function/function.c index 9ad8d8d..5eecc24 100644 --- a/src/translator/function/function.c +++ b/src/translator/function/function.c @@ -10,6 +10,7 @@ size_t translate_parsed_function(Translated *translated, DArray main_bytecode = translated->bytecode; DArray _temp_bytecode; darray_init(&_temp_bytecode, sizeof(uint8_t)); + set_registers(translated, 1); translated->bytecode = _temp_bytecode; translate_parsed(translated, parsedFunction->body); size_t function_bytecode_offset = diff --git a/src/translator/identifier/identifier.c b/src/translator/identifier/identifier.c index 990ad0c..c515765 100644 --- a/src/translator/identifier/identifier.c +++ b/src/translator/identifier/identifier.c @@ -3,6 +3,7 @@ #include #include #include +#include "../../hash_data/hash_data.h" size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *parsedIdentifier) { size_t length = strlen(parsedIdentifier->name); @@ -11,6 +12,7 @@ size_t translate_parsed_identifier(Translated *translated, ParsedIdentifier *par size_t start = push_instruction_byte(translated, OP_IDENTIFIER); push_instruction_code(translated,length); push_instruction_code(translated, identifier_pos); + push_instruction_code(translated, siphash64_bytes(parsedIdentifier->name, length, siphash_key_fixed_for_translator)); SourceLocation source_locations = { parsedIdentifier->line, parsedIdentifier->column, diff --git a/src/translator/if/if.c b/src/translator/if/if.c new file mode 100644 index 0000000..9cac56a --- /dev/null +++ b/src/translator/if/if.c @@ -0,0 +1,45 @@ +#include "../../parser/if/if.h" +#include "../translator.h" +#include +#include +#include + +size_t translate_parsed_if(Translated *translated, DArray *parsedIf) { + size_t *jump_after_body_positions = + checked_malloc(parsedIf->size * sizeof(size_t)); + + size_t first = translated->bytecode.size; + + set_registers(translated, 1); + + for (uint64_t i = 0; i < parsedIf->size; i++) { + ParsedConditional *condition = darray_get(parsedIf, i); + push_instruction_byte(translated, OP_NEW_SCOPE); + if (condition->condition) { + translate_parsed(translated, condition->condition); + push_instruction_byte(translated, OP_BOOL); + push_instruction_byte(translated, 0); + push_instruction_byte(translated, OP_JUMP_IF_FALSE); + push_instruction_byte(translated, 0); + uint64_t last_jump_index = push_instruction_code(translated, 0); + translate_parsed(translated, condition->content); + push_instruction_byte(translated, OP_POP_SCOPE); + push_instruction_byte(translated, OP_JUMP); + jump_after_body_positions[i] = push_instruction_code(translated, 0); + set_instruction_code(translated, last_jump_index, + translated->bytecode.size); + push_instruction_byte(translated, OP_POP_SCOPE); + } else { + translate_parsed(translated, condition->content); + push_instruction_byte(translated, OP_POP_SCOPE); + jump_after_body_positions[i] = 0; + } + } + for (uint64_t i = 0; i < parsedIf->size; i++) { + if (jump_after_body_positions[i]) + set_instruction_code(translated, jump_after_body_positions[i], + translated->bytecode.size); + } + free(jump_after_body_positions); + return first; +} \ No newline at end of file diff --git a/src/translator/if/if.h b/src/translator/if/if.h new file mode 100644 index 0000000..e637b7d --- /dev/null +++ b/src/translator/if/if.h @@ -0,0 +1,7 @@ +#ifndef TRANSLATE_iF_H +#define TRANSLATE_iF_H +#include "../translator.h" + +size_t translate_parsed_if(Translated *translated, DArray *parsedIf); + +#endif // TRANSLATE_iF_H \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index f5cc225..ac74a31 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -4,6 +4,7 @@ #include "declaration/declaration.h" #include "function/function.h" #include "identifier/identifier.h" +#include "if/if.h" #include "number/number.h" #include "string/string.h" #include @@ -91,6 +92,10 @@ size_t push_instruction_byte(Translated *translator, uint8_t byte) { return offset; } +void set_instruction_byte(Translated *translator, size_t index, uint8_t byte) { + memcpy(translator->bytecode.data + index, &byte, sizeof(byte)); +} + size_t push_instruction_code(Translated *translator, uint64_t code) { size_t offset = translator->bytecode.size; uint8_t bytes[8]; @@ -101,6 +106,10 @@ size_t push_instruction_code(Translated *translator, uint64_t code) { return offset; } +void set_instruction_code(Translated *translator, size_t index, uint64_t code) { + memcpy(translator->bytecode.data + index, &code, sizeof(code)); +} + void set_registers(Translated *translator, uint8_t count) { if (count > translator->registerCount) translator->registerCount = count; @@ -125,7 +134,10 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) { return translate_parsed_function(translated, (ParsedFunction *)parsedValue->data); case AST_IDENTIFIER: - return translate_parsed_identifier(translated, (ParsedIdentifier *)parsedValue->data); + return translate_parsed_identifier(translated, + (ParsedIdentifier *)parsedValue->data); + case AST_IF: + return translate_parsed_if(translated, (DArray *)parsedValue->data); } return 0; } diff --git a/src/translator/translator.h b/src/translator/translator.h index 109363f..611981c 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -8,7 +8,7 @@ #include #include -typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER } OperationType; +typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION, OP_IDENTIFIER, OP_BOOL, OP_JUMP_IF_FALSE, OP_JUMP, OP_NEW_SCOPE, OP_POP_SCOPE } OperationType; typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types; typedef struct { @@ -39,8 +39,12 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length); size_t push_instruction_byte(Translated *translator, uint8_t byte); +void set_instruction_byte(Translated *translator, size_t index, uint8_t byte); + size_t push_instruction_code(Translated *translator, uint64_t code); +void set_instruction_code(Translated *translator, size_t index, uint64_t code); + void set_registers(Translated *translator, uint8_t count); Translated init_translator(); diff --git a/testing.ar b/testing.ar new file mode 100644 index 0000000..001ede4 --- /dev/null +++ b/testing.ar @@ -0,0 +1,3 @@ +let y = 1 +if (let x = let z = y, a=null) z +else x \ No newline at end of file