diff --git a/.gitignore b/.gitignore index 987f111..7ba7c8b 100644 --- a/.gitignore +++ b/.gitignore @@ -64,5 +64,6 @@ build *.yy.c *.yy.h +__isotope__ __arcache__ argon_modules \ No newline at end of file diff --git a/anonymous-function-test.ar b/anonymous-function-test.ar deleted file mode 100644 index fcda09c..0000000 --- a/anonymous-function-test.ar +++ /dev/null @@ -1,8 +0,0 @@ -let factorial(x) = do - if (x-1) return x * factorial(x-1) - return 1 - -let i = 10000000 -term.log(factorial(10000)) -while (i) do - i=i-1 \ No newline at end of file diff --git a/app.py b/app.py deleted file mode 100644 index 0bacd2d..0000000 --- a/app.py +++ /dev/null @@ -1,3 +0,0 @@ -i = 1_000_000 -while i: - i=i-1 \ No newline at end of file diff --git a/debug_arbin.py b/debug_arbin.py deleted file mode 100644 index 78d6216..0000000 --- a/debug_arbin.py +++ /dev/null @@ -1,130 +0,0 @@ -# SPDX-FileCopyrightText: 2025 William Bell -# -# SPDX-License-Identifier: GPL-3.0-or-later - -import struct -from enum import Enum, EnumMeta, auto - -class AutoEnumMeta(EnumMeta): - @classmethod - def __prepare__(metacls, clsname, bases, **kwargs): - d = super().__prepare__(clsname, bases, **kwargs) - d['_next_value'] = 254 - return d - - def _generate_next_value_(cls, name, start, count, last_values): - value = cls._next_value - cls._next_value += 1 - return value - -class OperationType(Enum, metaclass=AutoEnumMeta): - OP_LOAD_CONST = auto() - OP_DECLARE = auto() - OP_LOAD_NULL = auto() - OP_JUMP = auto() - -class Types(Enum, metaclass=AutoEnumMeta): - TYPE_OP_STRING = auto() - TYPE_OP_NUMBER = auto() - -def read_arbin(filename): - with open(filename, "rb") as f: - # Read and verify file identifier (4 bytes) - file_id = f.read(4) - if file_id != b"ARBI": - raise ValueError("Invalid file identifier") - - # Read version number (uint64_t, little-endian) - version_number, = struct.unpack(" int: - print("OP_LOAD_CONST ", end="") - i+=1 - register = data["bytecode"][i] - print("To Register",register,"", end="") - i+=1 - match data["bytecode"][i]: - case Types.TYPE_OP_STRING.value: - print("TYPE_OP_STRING ", end="") - case Types.TYPE_OP_NUMBER.value: - print("TYPE_OP_NUMBER ", end="") - i+=1 - length = data["bytecode"][i] - i+=1 - offset = data["bytecode"][i] - i+=1 - print("Length",length,"", end="") - print("Offset",offset,"") - registers[register] = data["constants"][offset:offset+length].decode() - print("const value:", registers[register]) - return i - - def OP_DECLARE(registers,data, i) -> int: - print("OP_DECLARE ", end="") - i+=1 - length = data["bytecode"][i] - i+=1 - offset = data["bytecode"][i] - i+=1 - from_register = data["bytecode"][i] - i+=1 - print("Name Length",length,"", end="") - print("Name Offset",offset,"", end="") - print("From Register",from_register,"") - print("output: let", data['constants'][offset:offset+length].decode(),'=',registers[from_register]) - return i - def OP_LOAD_NULL(registers,data, i) -> int: - print("OP_LOAD_NULL ", end="") - i+=1 - to_register = data["bytecode"][i] - i+=1 - print("To Register",to_register,"") - registers[to_register] = "null" - return i -if __name__ == "__main__": - filename = "out.arbin" - data = read_arbin(filename) - print(f"Version: {data['version']}") - print(f"Register Count: {data['register_count']}") - print(f"Constants Size: {data['constants_size']} bytes") - print(f"Bytecode Length: {data['bytecode_size']} elements") - - registers = ["null"]*data['register_count'] - - i=0 - while i= 3) do - let filename = json.parse(disposition[2].splitN("=", 2)[1]) - req.files[name] = __makeFile(filename, headers["content-type"], body) - else do - req.formdata[name] = body.to("string") - res.next() - - -let formdata(req, res) = do - req.formdata = {} - req.files = {} - - if (req.method != "POST") return res.next() - if ("content-type" not in req.headers) return res.next() - let loweredContentType = req.headers["content-type"].lower() - if (loweredContentType.startswith("multipart/form-data")) return __multipart(req, res) - else if (loweredContentType.startswith("application/x-www-form-urlencoded")) req.formdata = url.decodeURLQuery(req.buffer.body.to("string")) - else if (loweredContentType.startswith("application/json")) req.formdata = json.parse(req.buffer.body.to("string")) - else req.files.file = __makeFile("file", req.headers["content-type"], req.buffer.body) - res.next() \ No newline at end of file diff --git a/gentest.py b/gentest.py deleted file mode 100644 index 69a8498..0000000 --- a/gentest.py +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-FileCopyrightText: 2025 William Bell -# -# SPDX-License-Identifier: GPL-3.0-or-later - -import random -import sys - -for i in range(10000000): - sys.stdout.write("\"hello world\"\n") - diff --git a/perf.data b/perf.data new file mode 100644 index 0000000..4f37086 Binary files /dev/null and b/perf.data differ diff --git a/perf.data.old b/perf.data.old new file mode 100644 index 0000000..78e08e2 Binary files /dev/null and b/perf.data.old differ diff --git a/src/arobject.h b/src/arobject.h index 6914ed9..1c3bdc6 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -56,6 +56,7 @@ struct string_struct { }; typedef struct Stack { + uint64_t fake_new_scopes; struct hashmap_GC *scope; struct Stack *prev; } Stack; diff --git a/src/err.c b/src/err.c index 92b292c..7c9485a 100644 --- a/src/err.c +++ b/src/err.c @@ -73,8 +73,7 @@ ArErr create_err(int64_t line, int64_t column, int length, char *path, err.length = length; // Copy error type safely - strncpy(err.type, type, sizeof(err.type) - 1); - err.type[sizeof(err.type) - 1] = '\0'; + snprintf(err.type, sizeof(err.type), "%s",(char*)type); // Format error message va_list args; diff --git a/src/parser/not/not.c b/src/parser/not/not.c new file mode 100644 index 0000000..640dcea --- /dev/null +++ b/src/parser/not/not.c @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include "not.h" +#include "../../lexer/token.h" +#include "../../memory.h" +#include "../parser.h" +#include + +ParsedValueReturn parse_not(char *file, DArray *tokens, size_t *index) { + bool invert = true; + (*index)++; + while (tokens->size > *index) { + Token *token = darray_get(tokens, *index); + if (token->type != TOKEN_EXCLAMATION) { + ParsedValueReturn value = + parse_token_full(file, tokens, index, true, false); + if (value.err.exists) { + return value; + } else if (!value.value) { + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, + "Syntax Error", "expected value"), + NULL}; + } + + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + ParsedToBool *parsedToBool = checked_malloc(sizeof(ParsedToBool)); + parsedToBool->value = value.value; + parsedToBool->invert = invert; + parsedValue->data = parsedToBool; + parsedValue->type = AST_TO_BOOL; + return (ParsedValueReturn){no_err, parsedValue}; + } + invert = !invert; + (*index)++; + } + ArErr err = error_if_finished(file, tokens, index); + return (ParsedValueReturn){err, NULL}; +} + +void free_not(void *ptr) { + ParsedValue *parsedValue = ptr; + ParsedToBool *parsedToBool = parsedValue->data; + free_parsed(parsedToBool->value); + free(parsedToBool->value); + free(parsedToBool); +} \ No newline at end of file diff --git a/src/parser/not/not.h b/src/parser/not/not.h new file mode 100644 index 0000000..c29fdd8 --- /dev/null +++ b/src/parser/not/not.h @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef NOT_H +#define NOT_H +#include "../parser.h" + +typedef struct { + bool invert; + ParsedValue*value; +} ParsedToBool; + +ParsedValueReturn parse_not(char *file, DArray *tokens, size_t *index); + +void free_not(void *ptr); + +#endif // NOT_H \ No newline at end of file diff --git a/src/parser/operations/operations.c b/src/parser/operations/operations.c index 1bcd5e2..fe4b46d 100644 --- a/src/parser/operations/operations.c +++ b/src/parser/operations/operations.c @@ -42,24 +42,22 @@ ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) { operationStruct->column = operation.column; operationStruct->length = operation.length; darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue)); - size_t last_position = 0; size_t to_operate_on_last_position = 0; for (size_t i = 0; i < positions.size; i++) { size_t *position = darray_get(&positions, i); DArray to_operate_on_slice = darray_slice( to_operate_on, to_operate_on_last_position, (*position) + 1); DArray operations_slice = - darray_slice(operations, last_position, *position); + darray_slice(operations, to_operate_on_last_position, (*position)); ParsedValue result = convert_to_operation(&to_operate_on_slice, &operations_slice); darray_push(&operationStruct->to_operate_on, &result); - last_position = (*position); to_operate_on_last_position = (*position) + 1; } DArray to_operate_on_slice = darray_slice( to_operate_on, to_operate_on_last_position, to_operate_on->size); DArray operations_slice = - darray_slice(operations, last_position, operations->size); + darray_slice(operations, to_operate_on_last_position, operations->size); ParsedValue result = convert_to_operation(&to_operate_on_slice, &operations_slice); darray_push(&operationStruct->to_operate_on, &result); 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 0e502ac..2a3a63e 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,3 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + #include "parentheses-and-anonymous-function.h" #include "../../memory.h" #include "../assignable/identifier/identifier.h" diff --git a/src/parser/parser.c b/src/parser/parser.c index 65481d9..62222f6 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -13,7 +13,6 @@ #include "assignable/identifier/identifier.h" #include "declaration/declaration.h" #include "dictionary/dictionary.h" -#include "parentheses-and-anonymous-function/parentheses-and-anonymous-function.h" #include "dowrap/dowrap.h" #include "function/function.h" #include "if/if.h" @@ -21,8 +20,10 @@ #include "literals/literals.h" #include "number/number.h" #include "operations/operations.h" +#include "parentheses-and-anonymous-function/parentheses-and-anonymous-function.h" #include "return/return.h" #include "string/string.h" +#include "not/not.h" #include "while/while.h" #include #include @@ -32,10 +33,10 @@ #include const char *ValueTypeNames[] = { - "string", "assign", "identifier", "number", - "if statement", "access", "call", "declaration", - "null", "boolean", "do wrap", "operations", - "list", "dictionary", "function", "return", "while loop"}; + "string", "assign", "identifier", "number", "if statement", + "access", "call", "declaration", "null", "boolean", + "do wrap", "operations", "list", "dictionary", "function", + "return", "while loop", "not"}; ArErr error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { @@ -138,6 +139,9 @@ ParsedValueReturn parse_token_full(char *file, DArray *tokens, size_t *index, case TOKEN_LBRACE: output = parse_dictionary(file, tokens, index); break; + case TOKEN_EXCLAMATION: + output = parse_not(file, tokens, index); + break; default: return (ParsedValueReturn){create_err(token->line, token->column, token->length, file, "Syntax Error", @@ -271,5 +275,8 @@ void free_parsed(void *ptr) { case AST_RETURN: free_parsed_return(parsed); break; + case AST_TO_BOOL: + free_not(parsed); + break; } } \ No newline at end of file diff --git a/src/parser/parser.h b/src/parser/parser.h index eafd728..c188f9b 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -50,7 +50,8 @@ typedef enum { AST_DICTIONARY, AST_FUNCTION, AST_RETURN, - AST_WHILE + AST_WHILE, + AST_TO_BOOL } ValueType; extern const char *ValueTypeNames[]; diff --git a/src/returnTypes.h b/src/returnTypes.h index c1fe11f..7130006 100644 --- a/src/returnTypes.h +++ b/src/returnTypes.h @@ -9,7 +9,7 @@ #include #include "arobject.h" -#define ERR_MSG_MAX_LEN 256 +#define ERR_MSG_MAX_LEN 64 typedef struct ArErr { bool exists; diff --git a/src/runtime/assignment/assignment.c b/src/runtime/assignment/assignment.c index 761630f..60d37d3 100644 --- a/src/runtime/assignment/assignment.c +++ b/src/runtime/assignment/assignment.c @@ -21,6 +21,7 @@ void runtime_assignment(Translated *translated, RuntimeState *state, if (exists) { hashmap_insert_GC(current_stack->scope, hash, key, state->registers[from_register], 0); + return; } } hashmap_insert_GC(stack->scope, hash, key, state->registers[from_register], diff --git a/src/runtime/call/call.c b/src/runtime/call/call.c index a3ce6b6..d368253 100644 --- a/src/runtime/call/call.c +++ b/src/runtime/call/call.c @@ -6,7 +6,6 @@ #include "call.h" #include "../../hash_data/hash_data.h" -#include "../objects/literals/literals.h" #include "../objects/string/string.h" #include #include @@ -156,7 +155,7 @@ void run_call(ArgonObject *original_object, size_t argc, ArgonObject **argv, *state->currentStackFramePointer, (*state->currentStackFramePointer)->depth + 1}; for (size_t i = 0; i < new_stackFrame.translated.registerCount; i++) { - new_stackFrame.state.registers[i] = ARGON_NULL; + new_stackFrame.state.registers[i] = NULL; } if (CStackFrame) { runtime(new_stackFrame.translated, new_stackFrame.state, diff --git a/src/runtime/internals/hashmap/hashmap.c b/src/runtime/internals/hashmap/hashmap.c index bcc7d2b..6eb0edd 100644 --- a/src/runtime/internals/hashmap/hashmap.c +++ b/src/runtime/internals/hashmap/hashmap.c @@ -15,18 +15,19 @@ #include struct hashmap_GC *createHashmap_GC() { - size_t size = 8; - struct hashmap_GC *t = - (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC)); - t->size = size; - t->order = 1; - t->list = (struct node_GC **)ar_alloc(sizeof(struct node_GC *) * size); - memset(t->list, 0, sizeof(struct node_GC *) * size); - t->count = 0; - return t; + size_t size = 8; + struct hashmap_GC *t = + (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC) + sizeof(struct node_GC *) * size); + t->size = size; + t->order = 1; + t->list = (struct node_GC **)((char*)t + sizeof(struct hashmap_GC)); + memset(t->list, 0, sizeof(struct node_GC *) * size); + t->count = 0; + return t; } void clear_hashmap_GC(struct hashmap_GC *t) { + if (!t->count) return; t->order = 1; t->count = 0; memset(t->list, 0, sizeof(struct node_GC *) * t->size); diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index 69fe289..7a87f75 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -7,7 +7,6 @@ #include "number.h" #include "../functions/functions.h" #include "../string/string.h" -#include #include #include #include diff --git a/src/runtime/objects/string/string.c b/src/runtime/objects/string/string.c index 02704bc..e56edbd 100644 --- a/src/runtime/objects/string/string.c +++ b/src/runtime/objects/string/string.c @@ -13,15 +13,14 @@ ArgonObject *ARGON_STRING_TYPE = NULL; -ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, +ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash, uint64_t hash) { ArgonObject *object = new_object(); add_builtin_field(object, __class__, ARGON_STRING_TYPE); add_builtin_field(object, field_length, new_number_object_from_int64(length)); object->type = TYPE_STRING; - object->value.as_str.data = ar_alloc_atomic(length); - memcpy(object->value.as_str.data, data, length); + object->value.as_str.data = data; object->value.as_str.prehash = prehash; object->value.as_str.hash_computed = hash; object->value.as_str.hash = hash; @@ -30,6 +29,13 @@ ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, return object; } +ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, + uint64_t hash) { + char*data_copy = ar_alloc_atomic(length); + memcpy(data_copy, data, length); + return new_string_object_without_memcpy(data_copy,length, prehash, hash); +} + ArgonObject *new_string_object_null_terminated(char *data) { return new_string_object(data, strlen(data), 0, 0); } \ No newline at end of file diff --git a/src/runtime/objects/string/string.h b/src/runtime/objects/string/string.h index f093741..ba10dc7 100644 --- a/src/runtime/objects/string/string.h +++ b/src/runtime/objects/string/string.h @@ -10,6 +10,9 @@ extern ArgonObject *ARGON_STRING_TYPE; +ArgonObject *new_string_object_without_memcpy(char *data, size_t length, uint64_t prehash, + uint64_t hash); + ArgonObject *new_string_object(char *data, size_t length, uint64_t prehash, uint64_t hash); ArgonObject *new_string_object_null_terminated(char*data); diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index a567b3f..70f4c61 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -359,12 +359,11 @@ ArgonObject *ARGON_STRING_TYPE___add__(size_t argc, ArgonObject **argv, return ARGON_NULL; } size_t length = argv[0]->value.as_str.length + argv[1]->value.as_str.length; - char *concat = malloc(length); + char *concat = ar_alloc_atomic(length); memcpy(concat, argv[0]->value.as_str.data, argv[0]->value.as_str.length); memcpy(concat + argv[0]->value.as_str.length, argv[1]->value.as_str.data, argv[1]->value.as_str.length); - ArgonObject *object = new_string_object(concat, length, 0, 0); - free(concat); + ArgonObject *object = new_string_object_without_memcpy(concat, length, 0, 0); return object; } @@ -485,6 +484,7 @@ void bootstrap_types() { ARGON_NULL_TYPE = new_object(); add_builtin_field(ARGON_NULL_TYPE, __base__, BASE_CLASS); ARGON_NULL = new_object(); + ARGON_NULL->type = TYPE_NULL; add_builtin_field(ARGON_NULL, __class__, ARGON_NULL_TYPE); ARGON_NULL->as_bool = false; @@ -681,22 +681,27 @@ RuntimeState init_runtime_state(Translated translated, char *path) { NULL, {0, 0, 0}, {}}; - for (size_t i = 0;iscope = createHashmap_GC(); - stack->prev = prev; - return stack; + if (!prev || prev->scope->count) { + Stack *stack = ar_alloc(sizeof(Stack)); + stack->fake_new_scopes = 0; + stack->scope = createHashmap_GC(); + stack->prev = prev; + return stack; + } + prev->fake_new_scopes++; + return prev; } void runtime(Translated _translated, RuntimeState _state, Stack *stack, ArErr *err) { - static void *dispatch_table[] = { + static void *const dispatch_table[] = { [OP_LOAD_STRING] = &&DO_LOAD_STRING, [OP_DECLARE] = &&DO_DECLARE, [OP_LOAD_NULL] = &&DO_LOAD_NULL, @@ -720,7 +725,8 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, [OP_SUBTRACTION] = &&DO_SUBTRACTION, [OP_LOAD_ACCESS_FUNCTION] = &&DO_LOAD_ACCESS_FUNCTION, [OP_MULTIPLICATION] = &&DO_MULTIPLICATION, - [OP_DIVISION] = &&DO_DIVISION}; + [OP_DIVISION] = &&DO_DIVISION, + [OP_NOT] = &&DO_NOT}; _state.head = 0; StackFrame *currentStackFrame = ar_alloc(sizeof(StackFrame)); @@ -756,15 +762,16 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, runtime_assignment(translated, state, currentStackFrame->stack); continue; DO_BOOL: { - uint8_t to_register = pop_byte(translated, state); - if (likely(state->registers[to_register]->type != TYPE_OBJECT)) { - state->registers[to_register] = - state->registers[to_register]->as_bool ? ARGON_TRUE : ARGON_FALSE; + if (state->registers[0] == ARGON_TRUE || + state->registers[0] == ARGON_FALSE) + continue; + if (likely(state->registers[0]->type != TYPE_OBJECT)) { + state->registers[0] = + state->registers[0]->as_bool ? ARGON_TRUE : ARGON_FALSE; continue; } ArgonObject *args[] = {ARGON_BOOL_TYPE, state->registers[0]}; - state->registers[to_register] = - ARGON_BOOL_TYPE___new__(2, args, err, state); + state->registers[0] = ARGON_BOOL_TYPE___new__(2, args, err, state); continue; } DO_JUMP_IF_FALSE: { @@ -775,6 +782,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, } continue; } + DO_NOT: + state->registers[0] = + state->registers[0] == ARGON_FALSE ? ARGON_TRUE : ARGON_FALSE; + continue; DO_JUMP: state->head = pop_bytecode(translated, state); continue; @@ -785,6 +796,10 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, clear_hashmap_GC(currentStackFrame->stack->scope); continue; DO_POP_SCOPE: + if (currentStackFrame->stack->fake_new_scopes) { + currentStackFrame->stack->fake_new_scopes--; + goto DO_EMPTY_SCOPE; + } currentStackFrame->stack = currentStackFrame->stack->prev; continue; DO_INIT_CALL: { diff --git a/src/shell.c b/src/shell.c index a380368..0a36a92 100644 --- a/src/shell.c +++ b/src/shell.c @@ -91,7 +91,8 @@ int execute_code(FILE *stream, char *path, Stack *scope, hashmap_free(__translated.constants.hashmap, NULL); Translated translated = { - __translated.registerCount, __translated.registerAssignment, NULL, {}, {}, __translated.path}; + __translated.registerCount, __translated.registerAssignment, NULL, {}, {}, + __translated.path}; translated.bytecode.data = ar_alloc(__translated.bytecode.capacity); memcpy(translated.bytecode.data, __translated.bytecode.data, __translated.bytecode.capacity); @@ -198,11 +199,13 @@ int shell() { totranslatelength = 0; }; int indent = 0; + int last_indent = 0; char textBefore[] = ">>> "; // Dynamic array of lines do { + last_indent = indent; // indent string size_t isz = (size_t)indent * 4; char *indentStr = (char *)malloc(isz + 1); @@ -253,7 +256,7 @@ int shell() { strcpy(textBefore, "... "); free(indentStr); - } while (indent > 0); + } while (indent > 0 || last_indent != 0); totranslate = realloc(totranslate, totranslatelength + 1); totranslate[totranslatelength] = '\0'; RuntimeState runtime_state; @@ -263,9 +266,12 @@ int shell() { if (resp) { continue; } - ArErr err = no_err; - argon_call(output_object, 1, (ArgonObject *[]){runtime_state.registers[0]}, - &err, &runtime_state); + if (runtime_state.registers[0]) { + ArErr err = no_err; + argon_call(output_object, 1, + (ArgonObject *[]){runtime_state.registers[0]}, &err, + &runtime_state); + } totranslatelength = 0; } diff --git a/src/shell.h b/src/shell.h index 7c7b1f3..e75a179 100644 --- a/src/shell.h +++ b/src/shell.h @@ -9,4 +9,4 @@ int shell(); -#endif // ARGON_SHELL_H \ No newline at end of file +#endif // ARGON_SHELL_H \ No newline at end of file diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index 1e45868..f1d5788 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -71,9 +71,7 @@ initilises a function to a given register. ## 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. (*) +converts a value in register 0 into true or false depending on the result from \_\_bool\_\_ (using asBool if the object is a primitive) ## OP_JUMP_IF_FALSE @@ -181,4 +179,8 @@ performs an division between register A and register B, storing the result in re 1. the register A (*) 2. the register B (*) -2. the register C (*) \ No newline at end of file +2. the register C (*) + +## OP_NOT + +inverts the boolean value in register 0. \ No newline at end of file diff --git a/src/translator/if/if.c b/src/translator/if/if.c index d21e393..e6088ea 100644 --- a/src/translator/if/if.c +++ b/src/translator/if/if.c @@ -40,7 +40,6 @@ size_t translate_parsed_if(Translated *translated, DArray *parsedIf, 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 last_jump_index = push_instruction_code(translated, 0); diff --git a/src/translator/operation/operation.c b/src/translator/operation/operation.c index bd234e0..cb46c38 100644 --- a/src/translator/operation/operation.c +++ b/src/translator/operation/operation.c @@ -11,7 +11,7 @@ size_t translate_operation(Translated *translated, ParsedOperation *operation, ArErr *err) { - if (operation->operation == TOKEN_AND) { + if (operation->operation == TOKEN_AND || operation->operation == TOKEN_OR) { size_t *jump_to_if_false = checked_malloc(operation->to_operate_on.size * sizeof(size_t)); uint8_t registerA = translated->registerAssignment++; @@ -21,7 +21,7 @@ size_t translate_operation(Translated *translated, ParsedOperation *operation, uint64_t position = translate_parsed( translated, darray_get(&operation->to_operate_on, i), err); if (i == 0) - position = first; + first = position; if (err->exists) { free(jump_to_if_false); return first; @@ -31,16 +31,21 @@ size_t translate_operation(Translated *translated, ParsedOperation *operation, push_instruction_byte(translated, registerA); push_instruction_byte(translated, OP_BOOL); - push_instruction_byte(translated, registerA); + if (operation->operation == TOKEN_OR) push_instruction_byte(translated, OP_NOT); push_instruction_byte(translated, OP_JUMP_IF_FALSE); - push_instruction_byte(translated, registerA); + push_instruction_byte(translated, 0); jump_to_if_false[i] = push_instruction_code(translated, 0); } for (size_t i = 0; i < operation->to_operate_on.size; i++) { set_instruction_code(translated, jump_to_if_false[i], translated->bytecode.size); } + push_instruction_byte(translated, OP_COPY_TO_REGISTER); + push_instruction_byte(translated, registerA); + push_instruction_byte(translated, 0); + push_instruction_byte(translated, OP_LOAD_NULL); + push_instruction_byte(translated, registerA); free(jump_to_if_false); return first; diff --git a/src/translator/translator.c b/src/translator/translator.c index cbba858..efbea54 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -6,10 +6,11 @@ #include "translator.h" #include "../hash_data/hash_data.h" +#include "../parser/not/not.h" #include "access/access.h" +#include "assignment/assignment.h" #include "call/call.h" #include "declaration/declaration.h" -#include "assignment/assignment.h" #include "dowrap/dowrap.h" #include "function/function.h" #include "identifier/identifier.h" @@ -148,7 +149,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, case AST_IF: return translate_parsed_if(translated, (DArray *)parsedValue->data, err); case AST_WHILE: - return translate_parsed_while(translated, (ParsedWhile *)parsedValue->data, err); + return translate_parsed_while(translated, (ParsedWhile *)parsedValue->data, + err); case AST_DOWRAP: return translate_parsed_dowrap(translated, (DArray *)parsedValue->data, err); @@ -165,7 +167,15 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, err); case AST_ASSIGN: return translate_parsed_assignment(translated, - (ParsedAssign *)parsedValue->data, err); + (ParsedAssign *)parsedValue->data, err); + case AST_TO_BOOL: { + size_t first = translate_parsed( + translated, ((ParsedToBool *)parsedValue->data)->value, err); + push_instruction_byte(translated, OP_BOOL); + if (((ParsedToBool *)parsedValue->data)->invert) + push_instruction_byte(translated, OP_NOT); + return first; + } } return 0; } diff --git a/src/translator/translator.h b/src/translator/translator.h index 3a63935..370bbce 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -38,7 +38,8 @@ typedef enum { OP_SUBTRACTION, OP_LOAD_ACCESS_FUNCTION, OP_MULTIPLICATION, - OP_DIVISION + OP_DIVISION, + OP_NOT } OperationType; void arena_resize(ConstantArena *arena, size_t new_size); diff --git a/src/translator/while/while.c b/src/translator/while/while.c index 2787abb..713667c 100644 --- a/src/translator/while/while.c +++ b/src/translator/while/while.c @@ -18,12 +18,12 @@ size_t translate_parsed_while(Translated *translated, ParsedWhile *parsedWhile, translated->return_jumps = &return_jumps; } size_t first = push_instruction_byte(translated, OP_NEW_SCOPE); - size_t start_of_loop = translate_parsed(translated, parsedWhile->condition, err); + size_t start_of_loop = + 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); @@ -31,9 +31,8 @@ size_t translate_parsed_while(Translated *translated, ParsedWhile *parsedWhile, push_instruction_byte(translated, OP_EMPTY_SCOPE); push_instruction_byte(translated, OP_JUMP); push_instruction_code(translated, start_of_loop); - - - + set_instruction_code(translated, jump_index, translated->bytecode.size); + push_instruction_byte(translated, OP_POP_SCOPE); if (translated->return_jumps) { push_instruction_byte(translated, OP_JUMP); size_t skip_return = push_instruction_code(translated, 0); @@ -50,8 +49,5 @@ size_t translate_parsed_while(Translated *translated, ParsedWhile *parsedWhile, 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/test.ar b/test.ar deleted file mode 100644 index 04ba1bc..0000000 --- a/test.ar +++ /dev/null @@ -1,94 +0,0 @@ -# SPDX-FileCopyrightText: 2025 William Bell - -# SPDX-License-Identifier: GPL-3.0-or-later - -"h" -"e" -"ll" -"o" -" " -"wo" -"rl" -"d" -"world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello world" -"hello\u0000world" -"🇬🇧" -"\u0000" -"hello" - -let hello = "helllo\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nbruhhhhh" - -1.24323234e2312324 - -let a, - b = "hello", - c, - d = 42, - temp_result, - compute_area(radius) = 3.1415, - identity(x) = x, - f(x)=do - term.log("hello world") - do - term.log('hello world') - term.log("hello world") - , - g(y, z), - result, - z = 0, - extremely_long_variable_name_to_test_limits, - cache_value = compute_area(5), - placeholder_fn_with_no_body(arg1, arg2, arg3), - total = identity(100), - deeply_nested_args_function(arg1, arg2, arg3, arg4, arg5), - sum = a, - another, - another_function(), - just_null_here, - x - - - - -if (x) do - term.log("hello world") - term.log("hello world") -else term.log("bruh") - - - - - - - -mm=x/2/4/2/4354/534/534//534//3422*404203420234+3432423324&&430234230||4320423040230423^384239423043024923%4432042304920.3432423423 - -let X = [ - 'hello world', - 'wow', - 10 -] - -term.log(x[0:1:1]) - -let y = { - 'hello':test, - world:'nice' -} - -term.log(y['hello'],y.world) \ No newline at end of file diff --git a/test.py b/test.py deleted file mode 100644 index b81251c..0000000 --- a/test.py +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-FileCopyrightText: 2025 William Bell -# -# SPDX-License-Identifier: GPL-3.0-or-later - -import string -from itertools import product -import sys - -def generate_names(max_width, skip_keywords=None): - if skip_keywords is None: - skip_keywords = {"if", "else", "while", "forever", "for", "break", "continue", - "return", "let", "import", "from", "do", "true", "false", "null", - "delete", "not", "try", "catch", "in", "or", "and", "elif"} - else: - skip_keywords = set(skip_keywords) - - chars = string.ascii_lowercase - first = True - write = sys.stdout.write - - for length in range(1, max_width + 1): - print(length, file=sys.stderr) - i = 0 - for p in product(chars, repeat=length): - name = ''.join(p) - if name in skip_keywords: - continue - write('let ') - write(name) - write(' = null\n') - first = False - if i>10000000: - break - i+=1 - -# Example usage: -max_width = 5 -generate_names(max_width) diff --git a/testing.ar b/testing.ar deleted file mode 100644 index 13ab4e8..0000000 --- a/testing.ar +++ /dev/null @@ -1,47 +0,0 @@ -let say_hi(name) = do - let z(y) = do - return y - let u = z( - do - return name - ) - - return "hello "+u+", how are you?" -term.log(say_hi("william") -, say_hi) - -let a = 9 -let b = 10 -term.log(string(a)+'+'+string(b)+'='+string(a+b)) - - -let call(f) = do - term.log(f) - - return f() - - -term.log( - call( - ()=call( - ()=do - term.log('hello testing testing') - return call( - ()=call( - ()=do - term.log("hello this is a test of anonymous functions. hopefully this works :)") - - return say_hi("test") - ) - ) - ) - ) -) -call(()=do - term.log(( - (x)=x - )( - 10000675435574942378423458324823473205237523053278452368578032472390453275238558438905348905894035890348905349805345485843578934268954328902589607469328905490832678934728969834689057843267854736890256743928563256749016078596789416895657435690769013674516750941765438576867893726789543789345678576846715416789058903890549045839804538905389045890435890349580348905894035890435784785236523656237985678342523678 - ) - ) -) \ No newline at end of file diff --git a/tests/iteration-test.ar b/tests/iteration-test.ar new file mode 100644 index 0000000..f858c3e --- /dev/null +++ b/tests/iteration-test.ar @@ -0,0 +1,3 @@ +let i = 1e6 +while (i) do + i = i-1 \ No newline at end of file