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

1
.gitignore vendored
View File

@@ -64,5 +64,6 @@ build
*.yy.c
*.yy.h
__isotope__
__arcache__
argon_modules

View File

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

3
app.py
View File

@@ -1,3 +0,0 @@
i = 1_000_000
while i:
i=i-1

View File

@@ -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("<Q", f.read(8))
# Read regCount, constantsSize, bytecodeSize (all uint64_t, little-endian)
reg_count, = struct.unpack("<Q", f.read(8))
constants_size, = struct.unpack("<Q", f.read(8))
bytecode_size, = struct.unpack("<Q", f.read(8))
# Read constants buffer (raw bytes)
constants = f.read(constants_size)
# Read bytecode array (uint64_t, little-endian)
bytecode = []
for _ in range(bytecode_size):
instr, = struct.unpack("<Q", f.read(8))
bytecode.append(instr)
return {
"version": version_number,
"register_count": reg_count,
"constants_size": constants_size,
"bytecode_size": bytecode_size,
"constants": constants,
"bytecode": bytecode,
}
class print_opcode:
def start(registers,data, i):
print()
match data['bytecode'][i]:
case OperationType.OP_LOAD_CONST.value:
return print_opcode.OP_LOAD_CONST(registers,data, i)
case OperationType.OP_DECLARE.value:
return print_opcode.OP_DECLARE(registers,data, i)
case OperationType.OP_LOAD_NULL.value:
return print_opcode.OP_LOAD_NULL(registers,data, i)
def OP_LOAD_CONST(registers,data, i) -> 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<len(data["bytecode"]):
i=print_opcode.start(registers,data,i)

View File

@@ -1,56 +0,0 @@
# SPDX-FileCopyrightText: 2025 William Bell
# SPDX-License-Identifier: GPL-3.0-or-later
let __makeFile(name, type, data) = do
let File = {name: name, type: type, data: data}
let save(path) = do
let file = file.write(path)
file.buffer(data)
file.close()
File.save = save
return File
let __multipart(req, res) = do
let boundary = buffer().from(req.headers["content-type"].splitN("boundary=", 2)[1])
let newLineSplit = buffer().from("\r\n\r\n")
let parts = req.buffer.body.split(boundary)
for (i from 0 to parts.length) do
let str = parts[i].to("string")
if (str == "" || str=="--" || str=="--\r\n") continue
str = null
let headers = {}
let lines = parts[i].splitN(newLineSplit, 2)
let headerLines = lines[0].to("string").split("\r\n")
for (j from 0 to headerLines.length) do
let header = headerLines[j].splitN(": ", 2)
if (header.length != 2) continue
headers[header[0].lower()] = header[1]
if (lines.length != 2) continue
let body = lines[1]
if (i != parts.length-1) do
body = body.slice(0, body.length-4)
if ("content-disposition" in headers) do
let disposition = headers["content-disposition"].split("; ")
if (disposition[0] == "form-data") do
let name = json.parse(disposition[1].splitN("=", 2)[1])
if (disposition.length >= 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()

View File

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

BIN
perf.data Normal file

Binary file not shown.

BIN
perf.data.old Normal file

Binary file not shown.

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

94
test.ar
View File

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

38
test.py
View File

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

View File

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

3
tests/iteration-test.ar Normal file
View File

@@ -0,0 +1,3 @@
let i = 1e6
while (i) do
i = i-1