diff --git a/.vscode/launch.json b/.vscode/launch.json index 8066bfc..4916ce1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/bin/argon", - "args": ["test.ar"], + "args": ["testing.ar"], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], diff --git a/gentest.py b/gentest.py index 59922b8..a05b12f 100644 --- a/gentest.py +++ b/gentest.py @@ -5,7 +5,7 @@ import random import sys -for i in range(100000000): +for i in range(10000): sys.stdout.write("\"") sys.stdout.write(str(random.random())) sys.stdout.write("\"\n") diff --git a/src/err.c b/src/err.c index a2e523f..94f5dca 100644 --- a/src/err.c +++ b/src/err.c @@ -15,6 +15,51 @@ #include #include +#ifdef _WIN32 +ssize_t getline(char **lineptr, size_t *n, FILE *stream) { + if (lineptr == NULL || n == NULL || stream == NULL) { + return -1; + } + + size_t pos = 0; + int c; + + if (*lineptr == NULL || *n == 0) { + *n = 128; // initial buffer size + *lineptr = malloc(*n); + if (*lineptr == NULL) { + return -1; + } + } + + while ((c = fgetc(stream)) != EOF) { + // Resize buffer if needed + if (pos + 1 >= *n) { + size_t new_size = *n * 2; + char *new_ptr = realloc(*lineptr, new_size); + if (new_ptr == NULL) { + return -1; + } + *lineptr = new_ptr; + *n = new_size; + } + + (*lineptr)[pos++] = (char)c; + + if (c == '\n') { + break; + } + } + + if (pos == 0 && c == EOF) { + return -1; // EOF and no data read + } + + (*lineptr)[pos] = '\0'; + return (ssize_t)pos; +} +#endif + const ArErr no_err = (ArErr){false}; ArErr create_err(int64_t line, int64_t column, int length, char *path, @@ -86,7 +131,6 @@ void output_err(ArErr err) { while ((len = getline(&buffer, &size, file)) != -1) { if (current_line == err.line) { - printf("bruh\n"); break; } current_line++; @@ -99,20 +143,24 @@ void output_err(ArErr err) { char *line_starts = buffer; size_t skipped_chars = 0; - while (*line_starts && isspace((unsigned char)*line_starts) && line_starts-buffer < err.column-1) { + while (*line_starts && isspace((unsigned char)*line_starts) && + line_starts - buffer < err.column - 1) { line_starts++; err.column--; skipped_chars++; } fprintf(stderr, " %zu | ", err.line); if (err.length) { - fprintf(stderr, "%.*s", (int)err.column-1, line_starts); + fprintf(stderr, "%.*s", (int)err.column - 1, line_starts); dyefg(stderr, DYE_RED); dye_style(stderr, DYE_STYLE_BOLD); fprintf(stderr, "%.*s", err.length, line_starts + err.column - 1); dye_style(stderr, DYE_STYLE_RESET); dyefg(stderr, DYE_RESET); - fprintf(stderr, "%.*s", (int)len - (int)skipped_chars-(int)err.column-(int)err.length, line_starts + (int)err.column + err.length - 1); + fprintf(stderr, "%.*s", + (int)len - (int)skipped_chars - (int)err.column - + (int)err.length, + line_starts + (int)err.column + err.length - 1); for (int64_t i = 0; i < err.column - 1; i++) { fprintf(stderr, " "); } diff --git a/src/hash_data/hash_data.c b/src/hash_data/hash_data.c index 4cfb464..6ad661a 100644 --- a/src/hash_data/hash_data.c +++ b/src/hash_data/hash_data.c @@ -4,10 +4,15 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#ifdef _WIN32 +#include +#include +#else #include +#include +#endif #include #include -#include #include "siphash/siphash.h" #include "hash_data.h" @@ -15,12 +20,19 @@ 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]) { +#ifdef _WIN32 + if (BCryptGenRandom(NULL, hash_key, 16, BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0) { + // Fallback or abort + } +#else int fd = open("/dev/urandom", O_RDONLY); if (fd < 0 || read(fd, hash_key, 16) != 16) { // Fallback or abort } close(fd); +#endif } uint64_t siphash64_bytes(const void *data, size_t len,const uint8_t hash_key[16]) { diff --git a/src/lexer/token.h b/src/lexer/token.h index 684e5a9..a696b27 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -79,10 +79,10 @@ typedef enum { TOKEN_COLON, TOKEN_EXCLAMATION, TOKEN_INVALID, -} TokenType; +} ArTokenType; typedef struct { - TokenType type; + ArTokenType type; size_t line; size_t column; size_t length; diff --git a/src/main.c b/src/main.c index f1c12ce..c21bec9 100644 --- a/src/main.c +++ b/src/main.c @@ -14,8 +14,6 @@ #include "../external/xxhash/xxhash.h" #include "hash_data/hash_data.h" -#include -#include #include #include #include @@ -26,11 +24,13 @@ #include #include #ifdef _WIN32 -#include -#define mkdir(path, mode) _mkdir(path) + #include + #include // for _mkdir + #include // for _stat #else -#include -#include + #include + #include + #include #endif #include "../external/cwalk/include/cwalk.h" #include @@ -43,6 +43,28 @@ #endif #include "err.h" +#if defined(_WIN32) || defined(_WIN64) + +// Windows / MinGW usually uses little-endian, so these can be no-ops +// But define them explicitly to avoid implicit declaration warnings + +static inline uint32_t le32toh(uint32_t x) { + return x; +} +static inline uint64_t le64toh(uint64_t x) { + return x; +} +static inline uint32_t htole32(uint32_t x) { + return x; +} +static inline uint64_t htole64(uint64_t x) { + return x; +} + +#else +#include // On Linux/BSD +#endif + char *get_current_directory() { char *buffer = NULL; @@ -72,16 +94,32 @@ char *get_current_directory() { } int ensure_dir_exists(const char *path) { - struct stat st = {0}; - - if (stat(path, &st) == -1) { - // Directory does not exist, create it - if (mkdir(path, 0755) != 0) { - perror("mkdir failed"); - return -1; +#ifdef _WIN32 + struct _stat st; + if (_stat(path, &st) != 0) { + // Directory does not exist, create it + if (_mkdir(path) != 0) { + perror("_mkdir failed"); + return -1; + } + } else if (!(st.st_mode & _S_IFDIR)) { + fprintf(stderr, "Path exists but is not a directory\n"); + return -1; } - } - return 0; +#else + struct stat st; + if (stat(path, &st) != 0) { + // Directory does not exist, create it + if (mkdir(path, 0755) != 0) { + perror("mkdir failed"); + return -1; + } + } else if (!S_ISDIR(st.st_mode)) { + fprintf(stderr, "Path exists but is not a directory\n"); + return -1; + } +#endif + return 0; } const char CACHE_FOLDER[] = "__arcache__"; diff --git a/src/parser/assignable/assign/assign.h b/src/parser/assignable/assign/assign.h index bfa13ef..a38e99c 100644 --- a/src/parser/assignable/assign/assign.h +++ b/src/parser/assignable/assign/assign.h @@ -11,7 +11,7 @@ typedef struct { ParsedValue * to; - TokenType type; + ArTokenType type; ParsedValue * from; } ParsedAssign; diff --git a/src/parser/dowrap/dowrap.c b/src/parser/dowrap/dowrap.c index 28f5b12..fc4301d 100644 --- a/src/parser/dowrap/dowrap.c +++ b/src/parser/dowrap/dowrap.c @@ -49,59 +49,57 @@ ParsedValueReturn parse_dowrap(char *file, DArray *tokens, size_t *index) { NULL}; } size_t indent_depth = 0; - bool temp_indent_depth_toggle = false; - size_t temp_indent_depth = 0; + bool has_body_started = false; + bool inside_body = false; bool pass = false; + DArray dowrap_tokens; darray_init(&dowrap_tokens, sizeof(Token)); DArray to_free; darray_init(&to_free, sizeof(char *)); - size_t temp_index_count = 0; + size_t dowrap_index = *index; + size_t last_normal_token = dowrap_index-1; - while (!pass && ++(*index) < tokens->size) { - token = darray_get(tokens, *index); + while (!pass && ++dowrap_index < tokens->size) { + token = darray_get(tokens, dowrap_index); switch (token->type) { - case TOKEN_INDENT: - temp_indent_depth_toggle = true; - if (dowrap_tokens.size == 0) { - indent_depth = strlen(token->value); - temp_indent_depth = indent_depth; - } else { - temp_indent_depth = strlen(token->value); - } - break; case TOKEN_NEW_LINE: - temp_indent_depth = 0; - temp_indent_depth_toggle = true; darray_push(&dowrap_tokens, token); - temp_index_count++; + inside_body = false; break; - default: - if (temp_indent_depth < indent_depth && temp_indent_depth_toggle) { - pass = true; - break; - } - if (temp_indent_depth > indent_depth) { - size_t indent_amount = temp_indent_depth - indent_depth; + case TOKEN_INDENT: + if (!inside_body && !has_body_started) { + indent_depth = token->length; + inside_body = true; + } else if (indent_depth < token->length) { + size_t indent_amount = token->length - indent_depth; Token indent_token; indent_token.line = token->line; indent_token.column = token->column; + indent_token.length = indent_amount; indent_token.type = TOKEN_INDENT; indent_token.value = repeat_space(indent_amount); darray_push(&dowrap_tokens, &indent_token); darray_push(&to_free, &indent_token.value); + inside_body = true; + } else if (indent_depth == token->length) { + inside_body = true; + } else if (indent_depth > token->length) { + inside_body = false; } - temp_indent_depth_toggle = false; - temp_indent_depth = 0; - temp_index_count = 0; + break; + default: + if (!inside_body) { + pass = true; + break; + } + last_normal_token = dowrap_index; + has_body_started = true; darray_push(&dowrap_tokens, token); } } - (*index) -= temp_index_count; - for (size_t i = 0; i < temp_index_count; i++) { - darray_pop(&dowrap_tokens, NULL); - } + *index = last_normal_token + 1; ArErr err = parser(file, dowrap_parsed, &dowrap_tokens, false); darray_free(&dowrap_tokens, NULL); diff --git a/src/parser/operations/operations.c b/src/parser/operations/operations.c index 04efa39..80c0f1d 100644 --- a/src/parser/operations/operations.c +++ b/src/parser/operations/operations.c @@ -16,10 +16,10 @@ ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) { if (to_operate_on->size == 1) { return *((ParsedValue *)darray_get(to_operate_on, 0)); } - TokenType operation = 0; + ArTokenType operation = 0; DArray positions; for (size_t i = 0; i < operations->size; i++) { - TokenType *current_operation = darray_get(operations, i); + ArTokenType *current_operation = darray_get(operations, i); if (operation < *current_operation) { if (operation != 0) { darray_free(&positions, NULL); @@ -68,7 +68,7 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, free(first_parsed_value); DArray operations; - darray_init(&operations, sizeof(TokenType)); + darray_init(&operations, sizeof(ArTokenType)); while (tokens->size > *index) { bool to_break = false; diff --git a/src/parser/operations/operations.h b/src/parser/operations/operations.h index 30b93a6..856c5e5 100644 --- a/src/parser/operations/operations.h +++ b/src/parser/operations/operations.h @@ -10,7 +10,7 @@ #include "../../lexer/token.h" // for Token typedef struct { - TokenType operation; + ArTokenType operation; DArray to_operate_on; // ParsedValue[] } ParsedOperation; diff --git a/src/translator/dowrap/dowrap.c b/src/translator/dowrap/dowrap.c new file mode 100644 index 0000000..a0098b3 --- /dev/null +++ b/src/translator/dowrap/dowrap.c @@ -0,0 +1,48 @@ +#include "dowrap.h" +#include + +size_t translate_parsed_dowrap(Translated *translated, DArray *parsedDowrap) { + set_registers(translated, 1); + + size_t first = translated->bytecode.size; + + if (parsedDowrap->size) { + DArray return_jumps; + push_instruction_byte(translated, OP_NEW_SCOPE); + darray_init(&return_jumps, sizeof(size_t)); + DArray *old_return_jumps = translated->return_jumps; + translated->return_jumps = &return_jumps; + for (size_t i = 0; i < parsedDowrap->size; i++) { + ParsedValue *parsedValue = darray_get(parsedDowrap, i); + translate_parsed(translated, parsedValue); + } + push_instruction_byte(translated, OP_LOAD_NULL); + push_instruction_byte(translated, 0); + if (!old_return_jumps) { + size_t return_jump_to = push_instruction_byte(translated, OP_POP_SCOPE); + for (size_t i = 0; i < return_jumps.size; i++) { + size_t *index = darray_get(&return_jumps, i); + set_instruction_code(translated, *index, return_jump_to); + } + } else { + push_instruction_byte(translated, OP_POP_SCOPE); + push_instruction_byte(translated, OP_JUMP); + size_t not_return_jump = push_instruction_code(translated, 0); + size_t return_jump_to = push_instruction_byte(translated, OP_POP_SCOPE); + push_instruction_byte(translated, OP_JUMP); + size_t return_up = push_instruction_code(translated, 0); + darray_push(old_return_jumps, &return_up); + for (size_t i = 0; i < return_jumps.size; i++) { + size_t *index = darray_get(&return_jumps, i); + set_instruction_code(translated, *index, return_jump_to); + } + set_instruction_code(translated, not_return_jump, translated->bytecode.size); + } + darray_free(&return_jumps, NULL); + translated->return_jumps = old_return_jumps; + } else { + push_instruction_byte(translated, OP_LOAD_NULL); + push_instruction_byte(translated, 0); + } + return first; +} \ No newline at end of file diff --git a/src/translator/dowrap/dowrap.h b/src/translator/dowrap/dowrap.h new file mode 100644 index 0000000..2e80ff1 --- /dev/null +++ b/src/translator/dowrap/dowrap.h @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef TRANSLATE_DO_WRAP_H +#define TRANSLATE_DO_WRAP_H +#include "../translator.h" + + +size_t translate_parsed_dowrap(Translated *translated, DArray *parsedDowrap); + +#endif // TRANSLATE_DO_WRAP_H \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index 7cf1e8e..c7e9d12 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -8,6 +8,7 @@ #include "../hash_data/hash_data.h" #include "../hashmap/hashmap.h" #include "declaration/declaration.h" +#include "dowrap/dowrap.h" #include "function/function.h" #include "identifier/identifier.h" #include "if/if.h" @@ -85,7 +86,8 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) { Translated init_translator() { Translated translated; - translated.registerCount = 0; + translated.registerCount = 1; + translated.return_jumps=NULL; darray_init(&translated.bytecode, sizeof(uint8_t)); darray_init(&translated.source_locations, sizeof(SourceLocation)); arena_init(&translated.constants); @@ -144,6 +146,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) { (ParsedIdentifier *)parsedValue->data); case AST_IF: return translate_parsed_if(translated, (DArray *)parsedValue->data); + case AST_DOWRAP: + return translate_parsed_dowrap(translated, (DArray *)parsedValue->data); } return 0; } diff --git a/src/translator/translator.h b/src/translator/translator.h index 0e6bbb1..7ea2aee 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -26,6 +26,7 @@ typedef struct { typedef struct { uint8_t registerCount; + DArray *return_jumps; DArray bytecode; DArray source_locations; ConstantArena constants; diff --git a/testing.ar b/testing.ar index 7f62b65..12f4433 100644 --- a/testing.ar +++ b/testing.ar @@ -5,4 +5,5 @@ let y = 1 let term = y if (let x = let z = y) do -else x \ No newline at end of file + do + x \ No newline at end of file