From fff4f6bcb5196f98068d157bdbaf223bfb1305bd Mon Sep 17 00:00:00 2001 From: William Bell <62452284+Ugric@users.noreply.github.com> Date: Thu, 28 Aug 2025 04:07:19 +0100 Subject: [PATCH] add while loop --- anonymous-function-test.ar | 4 +- .../parentheses-and-anonymous-function.c | 4 +- src/parser/parser.c | 8 +- src/parser/parser.h | 3 +- src/parser/while/while.c | 99 +++++++++++++++++++ src/parser/while/while.h | 20 ++++ src/translator/translator.c | 3 + src/translator/while/while.c | 57 +++++++++++ src/translator/while/while.h | 15 +++ 9 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 src/parser/while/while.c create mode 100644 src/parser/while/while.h create mode 100644 src/translator/while/while.c create mode 100644 src/translator/while/while.h diff --git a/anonymous-function-test.ar b/anonymous-function-test.ar index f75fd48..00bae09 100644 --- a/anonymous-function-test.ar +++ b/anonymous-function-test.ar @@ -1,3 +1 @@ -term.log(((x)=do - return x*x -)(3545436543634634)) \ No newline at end of file +term.log(((x)=x*x)()) \ No newline at end of file diff --git a/src/parser/parentheses-and-anonymous-function/parentheses-and-anonymous-function.c b/src/parser/parentheses-and-anonymous-function/parentheses-and-anonymous-function.c index 5e7eca7..0e502ac 100644 --- a/src/parser/parentheses-and-anonymous-function/parentheses-and-anonymous-function.c +++ b/src/parser/parentheses-and-anonymous-function/parentheses-and-anonymous-function.c @@ -1,7 +1,7 @@ #include "parentheses-and-anonymous-function.h" +#include "../../memory.h" #include "../assignable/identifier/identifier.h" #include "../function/function.h" -#include "../../memory.h" #include #include @@ -64,6 +64,8 @@ ParsedValueReturn parse_parentheses(char *file, DArray *tokens, size_t *index) { for (size_t i = 0; i < list.size; i++) { ParsedValue *item = darray_get(&list, i); if (item->type != AST_IDENTIFIER) { + darray_free(&list, free_parsed); + darray_free(¶meters, free_parameter); return (ParsedValueReturn){ create_err(token->line, token->column, token->length, file, "Syntax Error", "expected identifier"), diff --git a/src/parser/parser.c b/src/parser/parser.c index a3ca3bc..65481d9 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -23,6 +23,7 @@ #include "operations/operations.h" #include "return/return.h" #include "string/string.h" +#include "while/while.h" #include #include #include @@ -34,7 +35,7 @@ const char *ValueTypeNames[] = { "string", "assign", "identifier", "number", "if statement", "access", "call", "declaration", "null", "boolean", "do wrap", "operations", - "list", "dictionary", "function", "return"}; + "list", "dictionary", "function", "return", "while loop"}; ArErr error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { @@ -73,6 +74,8 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index, switch (token->type) { case TOKEN_IF: return parse_if(file, tokens, index); + case TOKEN_WHILE: + return parse_while(file, tokens, index); case TOKEN_RETURN: return parse_return(file, tokens, index); case TOKEN_LET: @@ -247,6 +250,9 @@ void free_parsed(void *ptr) { case AST_IF: free_parsed_if(parsed); break; + case AST_WHILE: + free_parsed_while(parsed); + break; case AST_OPERATION: free_operation(parsed); break; diff --git a/src/parser/parser.h b/src/parser/parser.h index 109cfd3..eafd728 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -49,7 +49,8 @@ typedef enum { AST_LIST, AST_DICTIONARY, AST_FUNCTION, - AST_RETURN + AST_RETURN, + AST_WHILE } ValueType; extern const char *ValueTypeNames[]; diff --git a/src/parser/while/while.c b/src/parser/while/while.c new file mode 100644 index 0000000..064fd9d --- /dev/null +++ b/src/parser/while/while.c @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include "while.h" +#include "../../lexer/token.h" +#include "../../memory.h" +#include "../parser.h" +#include + +ParsedValueReturn parse_while(char *file, DArray *tokens, size_t *index) { + Token *token = darray_get(tokens, *index); + (*index)++; + // Parse ( condition ) + token = darray_get(tokens, *index); + if (token->type != TOKEN_LPAREN) { + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "expected '(' after while"), + NULL}; + } + + (*index)++; + ArErr err = error_if_finished(file, tokens, index); + if (err.exists) { + return (ParsedValueReturn){err, NULL}; + } + skip_newlines_and_indents(tokens, index); + ParsedValueReturn condition = parse_token(file, tokens, index, true); + if (condition.err.exists) { + return condition; + } else if (!condition.value) { + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "expected condition"), + NULL}; + } + skip_newlines_and_indents(tokens, index); + + token = darray_get(tokens, *index); + if (token->type != TOKEN_RPAREN) { + if (condition.value) { + free_parsed(condition.value); + free(condition.value); + } + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "missing closing ')' in condition"), + NULL}; + } + + (*index)++; + err = error_if_finished(file, tokens, index); + if (err.exists) { + if (condition.value) { + free_parsed(condition.value); + free(condition.value); + } + return (ParsedValueReturn){err, NULL}; + } + // Parse the body + ParsedValueReturn parsed_content = parse_token(file, tokens, index, false); + + if (parsed_content.err.exists) { + if (condition.value) { + free_parsed(condition.value); + free(condition.value); + } + return parsed_content; + } + + if (!parsed_content.value) { + if (condition.value) { + free_parsed(condition.value); + free(condition.value); + } + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "expected body"), + NULL}; + } + + ParsedValue *Parsedvalue = checked_malloc(sizeof(ParsedValue)); + Parsedvalue->type = AST_WHILE; + ParsedWhile *Parsed_while = checked_malloc(sizeof(ParsedWhile)); + Parsedvalue->data = Parsed_while; + Parsed_while->condition = condition.value; + Parsed_while->content = parsed_content.value; + return (ParsedValueReturn){no_err, Parsedvalue}; +} + +void free_parsed_while(void *ptr) { + ParsedValue *parsedValue = ptr; + ParsedWhile *parsed_while = parsedValue->data; + free_parsed(parsed_while->condition); + free_parsed(parsed_while->content); + free(parsed_while); +} \ No newline at end of file diff --git a/src/parser/while/while.h b/src/parser/while/while.h new file mode 100644 index 0000000..87902f9 --- /dev/null +++ b/src/parser/while/while.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef PARSE_WHILE_H +#define PARSE_WHILE_H +#include "../parser.h" + +typedef struct { + ParsedValue * condition; + ParsedValue *content; +} ParsedWhile; + +ParsedValueReturn parse_while(char *file, DArray *tokens, size_t *index); + +void free_parsed_while(void *ptr); + +#endif // PARSE_WHILE_H \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index 524e05d..7e2843d 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -17,6 +17,7 @@ #include "operation/operation.h" #include "return/return.h" #include "string/string.h" +#include "while/while.h" #include #include #include @@ -148,6 +149,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, (ParsedIdentifier *)parsedValue->data); case AST_IF: return translate_parsed_if(translated, (DArray *)parsedValue->data, err); + case AST_WHILE: + return translate_parsed_while(translated, (ParsedWhile *)parsedValue->data, err); case AST_DOWRAP: return translate_parsed_dowrap(translated, (DArray *)parsedValue->data, err); diff --git a/src/translator/while/while.c b/src/translator/while/while.c new file mode 100644 index 0000000..a98de51 --- /dev/null +++ b/src/translator/while/while.c @@ -0,0 +1,57 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "while.h" +#include + +size_t translate_parsed_while(Translated *translated, ParsedWhile *parsedWhile, + ArErr *err) { + set_registers(translated, 1); + DArray return_jumps; + DArray *old_return_jumps = NULL; + if (translated->return_jumps) { + darray_init(&return_jumps, sizeof(size_t)); + old_return_jumps = translated->return_jumps; + translated->return_jumps = &return_jumps; + } + size_t first = push_instruction_byte(translated, OP_NEW_SCOPE); + translate_parsed(translated, parsedWhile->condition, err); + if (err->exists) { + return 0; + } + 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 jump_index = push_instruction_code(translated, 0); + translate_parsed(translated, parsedWhile->content, err); + push_instruction_byte(translated, OP_POP_SCOPE); + push_instruction_byte(translated, OP_JUMP); + push_instruction_code(translated, first); + + + + if (translated->return_jumps) { + push_instruction_byte(translated, OP_JUMP); + size_t skip_return = 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, skip_return, translated->bytecode.size); + darray_free(&return_jumps, NULL); + translated->return_jumps = old_return_jumps; + } + + set_instruction_code(translated, jump_index, + translated->bytecode.size); + return first; +} \ No newline at end of file diff --git a/src/translator/while/while.h b/src/translator/while/while.h new file mode 100644 index 0000000..82bf0c5 --- /dev/null +++ b/src/translator/while/while.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef TRANSLATE_WHILE_H +#define TRANSLATE_WHILE_H +#include "../translator.h" +#include "../../parser/while/while.h" + +size_t translate_parsed_while(Translated *translated, ParsedWhile *parsedWhile, + ArErr *err); + +#endif // TRANSLATE_WHILE_H \ No newline at end of file