add not and or, while also improving performance.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -64,5 +64,6 @@ build
|
||||
*.yy.c
|
||||
*.yy.h
|
||||
|
||||
__isotope__
|
||||
__arcache__
|
||||
argon_modules
|
||||
@@ -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
|
||||
130
debug_arbin.py
130
debug_arbin.py
@@ -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)
|
||||
@@ -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()
|
||||
10
gentest.py
10
gentest.py
@@ -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.old
Normal file
BIN
perf.data.old
Normal file
Binary file not shown.
@@ -56,6 +56,7 @@ struct string_struct {
|
||||
};
|
||||
|
||||
typedef struct Stack {
|
||||
uint64_t fake_new_scopes;
|
||||
struct hashmap_GC *scope;
|
||||
struct Stack *prev;
|
||||
} Stack;
|
||||
|
||||
@@ -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
50
src/parser/not/not.c
Normal 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
20
src/parser/not/not.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,8 @@ typedef enum {
|
||||
AST_DICTIONARY,
|
||||
AST_FUNCTION,
|
||||
AST_RETURN,
|
||||
AST_WHILE
|
||||
AST_WHILE,
|
||||
AST_TO_BOOL
|
||||
} ValueType;
|
||||
|
||||
extern const char *ValueTypeNames[];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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: {
|
||||
|
||||
16
src/shell.c
16
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -182,3 +180,7 @@ 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 (*)
|
||||
|
||||
## OP_NOT
|
||||
|
||||
inverts the boolean value in register 0.
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
94
test.ar
@@ -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
38
test.py
@@ -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)
|
||||
47
testing.ar
47
testing.ar
@@ -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
3
tests/iteration-test.ar
Normal file
@@ -0,0 +1,3 @@
|
||||
let i = 1e6
|
||||
while (i) do
|
||||
i = i-1
|
||||
Reference in New Issue
Block a user