add not and or, while also improving performance.

This commit is contained in:
William Bell
2025-09-07 21:03:57 +01:00
parent 57728af0b6
commit 23c4a7ebd1
36 changed files with 201 additions and 458 deletions

View File

@@ -56,6 +56,7 @@ struct string_struct {
};
typedef struct Stack {
uint64_t fake_new_scopes;
struct hashmap_GC *scope;
struct Stack *prev;
} Stack;

View File

@@ -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;

50
src/parser/not/not.c Normal file
View File

@@ -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 <stdio.h>
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);
}

20
src/parser/not/not.h Normal file
View File

@@ -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

View File

@@ -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);

View File

@@ -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"

View File

@@ -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 <gmp.h>
#include <stdbool.h>
@@ -32,10 +33,10 @@
#include <string.h>
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;
}
}

View File

@@ -50,7 +50,8 @@ typedef enum {
AST_DICTIONARY,
AST_FUNCTION,
AST_RETURN,
AST_WHILE
AST_WHILE,
AST_TO_BOOL
} ValueType;
extern const char *ValueTypeNames[];

View File

@@ -9,7 +9,7 @@
#include <stdint.h>
#include "arobject.h"
#define ERR_MSG_MAX_LEN 256
#define ERR_MSG_MAX_LEN 64
typedef struct ArErr {
bool exists;

View File

@@ -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],

View File

@@ -6,7 +6,6 @@
#include "call.h"
#include "../../hash_data/hash_data.h"
#include "../objects/literals/literals.h"
#include "../objects/string/string.h"
#include <inttypes.h>
#include <math.h>
@@ -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,

View File

@@ -15,18 +15,19 @@
#include <string.h>
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);

View File

@@ -7,7 +7,6 @@
#include "number.h"
#include "../functions/functions.h"
#include "../string/string.h"
#include <gmp-x86_64.h>
#include <gmp.h>
#include <inttypes.h>
#include <stdio.h>

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;i<translated.registerCount;i++) {
runtime.registers[i] = ARGON_NULL;
for (size_t i = 0; i < translated.registerCount; i++) {
runtime.registers[i] = NULL;
}
return runtime;
}
Stack *create_scope(Stack *prev) {
Stack *stack = ar_alloc(sizeof(Stack));
stack->scope = 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: {

View File

@@ -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;
}

View File

@@ -9,4 +9,4 @@
int shell();
#endif // ARGON_SHELL_H
#endif // ARGON_SHELL_H

View File

@@ -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 (*)
2. the register C (*)
## OP_NOT
inverts the boolean value in register 0.

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}