Compare commits

...

14 Commits

52 changed files with 1263 additions and 280 deletions

2
.gitignore vendored
View File

@@ -61,3 +61,5 @@ build
*.yy.h *.yy.h
out.arbin out.arbin
rand_test.ar
__arcache__

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "external/xxhash"]
path = external/xxhash
url = https://github.com/Cyan4973/xxHash.git

View File

@@ -1,3 +1,7 @@
This project is licensed under the GNU General Public License version 3 (GPLv3), except for
some files (e.g., in the `src/hash_data/siphash/` directory) which are licensed under CC0 1.0 Universal.
See the LICENSE-CC0 file in the respective directories for details.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007

View File

@@ -2,7 +2,7 @@ LEXER_SRC = src/lexer/lex.l
LEXER_C = src/lexer/lex.yy.c LEXER_C = src/lexer/lex.yy.c
LEXER_H = src/lexer/lex.yy.h LEXER_H = src/lexer/lex.yy.h
CFILES = $(shell find src -name '*.c') CFILES = external/xxhash/xxhash.c $(shell find src -name '*.c')
CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function CFLAGS = $(ARCHFLAGS) -lm -lgc -lgmp -Wall -Wextra -Wno-unused-function
BINARY = bin/argon BINARY = bin/argon
@@ -26,7 +26,7 @@ full-debug: $(CFILES) $(LEXER_C) $(LEXER_H)
optimised: $(CFILES) $(LEXER_C) $(LEXER_H) optimised: $(CFILES) $(LEXER_C) $(LEXER_H)
mkdir -p bin mkdir -p bin
gcc -O3 -fprofile-generate -o $(BINARY) $(CFILES) $(CFLAGS) gcc -O3 -fprofile-generate -o $(BINARY) $(CFILES) $(CFLAGS)
${BINARY} test.ar ${BINARY} rand_test.ar
gcc -O3 -fprofile-use -o $(BINARY) $(CFILES) $(CFLAGS) gcc -O3 -fprofile-use -o $(BINARY) $(CFILES) $(CFLAGS)

1
external/xxhash vendored Submodule

Submodule external/xxhash added at 38d555879f

7
gentest.py Normal file
View File

@@ -0,0 +1,7 @@
import random
myfile = open("rand_test.ar","w")
for i in range(10000000):
myfile.write("\"")
myfile.write(str(random.random())[2::])
myfile.write("\"\n")

View File

@@ -1,2 +0,0 @@
null
"hello\u0000world"

View File

@@ -4,7 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#define CHUNK_SIZE 1024 #define CHUNK_SIZE 1048576
typedef struct { typedef struct {
void *data; void *data;

28
src/hash_data/hash_data.c Normal file
View File

@@ -0,0 +1,28 @@
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include "siphash/siphash.h"
#include "hash_data.h"
uint8_t siphash_key[16];
uint8_t empty_siphash_key[16];
void generate_siphash_key(uint8_t hash_key[16]) {
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0 || read(fd, hash_key, 16) != 16) {
// Fallback or abort
}
close(fd);
}
uint64_t siphash64_bytes(const void *data, size_t len,uint8_t hash_key[16]) {
uint8_t out[8];
if (siphash(data, len, hash_key, out, sizeof(out)) != 0)
return 0;
uint64_t hash = 0;
for (int i = 0; i < 8; ++i)
hash |= ((uint64_t)out[i]) << (8 * i);
return hash;
}

11
src/hash_data/hash_data.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef HASH_DATA_H
#define HASH_DATA_H
#include <stdlib.h>
#include <stdint.h>
extern uint8_t siphash_key[16];
extern uint8_t empty_siphash_key[16];
void generate_siphash_key(uint8_t siphash_key[16]);
uint64_t siphash64_bytes(const void *data, size_t len,uint8_t siphash_key[16]);
#endif //HASH_DATA_H

View File

@@ -0,0 +1,122 @@
This license applies **only** to the files that explicitly state at the top of the file that they are under CC0 1.0 Universal.
All other files in this project are licensed under the GNU General Public License version 3 (GPLv3) unless otherwise stated.
Please refer to the LICENSE file in the root directory for the main project license.
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

View File

@@ -1,18 +1,22 @@
/* /*
SipHash reference C implementation * This file is dedicated to the public domain under CC0 1.0 Universal.
* See the LICENSE-CC0 file in this directory for details.
Copyright (c) 2012-2022 Jean-Philippe Aumasson *
<jeanphilippe.aumasson@gmail.com> * SipHash reference C implementation
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to> *
* Copyright (c) 2012-2022 Jean-Philippe Aumasson
To the extent possible under law, the author(s) have dedicated all copyright * <jeanphilippe.aumasson@gmail.com>
and related and neighboring rights to this software to the public domain * Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
worldwide. This software is distributed without any warranty. *
* To the extent possible under law, the author(s) have dedicated all copyright
You should have received a copy of the CC0 Public Domain Dedication along * and related and neighboring rights to this software to the public domain
with * worldwide. This software is distributed without any warranty.
this software. If not, see *
<http://creativecommons.org/publicdomain/zero/1.0/>. * You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*
* SPDX-License-Identifier: CC0-1.0
*/ */
#include "siphash.h" #include "siphash.h"

View File

@@ -0,0 +1,26 @@
/*
* This file is dedicated to the public domain under CC0 1.0 Universal.
* See the LICENSE-CC0 file in this directory for details.
*
* SipHash reference C implementation
*
* Copyright (c) 2012-2022 Jean-Philippe Aumasson
* <jeanphilippe.aumasson@gmail.com>
* Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <inttypes.h>
#include <string.h>
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen);

133
src/hashmap/hashmap.c Normal file
View File

@@ -0,0 +1,133 @@
#include "hashmap.h"
#include "../memory.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
struct hashmap *createHashmap() {
size_t size = 8;
struct hashmap *t = (struct hashmap *)checked_malloc(sizeof(struct hashmap));
t->size = size;
t->order = 1;
t->list = (struct node **)checked_malloc(sizeof(struct node *) * size);
memset(t->list, 0, sizeof(struct node *) * size);
return t;
}
void hashmap_free(struct hashmap *t, free_val_func free_val) {
if (!t) return;
for (size_t i = 0; i < t->size; i++) {
struct node *current = t->list[i];
while (current) {
struct node *next = current->next;
if (free_val && current->val) {
free_val(current->val);
}
free(current);
current = next;
}
}
free(t->list);
free(t);
}
void resize_hashmap(struct hashmap *t) {
int old_size = t->size;
int new_size = old_size * 2;
struct node **old_list = t->list;
// Create new list
t->list = (struct node **)checked_malloc(sizeof(struct node *) * new_size);
memset(t->list, 0, sizeof(struct node *) * new_size);
t->size = new_size;
t->count = 0;
// Rehash old entries into new list
for (int i = 0; i < old_size; i++) {
struct node *temp = old_list[i];
while (temp) {
hashmap_insert(t, temp->hash, temp->key, temp->val,
temp->order); // Will increment count
temp = temp->next;
}
}
free(old_list);
}
int hashCode(struct hashmap *t, uint64_t hash) { return hash % t->size; }
int hashmap_remove(struct hashmap *t, uint64_t hash) {
int pos = hashCode(t, hash);
struct node *list = t->list[pos];
struct node *temp = list;
struct node *prev = NULL;
while (temp) {
if (temp->hash == hash) {
if (prev)
prev->next = temp->next;
else
t->list[pos] = temp->next;
return 1;
}
prev = temp;
temp = temp->next;
}
list = NULL;
prev = NULL;
temp = NULL;
return 0;
}
void hashmap_insert(struct hashmap *t, uint64_t hash, void *key,
void *val, size_t order) {
if (!order) {
order = t->order++;
}
if ((t->count + 1) > t->size * 0.75) {
resize_hashmap(t);
}
int pos = hashCode(t, hash);
struct node *list = t->list[pos];
struct node *temp = list;
// Check if key exists → overwrite
while (temp) {
if (temp->hash == hash) {
temp->val = val;
return;
}
temp = temp->next;
}
// Insert new node
struct node *newNode = (struct node *)checked_malloc(sizeof(struct node));
newNode->hash = hash;
newNode->key = key;
newNode->val = val;
newNode->order = order;
newNode->next = list;
t->list[pos] = newNode;
t->count++;
}
void *hashmap_lookup(struct hashmap *t, uint64_t hash) {
int pos = hashCode(t, hash);
struct node *list = t->list[pos];
struct node *temp = list;
while (temp) {
if (temp->hash == hash) {
return temp->val;
}
temp = temp->next;
}
return NULL;
}

37
src/hashmap/hashmap.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef HASHMAP_H
#define HASHMAP_H
#include <stdint.h>
#include <stdlib.h>
typedef struct ArgonObject ArgonObject;
typedef void (*free_val_func)(void *val);
struct node {
uint64_t hash;
void *key;
void *val;
size_t order;
struct node *next;
};
struct hashmap {
size_t size;
size_t count;
size_t order;
struct node **list;
};
struct hashmap *createHashmap();
void hashmap_free(struct hashmap *t, free_val_func free_val);
int hashCode(struct hashmap *t, uint64_t hash);
int hashmap_remove(struct hashmap *t, uint64_t hash);
void hashmap_insert(struct hashmap *t, uint64_t hash, void *key,
void *val, size_t order);
void *hashmap_lookup(struct hashmap *t, uint64_t hash);
#endif // HASHMAP_H

View File

@@ -3,83 +3,345 @@
#include "lexer/token.h" #include "lexer/token.h"
#include "memory.h" #include "memory.h"
#include "parser/parser.h" #include "parser/parser.h"
#include "translator/translator.h"
#include "runtime/runtime.h" #include "runtime/runtime.h"
#include "translator/translator.h"
#include "../external/xxhash/xxhash.h"
#include "hash_data/hash_data.h"
#include <arpa/inet.h>
#include <endian.h> #include <endian.h>
#include <string.h>
#include <locale.h> #include <locale.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#ifdef _WIN32
#include <direct.h>
#define mkdir(path, mode) _mkdir(path)
#else
#include <sys/stat.h>
#include <sys/types.h>
#endif
#include <string.h>
const char FILE_IDENTIFIER[] = "ARBI"; int ensure_dir_exists(const char *path) {
const uint64_t version_number = 0; struct stat st = {0};
if (stat(path, &st) == -1) {
// Directory does not exist, create it
if (mkdir(path, 0755) != 0) {
perror("mkdir failed");
return -1;
}
}
return 0;
}
char *normalize_path(char *path) {
#ifdef _WIN32
for (char *p = path; *p; p++) {
if (*p == '/') {
*p = '\\';
}
}
#endif
return path;
}
// Join two paths using '/' as separator, no platform checks here.
int path_join(char *dest, size_t dest_size, const char *path1,
const char *path2) {
size_t len1 = strlen(path1);
size_t len2 = strlen(path2);
// Check if buffer is large enough (extra 2 for '/' and '\0')
if (len1 + len2 + 2 > dest_size)
return -1;
strcpy(dest, path1);
// Add '/' if needed
if (len1 > 0 && dest[len1 - 1] != '/') {
dest[len1] = '/';
dest[len1 + 1] = '\0';
len1++;
}
// Skip leading '/' in path2 to avoid double separator
if (len2 > 0 && path2[0] == '/') {
path2++;
len2--;
}
strcat(dest, path2);
return 0;
}
const char CACHE_FOLDER[] = "__arcache__";
const char FILE_IDENTIFIER[5] = "ARBI";
const char BYTECODE_EXTENTION[] = "arbin";
const uint32_t version_number = 0;
#ifdef _WIN32
#define PATH_SEP '\\'
#else
#define PATH_SEP '/'
#endif
char *replace_extension(const char *path, const char *new_ext) {
// Defensive: if new_ext doesn't start with '.', add it
int need_dot = (new_ext[0] != '.');
// Find last path separator to avoid changing dots in folder names
const char *last_sep = strrchr(path, PATH_SEP);
#ifdef _WIN32
// Windows can have '/' too as separator in practice, check it
const char *last_alt_sep = strrchr(path, '/');
if (last_alt_sep && (!last_sep || last_alt_sep > last_sep)) {
last_sep = last_alt_sep;
}
#endif
// Find last '.' after last_sep (if any)
const char *last_dot = strrchr(path, '.');
if (last_dot && (!last_sep || last_dot > last_sep)) {
// Extension found: copy path up to last_dot, then append new_ext
size_t base_len = last_dot - path;
size_t ext_len = strlen(new_ext) + (need_dot ? 1 : 0);
size_t new_len = base_len + ext_len + 1;
char *result = malloc(new_len);
if (!result)
return NULL;
memcpy(result, path, base_len);
if (need_dot)
result[base_len] = '.';
strcpy(result + base_len + (need_dot ? 1 : 0), new_ext);
return result;
} else {
// No extension found: append '.' + new_ext (if needed)
size_t path_len = strlen(path);
size_t ext_len = strlen(new_ext) + (need_dot ? 1 : 0);
size_t new_len = path_len + ext_len + 1;
char *result = malloc(new_len);
if (!result)
return NULL;
strcpy(result, path);
if (need_dot)
strcat(result, ".");
strcat(result, new_ext);
return result;
}
}
int load_cache(Translated *translated_dest, char *joined_paths, uint64_t hash) {
FILE *bytecode_file = fopen(joined_paths, "rb");
if (!bytecode_file)
return 1;
char file_identifier_from_cache[sizeof(FILE_IDENTIFIER)];
file_identifier_from_cache[strlen(FILE_IDENTIFIER)] = '\0';
if (fread(&file_identifier_from_cache, 1,
sizeof(file_identifier_from_cache) - 1,
bytecode_file) != sizeof(file_identifier_from_cache) - 1 ||
memcmp(file_identifier_from_cache, FILE_IDENTIFIER,
sizeof(file_identifier_from_cache)) != 0) {
fclose(bytecode_file);
return 1;
}
uint32_t read_version;
if (fread(&read_version, 1, sizeof(read_version), bytecode_file) !=
sizeof(read_version)) {
goto FAILED;
}
read_version = le32toh(read_version);
if (read_version != version_number) {
goto FAILED;
}
uint64_t read_hash;
if (fread(&read_hash, 1, sizeof(read_hash), bytecode_file) !=
sizeof(read_hash)) {
goto FAILED;
}
read_hash = le64toh(read_hash);
if (read_hash != hash) {
goto FAILED;
}
uint8_t register_count;
if (fread(&register_count, 1, sizeof(register_count), bytecode_file) !=
sizeof(register_count)) {
goto FAILED;
}
uint64_t constantsSize;
if (fread(&constantsSize, 1, sizeof(constantsSize), bytecode_file) !=
sizeof(constantsSize)) {
goto FAILED;
}
constantsSize = le64toh(constantsSize);
uint64_t bytecodeSize;
if (fread(&bytecodeSize, 1, sizeof(bytecodeSize), bytecode_file) !=
sizeof(bytecodeSize)) {
goto FAILED;
}
bytecodeSize = le64toh(bytecodeSize);
arena_resize(&translated_dest->constants, constantsSize);
if (fread(translated_dest->constants.data, 1, constantsSize, bytecode_file) !=
constantsSize) {
goto FAILED;
}
darray_resize(&translated_dest->bytecode, bytecodeSize);
if (fread(translated_dest->bytecode.data, 1, bytecodeSize, bytecode_file) !=
bytecodeSize) {
goto FAILED;
}
translated_dest->registerCount = register_count;
fclose(bytecode_file);
return 0;
FAILED:
fclose(bytecode_file);
return 1;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
generate_siphash_key(siphash_key);
clock_t start, end;
double time_spent, total_time_spent = 0;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
if (argc <= 1) if (argc <= 1)
return -1; return -1;
ar_memory_init(); ar_memory_init();
char *path = argv[1]; char *path = argv[1];
DArray tokens;
darray_init(&tokens, sizeof(Token));
FILE *file = fopen(path, "r"); FILE *file = fopen(path, "r");
if (!file) { if (!file) {
return -1; return -1;
} }
LexerState state = {path, file, 0, 0, &tokens}; XXH3_state_t *hash_state = XXH3_createState();
lexer(state); XXH3_64bits_reset(hash_state);
fclose(state.file);
DArray ast; char buffer[8192];
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0) {
XXH3_64bits_update(hash_state, buffer, bytes);
}
rewind(file);
uint64_t hash = XXH3_64bits_digest(hash_state);
XXH3_freeState(hash_state);
darray_init(&ast, sizeof(ParsedValue)); char *filename_without_extention =
replace_extension(path, BYTECODE_EXTENTION);
parser(path, &ast, &tokens, false); size_t joined_paths_length =
darray_free(&tokens, free_token); strlen(CACHE_FOLDER) + strlen(filename_without_extention) + 2;
char *joined_paths = checked_malloc(joined_paths_length);
path_join(joined_paths, joined_paths_length, CACHE_FOLDER,
filename_without_extention);
free(filename_without_extention);
filename_without_extention = NULL;
Translated translated = init_translator(); Translated translated = init_translator();
translate(&translated, &ast); if (load_cache(&translated, joined_paths, hash) != 0) {
free_translator(&translated);
translated = init_translator();
darray_free(&ast, free_parsed); DArray tokens;
darray_init(&tokens, sizeof(Token));
file = fopen("out.arbin", "wb"); LexerState state = {path, file, 0, 0, &tokens};
start = clock();
lexer(state);
end = clock();
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
total_time_spent += time_spent;
printf("Lexer time taken: %f seconds\n", time_spent);
fclose(state.file);
uint64_t regCount = (uint64_t)translated.registerCount; DArray ast;
uint64_t constantsSize = (uint64_t)translated.constants.size;
uint64_t bytecodeSize = (uint64_t)translated.bytecode.size;
uint64_t version_number_htole64ed = htole64(version_number); darray_init(&ast, sizeof(ParsedValue));
regCount = htole64(regCount);
regCount = htole64(regCount);
constantsSize = htole64(constantsSize);
bytecodeSize = htole64(bytecodeSize);
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file); start = clock();
fwrite(&version_number_htole64ed, sizeof(uint64_t), 1, file); parser(path, &ast, &tokens, false);
fwrite(&regCount, sizeof(uint64_t), 1, file); end = clock();
fwrite(&constantsSize, sizeof(uint64_t), 1, file); time_spent = (double)(end - start) / CLOCKS_PER_SEC;
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file); total_time_spent += time_spent;
fwrite(translated.constants.data, 1, translated.constants.size, file); printf("Parser time taken: %f seconds\n", time_spent);
fwrite(translated.bytecode.data, translated.bytecode.element_size, darray_free(&tokens, free_token);
translated.bytecode.size, file);
fclose(file); start = clock();
translate(&translated, &ast);
end = clock();
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
total_time_spent += time_spent;
printf("Translation time taken: %f seconds\n", time_spent);
generate_siphash_key(); darray_free(&ast, free_parsed);
ensure_dir_exists(CACHE_FOLDER);
file = fopen(joined_paths, "wb");
uint64_t constantsSize = (uint64_t)translated.constants.size;
uint64_t bytecodeSize = (uint64_t)translated.bytecode.size;
uint32_t version_number_htole32ed = htole32(version_number);
uint64_t net_hash = htole64(hash);
constantsSize = htole64(constantsSize);
bytecodeSize = htole64(bytecodeSize);
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file);
fwrite(&version_number_htole32ed, sizeof(uint32_t), 1, file);
fwrite(&net_hash, sizeof(net_hash), 1, file);
fwrite(&translated.registerCount, sizeof(uint8_t), 1, file);
fwrite(&constantsSize, sizeof(uint64_t), 1, file);
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file);
fwrite(translated.constants.data, 1, translated.constants.size, file);
fwrite(translated.bytecode.data, translated.bytecode.element_size,
translated.bytecode.size, file);
fclose(file);
}
init_types(); init_types();
start = clock();
runtime(translated); runtime(translated);
end = clock();
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
total_time_spent += time_spent;
printf("Execution time taken: %f seconds\n", time_spent);
printf("total time taken: %f seconds\n", total_time_spent);
free_translator(&translated); free_translator(&translated);
free(joined_paths);
return 0; return 0;
} }

View File

@@ -1,13 +1,9 @@
#include "memory.h" #include "memory.h"
#include <gc.h>
#include <gc/gc.h> #include <gc/gc.h>
#include <gmp.h> #include <gmp.h>
#include <stdio.h>
#include <stdlib.h> // for malloc/free (temp arena fallback) #include <stdlib.h> // for malloc/free (temp arena fallback)
#include <string.h> #include <string.h>
#include <stdio.h>
// runtime
#include "runtime/objects/type/type.h"
void *checked_malloc(size_t size) { void *checked_malloc(size_t size) {
void *ptr = malloc(size); void *ptr = malloc(size);
@@ -19,15 +15,14 @@ void *checked_malloc(size_t size) {
} }
void *gmp_gc_realloc(void *ptr, size_t old_size, size_t new_size) { void *gmp_gc_realloc(void *ptr, size_t old_size, size_t new_size) {
(void)old_size; // Ignore old_size, Boehm doesn't need it (void)old_size; // Ignore old_size, Boehm doesn't need it
return GC_realloc(ptr, new_size); return GC_realloc(ptr, new_size);
} }
void gmp_gc_free(void *ptr, size_t size) { void gmp_gc_free(void *ptr, size_t size) {
(void)size; // Boehm GC manages this itself (void)size; // Boehm GC manages this itself
// No-op — memory will be collected automatically // No-op — memory will be collected automatically
GC_FREE(ptr); GC_FREE(ptr);
} }
void ar_memory_init() { void ar_memory_init() {
@@ -35,9 +30,13 @@ void ar_memory_init() {
mp_set_memory_functions(GC_malloc, gmp_gc_realloc, gmp_gc_free); mp_set_memory_functions(GC_malloc, gmp_gc_realloc, gmp_gc_free);
} }
void *ar_alloc(size_t size) { return GC_MALLOC(size); } void *ar_alloc(size_t size) { return GC_MALLOC(size); }
void ar_finalizer(void *obj, GC_finalization_proc fn, void *client_data,
GC_finalization_proc *old_fn, void **old_client_data) {
return GC_register_finalizer_no_order(obj, fn, client_data, old_fn, old_client_data);
}
void *ar_alloc_atomic(size_t size) { return GC_MALLOC_ATOMIC(size); } void *ar_alloc_atomic(size_t size) { return GC_MALLOC_ATOMIC(size); }
char *ar_strdup(const char *str) { char *ar_strdup(const char *str) {

View File

@@ -2,8 +2,12 @@
#define ARGON_MEMORY_H #define ARGON_MEMORY_H
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <gc/gc.h>
// GC-managed allocations // GC-managed allocations
void ar_finalizer(void *obj, GC_finalization_proc fn, void *client_data,
GC_finalization_proc *old_fn, void **old_client_data);
void *ar_alloc(size_t size); void *ar_alloc(size_t size);
void *ar_alloc_atomic(size_t size); void *ar_alloc_atomic(size_t size);
char *ar_strdup(const char *str); char *ar_strdup(const char *str);

View File

@@ -49,5 +49,6 @@ void free_parse_call(void *ptr) {
darray_free(&parsedCall->args, free_parsed); darray_free(&parsedCall->args, free_parsed);
free_parsed(parsedCall->to_call); free_parsed(parsedCall->to_call);
free(parsedCall->to_call);
free(parsedCall); free(parsedCall);
} }

View File

@@ -1,6 +1,7 @@
#include "declaration.h" #include "declaration.h"
#include "../../lexer/token.h" #include "../../lexer/token.h"
#include "../../memory.h" #include "../../memory.h"
#include "../function/function.h"
#include "../literals/literals.h" #include "../literals/literals.h"
#include "../parser.h" #include "../parser.h"
#include <stdio.h> #include <stdio.h>
@@ -22,7 +23,8 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
darray_push(declarations, &_declaration); darray_push(declarations, &_declaration);
ParsedSingleDeclaration *declaration = ParsedSingleDeclaration *declaration =
darray_get(declarations, declarations->size - 1); darray_get(declarations, declarations->size - 1);
declaration->is_function = false; bool isFunction=false;
DArray parameters;
declaration->from = parse_null(); declaration->from = parse_null();
if (token->type != TOKEN_IDENTIFIER) { if (token->type != TOKEN_IDENTIFIER) {
@@ -38,8 +40,8 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
return parsedValue; return parsedValue;
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
if (token->type == TOKEN_LPAREN) { if (token->type == TOKEN_LPAREN) {
declaration->is_function = true; isFunction = true;
darray_init(&declaration->parameters, sizeof(char *)); darray_init(&parameters, sizeof(char *));
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
token = darray_get(tokens, *index); token = darray_get(tokens, *index);
@@ -61,9 +63,9 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
file, token->line, token->column); file, token->line, token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
char *parameter_name = char *parameter_name = checked_malloc(strlen(token->value) + 1);
strcpy(checked_malloc(strlen(token->value) + 1), token->value); strcpy(parameter_name, token->value);
darray_push(&declaration->parameters, &parameter_name); darray_push(&parameters, &parameter_name);
(*index)++; (*index)++;
error_if_finished(file, tokens, index); error_if_finished(file, tokens, index);
skip_newlines_and_indents(tokens, index); skip_newlines_and_indents(tokens, index);
@@ -97,10 +99,15 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) {
token->column); token->column);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if ((*index) >= tokens->size)
break;
token = darray_get(tokens, *index);
} }
if (isFunction) {
declaration->from = create_parsed_function(declaration->name, parameters,
declaration->from);
}
if ((*index) >= tokens->size)
break;
token = darray_get(tokens, *index);
size_t count = skip_newlines_and_indents(tokens, index); size_t count = skip_newlines_and_indents(tokens, index);
if ((*index) >= tokens->size) if ((*index) >= tokens->size)
break; break;
@@ -127,8 +134,6 @@ void free_string(void *ptr) {
void free_single_declaration(void *ptr) { void free_single_declaration(void *ptr) {
ParsedSingleDeclaration *declaration = ptr; ParsedSingleDeclaration *declaration = ptr;
free(declaration->name); free(declaration->name);
if (declaration->is_function)
darray_free(&declaration->parameters, free_string);
free_parsed(declaration->from); free_parsed(declaration->from);
free(declaration->from); free(declaration->from);
} }

View File

@@ -5,8 +5,6 @@
typedef struct { typedef struct {
char * name; char * name;
bool is_function;
DArray parameters; // string[]
ParsedValue * from; ParsedValue * from;
} ParsedSingleDeclaration; } ParsedSingleDeclaration;

View File

@@ -88,5 +88,5 @@ void free_parsed_dictionary(void *ptr) {
ParsedValue *parsedValue = ptr; ParsedValue *parsedValue = ptr;
DArray *parsed_dictionary = parsedValue->data; DArray *parsed_dictionary = parsedValue->data;
darray_free(parsed_dictionary, free_dictionary_entry); darray_free(parsed_dictionary, free_dictionary_entry);
free(parsedValue->data); free(parsed_dictionary);
} }

View File

@@ -0,0 +1,32 @@
#include "function.h"
#include "../../memory.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ParsedValue *create_parsed_function(char *name, DArray parameters,
ParsedValue *body) {
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
parsedValue->type=AST_FUNCTION;
ParsedFunction *parsedFunction = checked_malloc(sizeof(ParsedFunction));
parsedValue->data=parsedFunction;
parsedFunction->name=strcpy(checked_malloc(strlen(name) + 1), name);
parsedFunction->body = body;
parsedFunction->parameters=parameters;
return parsedValue;
}
void free_parameter(void *ptr) {
char** data = ptr;
free(*data);
}
void free_function(void *ptr) {
ParsedValue *parsedValue = ptr;
ParsedFunction *parsed = parsedValue->data;
free_parsed(parsed->body);
free(parsed->body);
free(parsed->name);
darray_free(&parsed->parameters, free_parameter);
free(parsed);
}

View File

@@ -0,0 +1,17 @@
#ifndef FUNCTION_H
#define FUNCTION_H
#include "../../lexer/token.h" // for Token
#include "../parser.h"
typedef struct {
char * name;
DArray parameters;
ParsedValue *body;
} ParsedFunction;
ParsedValue *create_parsed_function(char *name, DArray parameters,
ParsedValue *body);
void free_function(void *ptr);
#endif // FUNCTION_H

View File

@@ -115,5 +115,5 @@ void free_parsed_if(void *ptr) {
ParsedValue *parsedValue = ptr; ParsedValue *parsedValue = ptr;
DArray *parsed_if = parsedValue->data; DArray *parsed_if = parsedValue->data;
darray_free(parsed_if, free_conditional); darray_free(parsed_if, free_conditional);
free(parsedValue->data); free(parsed_if);
} }

View File

@@ -45,5 +45,5 @@ void free_parsed_list(void *ptr) {
ParsedValue *parsedValue = ptr; ParsedValue *parsedValue = ptr;
DArray *parsed_list = parsedValue->data; DArray *parsed_list = parsedValue->data;
darray_free(parsed_list, free_parsed); darray_free(parsed_list, free_parsed);
free(parsedValue->data); free(parsed_list);
} }

View File

@@ -6,9 +6,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
ParsedValue *convert_to_operation(DArray *to_operate_on, DArray *operations) { ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) {
if (to_operate_on->size == 1) { if (to_operate_on->size == 1) {
return darray_get(to_operate_on, 0); return *((ParsedValue*)darray_get(to_operate_on, 0));
} }
TokenType operation = 0; TokenType operation = 0;
DArray positions; DArray positions;
@@ -23,10 +23,10 @@ ParsedValue *convert_to_operation(DArray *to_operate_on, DArray *operations) {
} }
darray_push(&positions, &i); darray_push(&positions, &i);
} }
ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); ParsedValue parsedValue;
parsedValue->type = AST_OPERATION; parsedValue.type = AST_OPERATION;
ParsedOperation *operationStruct = checked_malloc(sizeof(ParsedOperation)); ParsedOperation *operationStruct = checked_malloc(sizeof(ParsedOperation));
parsedValue->data = operationStruct; parsedValue.data = operationStruct;
operationStruct->operation = operation; operationStruct->operation = operation;
darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue)); darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue));
size_t last_position = 0; size_t last_position = 0;
@@ -37,16 +37,18 @@ ParsedValue *convert_to_operation(DArray *to_operate_on, DArray *operations) {
to_operate_on, to_operate_on_last_position, (*position) + 1); to_operate_on, to_operate_on_last_position, (*position) + 1);
DArray operations_slice = DArray operations_slice =
darray_slice(operations, last_position, *position); darray_slice(operations, last_position, *position);
ParsedValue result = convert_to_operation(&to_operate_on_slice, &operations_slice);
darray_push(&operationStruct->to_operate_on, darray_push(&operationStruct->to_operate_on,
convert_to_operation(&to_operate_on_slice, &operations_slice)); &result);
last_position = (*position); last_position = (*position);
to_operate_on_last_position = (*position) + 1; to_operate_on_last_position = (*position) + 1;
} }
DArray to_operate_on_slice = DArray to_operate_on_slice =
darray_slice(to_operate_on, to_operate_on_last_position, to_operate_on->size); 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 operations_slice = darray_slice(operations, last_position, operations->size);
ParsedValue result =convert_to_operation(&to_operate_on_slice, &operations_slice);
darray_push(&operationStruct->to_operate_on, darray_push(&operationStruct->to_operate_on,
convert_to_operation(&to_operate_on_slice, &operations_slice)); &result);
darray_free(&positions, NULL); darray_free(&positions, NULL);
return parsedValue; return parsedValue;
} }
@@ -80,10 +82,12 @@ ParsedValue *parse_operations(char *file, DArray *tokens, size_t *index,
darray_push(&to_operate_on, parsedValue); darray_push(&to_operate_on, parsedValue);
free(parsedValue); free(parsedValue);
} }
ParsedValue *output = convert_to_operation(&to_operate_on, &operations); ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue));
ParsedValue output = convert_to_operation(&to_operate_on, &operations);
memcpy(parsedValue, &output,sizeof(ParsedValue));
darray_free(&to_operate_on, NULL); darray_free(&to_operate_on, NULL);
darray_free(&operations, NULL); darray_free(&operations, NULL);
return output; return parsedValue;
} }
void free_operation(void *ptr) { void free_operation(void *ptr) {

View File

@@ -8,6 +8,7 @@
#include "declaration/declaration.h" #include "declaration/declaration.h"
#include "dictionary/dictionary.h" #include "dictionary/dictionary.h"
#include "dowrap/dowrap.h" #include "dowrap/dowrap.h"
#include "function/function.h"
#include "if/if.h" #include "if/if.h"
#include "list/list.h" #include "list/list.h"
#include "literals/literals.h" #include "literals/literals.h"
@@ -22,9 +23,9 @@
#include <string.h> #include <string.h>
const char *ValueTypeNames[] = { const char *ValueTypeNames[] = {
"string", "assign", "identifier", "number", "if statement", "string", "assign", "identifier", "number", "if statement",
"access", "call", "declaration", "null", "boolean", "access", "call", "declaration", "null", "boolean",
"do wrap", "operations", "list", "dictionary"}; "do wrap", "operations", "list", "dictionary", "function"};
void error_if_finished(char *file, DArray *tokens, size_t *index) { void error_if_finished(char *file, DArray *tokens, size_t *index) {
if ((*index) >= tokens->size) { if ((*index) >= tokens->size) {
@@ -232,5 +233,7 @@ void free_parsed(void *ptr) {
case AST_DICTIONARY: case AST_DICTIONARY:
free_parsed_dictionary(parsed); free_parsed_dictionary(parsed);
break; break;
case AST_FUNCTION:
free_function(parsed);
} }
} }

View File

@@ -39,7 +39,8 @@ typedef enum {
AST_DOWRAP, AST_DOWRAP,
AST_OPERATION, AST_OPERATION,
AST_LIST, AST_LIST,
AST_DICTIONARY AST_DICTIONARY,
AST_FUNCTION
} ValueType; } ValueType;
extern const char* ValueTypeNames[]; extern const char* ValueTypeNames[];

View File

@@ -0,0 +1,113 @@
#include "darray_armem.h"
#include "../../../memory.h"
#include <gc/gc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void darray_armem_init(darray_armem *arr, size_t element_size) {
arr->element_size = element_size;
arr->size = 0;
arr->capacity = CHUNK_SIZE;
arr->data = ar_alloc(CHUNK_SIZE * element_size);
arr->resizable = true;
if (!arr->data) {
fprintf(stderr, "darray_armem_init: allocation failed\n");
exit(EXIT_FAILURE);
}
}
void darray_armem_resize(darray_armem *arr, size_t new_size) {
if (!arr->resizable) {
fprintf(stderr, "darray_armem_resize: unresizable darray_armem\n");
exit(EXIT_FAILURE);
}
size_t new_capacity = ((new_size + CHUNK_SIZE) / CHUNK_SIZE) * CHUNK_SIZE;
if (new_capacity != arr->capacity) {
void *new_data = ar_alloc(new_capacity * arr->element_size);
memccpy(new_data,arr->data, arr->element_size, arr->capacity);
if (!new_data) {
fprintf(stderr, "darray_armem_resize: reallocation failed\n");
exit(EXIT_FAILURE);
}
arr->data = new_data;
arr->capacity = new_capacity;
}
arr->size = new_size;
}
void darray_armem_push(darray_armem *arr, void *element) {
if (!arr->resizable) {
fprintf(stderr, "darray_armem_resize: unresizable darray_armem\n");
exit(EXIT_FAILURE);
}
if (arr->size >= arr->capacity) {
darray_armem_resize(arr, arr->size + 1);
} else {
arr->size++;
}
void *target = (char *)arr->data + (arr->size - 1) * arr->element_size;
memcpy(target, element, arr->element_size);
}
void darray_armem_pop(darray_armem *arr, void (*free_data)(void *)) {
if (!arr->resizable) {
fprintf(stderr, "darray_armem_resize: unresizable darray_armem\n");
exit(EXIT_FAILURE);
}
if (arr->size == 0)
return;
if (free_data) {
void *target = (char *)arr->data + (arr->size-1) * arr->element_size;
free_data(target);
}
darray_armem_resize(arr, arr->size-1);
}
void *darray_armem_get(darray_armem *arr, size_t index) {
if (index >= arr->size) {
fprintf(stderr, "darray_armem_get: index out of bounds\n");
exit(EXIT_FAILURE);
}
return (char *)arr->data + index * arr->element_size;
}
darray_armem darray_armem_slice(darray_armem *arr, size_t start, size_t end) {
if (start > end || end > arr->size) {
fprintf(stderr, "darray_armem_slice: invalid slice range\n");
exit(EXIT_FAILURE);
}
darray_armem slice;
slice.data = (char *)arr->data + start * arr->element_size;
slice.size = (end - start);
slice.element_size = arr->element_size;
slice.capacity = ((slice.size + CHUNK_SIZE) / CHUNK_SIZE) * CHUNK_SIZE;
slice.resizable = false;
return slice;
}
void darray_armem_free(darray_armem *arr, void (*free_data)(void *)) {
if (!arr->resizable) {
// It's a view/slice — don't free
return;
}
if (free_data) {
for (size_t i = 0; i < arr->size; ++i) {
void *element = (char *)arr->data + i * arr->element_size;
free_data(element);
}
}
free(arr->data);
arr->data = NULL;
arr->size = 0;
arr->capacity = 0;
arr->element_size = 0;
arr->resizable = false;
}

View File

@@ -0,0 +1,37 @@
#ifndef darray_armem_H
#define darray_armem_H
#include <stdbool.h>
#include <stddef.h> // for size_t
#define CHUNK_SIZE 1048576
typedef struct {
void *data;
size_t element_size;
size_t size;
size_t capacity;
bool resizable;
} darray_armem;
// Initializes the dynamic_array
void darray_armem_init(darray_armem *arr, size_t element_size);
// Pushes an element onto the array
void darray_armem_push(darray_armem *arr, void *element);
// Pops the last element, calling `free_data` if provided
void darray_armem_pop(darray_armem *arr, void (*free_data)(void *));
// Gets a pointer to an element at index
void *darray_armem_get(darray_armem *arr, size_t index);
// Frees the entire array and optionally each element
void darray_armem_free(darray_armem *arr, void (*free_data)(void *));
// Resizes the array to a new size (internal use, but exposed)
void darray_armem_resize(darray_armem *arr, size_t new_size);
darray_armem darray_armem_slice(darray_armem *arr, size_t start, size_t end);
#endif // darray_armem_H

View File

@@ -7,47 +7,47 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct hashmap *createHashmap() { struct hashmap_GC *createHashmap_GC() {
size_t size = 8; size_t size = 8;
struct hashmap *t = (struct hashmap *)ar_alloc(sizeof(struct hashmap)); struct hashmap_GC *t = (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC));
t->size = size; t->size = size;
t->order = 1; t->order = 1;
t->list = (struct node **)ar_alloc(sizeof(struct node *) * size); t->list = (struct node_GC **)ar_alloc(sizeof(struct node_GC *) * size);
memset(t->list, 0, sizeof(struct node *) * size); memset(t->list, 0, sizeof(struct node_GC *) * size);
return t; return t;
} }
void resize_hashmap(struct hashmap *t) { void resize_hashmap_GC(struct hashmap_GC *t) {
int old_size = t->size; int old_size = t->size;
int new_size = old_size * 2; int new_size = old_size * 2;
struct node **old_list = t->list; struct node_GC **old_list = t->list;
// Create new list // Create new list
t->list = (struct node **)ar_alloc(sizeof(struct node *) * new_size); t->list = (struct node_GC **)ar_alloc(sizeof(struct node_GC *) * new_size);
memset(t->list, 0, sizeof(struct node *) * new_size); memset(t->list, 0, sizeof(struct node_GC *) * new_size);
t->size = new_size; t->size = new_size;
t->count = 0; t->count = 0;
// Rehash old entries into new list // Rehash old entries into new list
for (int i = 0; i < old_size; i++) { for (int i = 0; i < old_size; i++) {
struct node *temp = old_list[i]; struct node_GC *temp = old_list[i];
while (temp) { while (temp) {
hashmap_insert(t, temp->hash, temp->key, temp->val, hashmap_insert_GC(t, temp->hash, temp->key, temp->val,
temp->order); // Will increment count temp->order); // Will increment count
temp = temp->next; temp = temp->next;
} }
} }
} }
int hashCode(struct hashmap *t, uint64_t hash) { return hash % t->size; } int hashCode_GC(struct hashmap_GC *t, uint64_t hash) { return hash % t->size; }
int hashmap_remove(struct hashmap *t, uint64_t hash) { int hashmap_remove_GC(struct hashmap_GC *t, uint64_t hash) {
int pos = hashCode(t, hash); int pos = hashCode_GC(t, hash);
struct node *list = t->list[pos]; struct node_GC *list = t->list[pos];
struct node *temp = list; struct node_GC *temp = list;
struct node *prev = NULL; struct node_GC *prev = NULL;
while (temp) { while (temp) {
if (temp->hash == hash) { if (temp->hash == hash) {
if (prev) if (prev)
@@ -65,18 +65,18 @@ int hashmap_remove(struct hashmap *t, uint64_t hash) {
return 0; return 0;
} }
void hashmap_insert(struct hashmap *t, uint64_t hash, void *key, void hashmap_insert_GC(struct hashmap_GC *t, uint64_t hash, void *key,
void *val, size_t order) { void *val, size_t order) {
if (!order) { if (!order) {
order = t->order++; order = t->order++;
} }
if ((t->count + 1) > t->size * 0.75) { if ((t->count + 1) > t->size * 0.75) {
resize_hashmap(t); resize_hashmap_GC(t);
} }
int pos = hashCode(t, hash); int pos = hashCode_GC(t, hash);
struct node *list = t->list[pos]; struct node_GC *list = t->list[pos];
struct node *temp = list; struct node_GC *temp = list;
// Check if key exists → overwrite // Check if key exists → overwrite
while (temp) { while (temp) {
@@ -88,7 +88,7 @@ void hashmap_insert(struct hashmap *t, uint64_t hash, void *key,
} }
// Insert new node // Insert new node
struct node *newNode = (struct node *)ar_alloc(sizeof(struct node)); struct node_GC *newNode = (struct node_GC *)ar_alloc(sizeof(struct node_GC));
newNode->hash = hash; newNode->hash = hash;
newNode->key = key; newNode->key = key;
newNode->val = val; newNode->val = val;
@@ -98,10 +98,10 @@ void hashmap_insert(struct hashmap *t, uint64_t hash, void *key,
t->count++; t->count++;
} }
void *hashmap_lookup(struct hashmap *t, uint64_t hash) { void *hashmap_lookup_GC(struct hashmap_GC *t, uint64_t hash) {
int pos = hashCode(t, hash); int pos = hashCode_GC(t, hash);
struct node *list = t->list[pos]; struct node_GC *list = t->list[pos];
struct node *temp = list; struct node_GC *temp = list;
while (temp) { while (temp) {
if (temp->hash == hash) { if (temp->hash == hash) {
return temp->val; return temp->val;

View File

@@ -1,33 +1,33 @@
#ifndef HASHMAP_H #ifndef HASHMAP_GC_H
#define HASHMAP_H #define HASHMAP_GC_H
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
typedef struct ArgonObject ArgonObject; typedef struct ArgonObject ArgonObject;
struct node { struct node_GC {
uint64_t hash; uint64_t hash;
void *key; void *key;
void *val; void *val;
size_t order; size_t order;
struct node *next; struct node_GC *next;
}; };
struct hashmap { struct hashmap_GC {
size_t size; size_t size;
size_t count; size_t count;
size_t order; size_t order;
struct node **list; struct node_GC **list;
}; };
struct hashmap *createHashmap(); struct hashmap_GC *createHashmap_GC();
int hashCode(struct hashmap *t, uint64_t hash); int hashCode_GC(struct hashmap_GC *t, uint64_t hash);
int hashmap_remove(struct hashmap *t, uint64_t hash); int hashmap_remove_GC(struct hashmap_GC *t, uint64_t hash);
void hashmap_insert(struct hashmap *t, uint64_t hash, void *key, void hashmap_insert_GC(struct hashmap_GC *t, uint64_t hash, void *key,
void *val, size_t order); void *val, size_t order);
void *hashmap_lookup(struct hashmap *t, uint64_t hash); void *hashmap_lookup_GC(struct hashmap_GC *t, uint64_t hash);
#endif // HASHMAP_H #endif // HASHMAP_GC_H

View File

@@ -1,22 +0,0 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2021 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <inttypes.h>
#include <string.h>
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen);

View File

@@ -0,0 +1,40 @@
#include "../../runtime.h"
#include "../object.h"
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
ArgonObject *ARGON_FUNCTION_TYPE = NULL;
void init_function_type() {
ARGON_FUNCTION_TYPE = init_argon_class("Function");
}
void load_argon_function(Translated *translated, RuntimeState *state,
struct Stack stack) {
ArgonObject *object = init_child_argon_object(ARGON_FUNCTION_TYPE);
object->type = TYPE_FUNCTION;
uint64_t offset = pop_bytecode(translated, state);
uint64_t length = pop_bytecode(translated, state);
object->name = ar_alloc_atomic(length + 1);
memcpy(object->name, arena_get(&translated->constants, offset), length);
object->name[length] = '\0';
object->value.argon_fn.number_of_parameters = pop_bytecode(translated, state);
object->value.argon_fn.parameters =
ar_alloc(object->value.argon_fn.number_of_parameters * sizeof(char *));
for (size_t i = 0; i < object->value.argon_fn.number_of_parameters; i++) {
offset = pop_bytecode(translated, state);
length = pop_bytecode(translated, state);
object->value.argon_fn.parameters[i] = ar_alloc_atomic(length + 1);
memcpy(object->value.argon_fn.parameters[i], arena_get(&translated->constants, offset), length);
object->value.argon_fn.parameters[i][length] = '\0';
}
offset = pop_bytecode(translated, state);
length = pop_bytecode(translated, state);
darray_armem_init(&object->value.argon_fn.bytecode, sizeof(uint64_t));
darray_armem_resize(&object->value.argon_fn.bytecode, length/object->value.argon_fn.bytecode.element_size);
memcpy(object->value.argon_fn.bytecode.data, arena_get(&translated->constants, offset), length);
object->value.argon_fn.stack = stack;
state->registers[0]=object;
}

View File

@@ -0,0 +1,9 @@
#ifndef FUNCTION_H
#define FUNCTION_H
#include "../object.h"
void init_function_type();
ArgonObject *load_argon_function(Translated *translated, RuntimeState *state, struct Stack stack);
#endif // FUNCTION_H

View File

@@ -3,8 +3,12 @@
#include <string.h> #include <string.h>
#include "null.h" #include "null.h"
ArgonObject *ARGON_NULL_TYPE = NULL;
ArgonObject *ARGON_NULL = NULL; ArgonObject *ARGON_NULL = NULL;
void init_null() { void init_null() {
ARGON_NULL = init_argon_object(); ARGON_NULL_TYPE = init_argon_class("NULL_TYPE");
ARGON_NULL = init_child_argon_object(ARGON_NULL_TYPE);
ARGON_NULL->type=TYPE_NULL;
} }

View File

@@ -1,24 +1,37 @@
#include "object.h" #include "object.h"
#include "../../hash_data/hash_data.h"
#include "../../memory.h" #include "../../memory.h"
#include "../runtime.h" #include "type/type.h"
#include <stdbool.h>
#include <string.h> #include <string.h>
ArgonObject *BASE_OBJECT = NULL; ArgonObject *BASE_CLASS = NULL;
void init_base_field() { void init_base_field() {
add_field(BASE_OBJECT, "test", BASE_OBJECT); // add_field(BASE_CLASS, "test", BASE_CLASS);
} }
ArgonObject* init_argon_object() { ArgonObject *init_child_argon_object(ArgonObject *cls) {
ArgonObject *object = ar_alloc(sizeof(ArgonObject)); ArgonObject *object = init_argon_class(NULL);
object->type = TYPE_OBJECT; object->self = object;
object->typeObject = NULL; object->baseObject = cls;
object->baseObject = BASE_OBJECT; add_field(object, "__call__", NULL);
object->fields = createHashmap(); return object;
memset(&object->value, 0, sizeof(object->value));
return object;
} }
void add_field(ArgonObject*target, char* name, ArgonObject *object) { ArgonObject *init_argon_class(char *name) {
hashmap_insert(target->fields, siphash64_bytes(name, strlen(name)),name, object, 0); ArgonObject *object = ar_alloc(sizeof(ArgonObject));
object->name = name;
object->type = TYPE_OBJECT;
object->self = NULL;
object->baseObject = ARGON_TYPE;
object->fields = createHashmap_GC();
memset(&object->value, 0, sizeof(object->value));
return object;
}
void add_field(ArgonObject *target, char *name, ArgonObject *object) {
hashmap_insert_GC(target->fields,
siphash64_bytes(name, strlen(name), siphash_key), name,
object, 0);
} }

View File

@@ -1,15 +1,23 @@
#ifndef OBJECT_H #ifndef OBJECT_H
#define OBJECT_H #define OBJECT_H
#include "../internals/hashmap/hashmap.h" #include "../internals/hashmap/hashmap.h"
#include "../internals/dynamic_array_armem/darray_armem.h"
#include <gmp.h> #include <gmp.h>
#include <stdbool.h> #include <stdbool.h>
#include "../runtime.h"
extern ArgonObject *BASE_OBJECT; extern ArgonObject *BASE_CLASS;
struct string_struct { struct string_struct {
char *data; char *data;
size_t length; size_t length;
}; };
struct argon_function_struct {
darray_armem bytecode;
struct Stack stack;
size_t number_of_parameters;
char** parameters;
};
typedef enum { typedef enum {
TYPE_NULL, TYPE_NULL,
@@ -23,21 +31,23 @@ typedef enum {
struct ArgonObject { struct ArgonObject {
ArgonType type; ArgonType type;
char* name;
ArgonObject *self;
ArgonObject *baseObject; ArgonObject *baseObject;
ArgonObject *typeObject; struct hashmap_GC *fields; // dynamic fields/methods
struct hashmap *fields; // dynamic fields/methods
union { union {
mpq_t as_number; mpq_t as_number;
bool as_bool; bool as_bool;
struct string_struct as_str; struct string_struct as_str;
void *native_fn; void *native_fn;
struct argon_function_struct argon_fn;
// others as needed // others as needed
} value; } value;
}; };
typedef struct ArgonObject ArgonObject; typedef struct ArgonObject ArgonObject;
void init_base_field(); void init_base_field();
ArgonObject* init_child_argon_object(ArgonObject *cls);
ArgonObject *init_argon_object(); ArgonObject* init_argon_class(char*name);
void add_field(ArgonObject*target, char* name, ArgonObject *object); void add_field(ArgonObject*target, char* name, ArgonObject *object);
#endif // OBJECT_H #endif // OBJECT_H

View File

@@ -2,23 +2,18 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdio.h> #include <stdio.h>
#include "string.h"
ArgonObject *ARGON_STRING_TYPE = NULL; ArgonObject *ARGON_STRING_TYPE = NULL;
ArgonObject *ARGON_STRING_BASE = NULL;
void init_string_type() { void init_string_type() {
ARGON_STRING_TYPE = init_argon_object(); ARGON_STRING_TYPE = init_argon_class("String");
ARGON_STRING_BASE = init_argon_object();
} }
ArgonObject *init_string_object(char*data, size_t length) { ArgonObject *init_string_object(char*data, size_t length) {
fwrite(data, 1, length, stdout); ArgonObject * object = init_child_argon_object(ARGON_STRING_TYPE);
printf("\n"); object->type = TYPE_STRING;
ArgonObject * object = init_argon_object();
object->typeObject = ARGON_STRING_TYPE;
object->baseObject = ARGON_STRING_BASE;
object->value.as_str.data = data; object->value.as_str.data = data;
object->value.as_str.length = length; object->value.as_str.length = length;
return object; return object;

View File

@@ -6,5 +6,6 @@
ArgonObject *ARGON_TYPE = NULL; ArgonObject *ARGON_TYPE = NULL;
void init_type() { void init_type() {
ARGON_TYPE = init_argon_object(); ARGON_TYPE = init_argon_class("type");
ARGON_TYPE->baseObject = BASE_CLASS;
} }

View File

@@ -1,57 +1,80 @@
#include "runtime.h" #include "runtime.h"
#include "../translator/translator.h" #include "../translator/translator.h"
#include "internals/siphash/siphash.h" #include "objects/functions/functions.h"
#include "objects/null/null.h" #include "objects/null/null.h"
#include "objects/object.h" #include "objects/object.h"
#include "objects/string/string.h" #include "objects/string/string.h"
#include "objects/type/type.h" #include "objects/type/type.h"
#include <fcntl.h> #include <fcntl.h>
#include <gc/gc.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
uint64_t bytes_to_uint64(const uint8_t bytes[8]) {
uint64_t value = 0;
for (int i = 0; i < 8; i++) {
value |= ((uint64_t)bytes[i]) << (i * 8);
}
return value;
}
void init_types() { void init_types() {
BASE_OBJECT = init_argon_object(); BASE_CLASS = init_argon_class("BASE_CLASS");
init_type(); init_type();
init_function_type();
init_null(); init_null();
init_string_type(); init_string_type();
init_base_field(); init_base_field();
} }
uint8_t pop_byte(Translated *translated, RuntimeState *state) {
return *((uint8_t *)darray_get(&translated->bytecode, state->head++));
}
uint64_t pop_bytecode(Translated *translated, RuntimeState *state) { uint64_t pop_bytecode(Translated *translated, RuntimeState *state) {
uint64_t *instruction = darray_get(&translated->bytecode, state->head++); uint8_t bytes[8];
return *instruction; for (size_t i = 0; i < sizeof(bytes); i++) {
bytes[i] = *((uint8_t *)darray_get(&translated->bytecode, state->head++));
}
return bytes_to_uint64(bytes);
} }
void load_const(Translated *translated, RuntimeState *state) { void load_const(Translated *translated, RuntimeState *state) {
uint64_t to_register = pop_bytecode(translated, state); uint64_t to_register = pop_byte(translated, state);
types type = pop_bytecode(translated, state); types type = pop_byte(translated, state);
size_t length = pop_bytecode(translated, state); size_t length = pop_bytecode(translated, state);
uint64_t offset = pop_bytecode(translated, state); uint64_t offset = pop_bytecode(translated, state);
void*data = ar_alloc(length); void *data = ar_alloc_atomic(length);
memcpy(data, arena_get(&translated->constants,offset), length); memcpy(data, arena_get(&translated->constants, offset), length);
ArgonObject *object = ARGON_NULL; ArgonObject *object = ARGON_NULL;
switch (type) { switch (type) {
case TYPE_OP_STRING: case TYPE_OP_STRING:
object = init_string_object(data, length); object = init_string_object(data, length);
break; break;
} }
state->registers[to_register] = object; state->registers[to_register] = object;
} }
void run_instruction(Translated *translated, RuntimeState *state) { void run_instruction(Translated *translated, RuntimeState *state,
OperationType opcode = pop_bytecode(translated, state); struct Stack stack) {
OperationType opcode = pop_byte(translated, state);
switch (opcode) { switch (opcode) {
case OP_LOAD_NULL: case OP_LOAD_NULL:
state->registers[pop_bytecode(translated, state)] = ARGON_NULL; state->registers[pop_byte(translated, state)] = ARGON_NULL;
break; break;
case OP_LOAD_CONST: case OP_LOAD_CONST:
load_const(translated,state); load_const(translated, state);
break;
case OP_LOAD_FUNCTION:
load_argon_function(translated, state, stack);
break; break;
} }
} }
@@ -59,30 +82,10 @@ void run_instruction(Translated *translated, RuntimeState *state) {
void runtime(Translated translated) { void runtime(Translated translated) {
RuntimeState state = { RuntimeState state = {
checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0}; checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0};
struct Stack stack = {};
while (state.head < translated.bytecode.size) state.head = 0;
run_instruction(&translated, &state); while (state.head < translated.bytecode.size) {
run_instruction(&translated, &state, stack);
}
free(state.registers); free(state.registers);
} }
static uint8_t siphash_key[16];
void generate_siphash_key() {
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0 || read(fd, siphash_key, 16) != 16) {
// Fallback or abort
}
close(fd);
}
uint64_t siphash64_bytes(const void *data, size_t len) {
uint8_t out[8];
if (siphash(data, len, siphash_key, out, sizeof(out)) != 0)
return 0;
uint64_t hash = 0;
for (int i = 0; i < 8; ++i)
hash |= ((uint64_t)out[i]) << (8 * i);
return hash;
}

View File

@@ -8,14 +8,17 @@ typedef struct {
size_t head; size_t head;
} RuntimeState; } RuntimeState;
typedef struct Stack {
ArgonObject *scope;
struct Stack *prev;
} Stack;
void init_types(); void init_types();
void run_instruction(Translated *translated, RuntimeState *state); uint64_t pop_bytecode(Translated *translated, RuntimeState *state);
void run_instruction(Translated *translated, RuntimeState *state, struct Stack stack);
void runtime(Translated translated); void runtime(Translated translated);
uint64_t siphash64_bytes(const void *data, size_t len);
void generate_siphash_key();
#endif // RUNTIME_H #endif // RUNTIME_H

View File

@@ -1,13 +1,15 @@
# Bytecode Specification # Bytecode Specification
all opcodes are uint8_t, and all operands are uint64_t unless marked with an asterisk (*), where it is marked as uint8_t
## OP_LOAD_CONST ## OP_LOAD_CONST
loads and initialises a value from the constant buffer into the provided register. loads and initialises a value from the constant buffer into the provided register.
this operation 4 operands. this operation 4 operands.
1. the register to write to. 1. the register to write to. (*)
2. the type of data from the constant buffer. 2. the type of data from the constant buffer. (*)
3. the length of the data in the constant buffer. 3. the length of the data in the constant buffer.
4. the offset in the constant buffer. 4. the offset in the constant buffer.
@@ -19,7 +21,7 @@ this operation takes 3 operands.
1. the length of the variable name. 1. the length of the variable name.
2. the offset in the constant buffer of the variable name. 2. the offset in the constant buffer of the variable name.
3. the register of the given value 3. the register of the given value (*)
## OP_LOAD_NULL ## OP_LOAD_NULL
@@ -27,4 +29,17 @@ sets a given register to null.
this operation takes 1 operand. this operation takes 1 operand.
1. the register to set to null. 1. the register to set to null. (*)
## OP_LOAD_FUNCTION
initilises a function to a given register.
1. the offset of the name of the function.
2. the length of the name of the function.
3. the number of arguments.
4. the offset of the name of the argument.
5. the length of the name of the argument.
6. instruction 4 and 5 loop for each argument.
7. the offset of the bytecode of the function.
8. the length of the bytecode of the function.

View File

@@ -9,7 +9,6 @@ size_t translate_parsed_declaration(Translated *translated,
set_registers(translated, 1); set_registers(translated, 1);
size_t first = 0; size_t first = 0;
for (size_t i = 0; i < delcarations.size; i++) { for (size_t i = 0; i < delcarations.size; i++) {
// TODO: add function delclaration
ParsedSingleDeclaration *singleDeclaration = darray_get(&delcarations, i); ParsedSingleDeclaration *singleDeclaration = darray_get(&delcarations, i);
size_t temp = translate_parsed(translated, singleDeclaration->from); size_t temp = translate_parsed(translated, singleDeclaration->from);
if (i == 0) if (i == 0)
@@ -18,14 +17,14 @@ size_t translate_parsed_declaration(Translated *translated,
size_t offset = size_t offset =
arena_push(&translated->constants, singleDeclaration->name, length); arena_push(&translated->constants, singleDeclaration->name, length);
push_instruction_code(translated, OP_DECLARE); push_instruction_byte(translated, OP_DECLARE);
push_instruction_code(translated, length); push_instruction_code(translated, length);
push_instruction_code(translated, offset); push_instruction_code(translated, offset);
push_instruction_code(translated, 0); push_instruction_byte(translated, 0);
} }
if (delcarations.size != 1) { if (delcarations.size != 1) {
push_instruction_code(translated, OP_LOAD_NULL); push_instruction_byte(translated, OP_LOAD_NULL);
push_instruction_code(translated, 0); push_instruction_byte(translated, 0);
} }
return first; return first;
} }

View File

@@ -1,9 +1,37 @@
#include "function.h" #include "function.h"
#include "../translator.h" #include "../translator.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
size_t translate_parsed_function(Translated *translated, size_t translate_parsed_function(Translated *translated,
ParsedValue *parsedValue) { ParsedFunction *parsedFunction) {
return 0; DArray main_bytecode = translated->bytecode;
DArray _temp_bytecode;
darray_init(&_temp_bytecode, sizeof(uint8_t));
translated->bytecode = _temp_bytecode;
translate_parsed(translated, parsedFunction->body);
size_t function_bytecode_offset =
arena_push(&translated->constants, translated->bytecode.data,
translated->bytecode.size*translated->bytecode.element_size);
size_t function_bytecode_length = translated->bytecode.size;
darray_free(&translated->bytecode, NULL);
translated->bytecode = main_bytecode;
size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION);
size_t offset = arena_push(&translated->constants, parsedFunction->name,
strlen(parsedFunction->name));
push_instruction_code(translated, offset);
push_instruction_code(translated, strlen(parsedFunction->name));
push_instruction_code(translated, parsedFunction->parameters.size);
for (size_t i = 0; i < parsedFunction->parameters.size; i++) {
char **parameter_name = darray_get(&parsedFunction->parameters, i);
offset = arena_push(&translated->constants, *parameter_name,
strlen(*parameter_name));
push_instruction_code(translated, offset);
push_instruction_code(translated, strlen(*parameter_name));
}
push_instruction_code(translated, function_bytecode_offset);
push_instruction_code(translated, function_bytecode_length*translated->bytecode.element_size);
return start;
} }

View File

@@ -1,8 +1,9 @@
#ifndef BYTECODE_FUNCTION_H #ifndef BYTECODE_FUNCTION_H
#define BYTECODE_FUNCTION_H #define BYTECODE_FUNCTION_H
#include "../translator.h" #include "../translator.h"
#include "../../parser/function/function.h"
size_t translate_parsed_function(Translated *translated, size_t translate_parsed_function(Translated *translated,
ParsedValue *parsedValue); ParsedFunction *parsedFunction);
#endif #endif

View File

@@ -10,10 +10,10 @@ size_t translate_parsed_number(Translated *translated, char *number_str, size_t
size_t number_pos = arena_push(&translated->constants, number_str, length); size_t number_pos = arena_push(&translated->constants, number_str, length);
set_registers(translated, to_register+1); set_registers(translated, to_register+1);
size_t start = push_instruction_code(translated, OP_LOAD_CONST); size_t start = push_instruction_byte(translated, OP_LOAD_CONST);
push_instruction_code(translated, to_register); push_instruction_byte(translated, to_register);
push_instruction_code(translated, TYPE_OP_NUMBER); push_instruction_byte(translated, TYPE_OP_NUMBER);
push_instruction_code(translated,length); push_instruction_code(translated,length);
push_instruction_code(translated, number_pos); push_instruction_code(translated, number_pos);
return start; return start;

View File

@@ -7,9 +7,9 @@
size_t translate_parsed_string(Translated *translated, ParsedString parsedString) { size_t translate_parsed_string(Translated *translated, ParsedString parsedString) {
size_t string_pos = arena_push(&translated->constants, parsedString.string, parsedString.length); size_t string_pos = arena_push(&translated->constants, parsedString.string, parsedString.length);
set_registers(translated, 1); set_registers(translated, 1);
size_t start = push_instruction_code(translated, OP_LOAD_CONST); size_t start = push_instruction_byte(translated, OP_LOAD_CONST);
push_instruction_code(translated, 0); push_instruction_byte(translated, 0);
push_instruction_code(translated, TYPE_OP_STRING); push_instruction_byte(translated, TYPE_OP_STRING);
push_instruction_code(translated,parsedString.length); push_instruction_code(translated,parsedString.length);
push_instruction_code(translated, string_pos); push_instruction_code(translated, string_pos);
return start; return start;

View File

@@ -1,5 +1,8 @@
#include "translator.h" #include "translator.h"
#include "../hash_data/hash_data.h"
#include "../hashmap/hashmap.h"
#include "declaration/declaration.h" #include "declaration/declaration.h"
#include "function/function.h"
#include "number/number.h" #include "number/number.h"
#include "string/string.h" #include "string/string.h"
#include <stddef.h> #include <stddef.h>
@@ -8,10 +11,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void uint64_to_bytes(uint64_t value, uint8_t bytes[8]) {
for (int i = 0; i < 8; i++) {
bytes[i] = (value >> (i * 8)) & 0xFF;
}
}
void arena_init(ConstantArena *arena) { void arena_init(ConstantArena *arena) {
arena->data = checked_malloc(CHUNK_SIZE); arena->data = checked_malloc(CHUNK_SIZE);
arena->capacity = CHUNK_SIZE; arena->capacity = CHUNK_SIZE;
arena->size = 0; arena->size = 0;
arena->hashmap = createHashmap();
} }
void arena_resize(ConstantArena *arena, size_t new_size) { void arena_resize(ConstantArena *arena, size_t new_size) {
@@ -31,6 +41,7 @@ void arena_free(ConstantArena *arena) {
free(arena->data); free(arena->data);
arena->capacity = 0; arena->capacity = 0;
arena->size = 0; arena->size = 0;
hashmap_free(arena->hashmap, NULL);
} }
void *arena_get(ConstantArena *arena, size_t offset) { void *arena_get(ConstantArena *arena, size_t offset) {
@@ -38,42 +49,57 @@ void *arena_get(ConstantArena *arena, size_t offset) {
} }
size_t arena_push(ConstantArena *arena, const void *data, size_t length) { size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
if (arena->size >= length) { uint64_t hash = siphash64_bytes(data, length, siphash_key);
for (size_t i = 0; i <= (arena->size - length); i++) {
if (memcmp(data, arena->data + i, length) == 0) { // Look up offset in hashmap
return i; void *val = hashmap_lookup(arena->hashmap, hash);
} if (val != NULL) {
size_t offset =
(size_t)(uintptr_t)val - 1; // stored as pointer but really offset
// Verify to avoid collision false positive
if (memcmp(arena->data + offset, data, length) == 0) {
return offset;
} }
} }
// Not found: append data
arena_resize(arena, arena->size + length); arena_resize(arena, arena->size + length);
size_t offset = arena->size; size_t offset = arena->size;
memcpy(arena->data + arena->size, data, length); memcpy(arena->data + arena->size, data, length);
arena->size += length; arena->size += length;
// Insert into hashmap: store offset as pointer-sized integer
hashmap_insert(arena->hashmap, hash, (void *)data,
(void *)(uintptr_t)offset + 1, 0);
return offset; return offset;
} }
Translated init_translator() { Translated init_translator() {
Translated translated; Translated translated;
translated.registerCount = 0; translated.registerCount = 0;
darray_init(&translated.bytecode, sizeof(uint64_t)); darray_init(&translated.bytecode, sizeof(uint8_t));
arena_init(&translated.constants); arena_init(&translated.constants);
return translated; return translated;
} }
void set_instruction_code(Translated *translator, size_t offset, size_t push_instruction_byte(Translated *translator, uint8_t byte) {
uint64_t code) {
size_t *ptr = (translator->bytecode.data + offset);
*ptr = code;
}
size_t push_instruction_code(Translated *translator, uint64_t code) {
code = htole64(code);
size_t offset = translator->bytecode.size; size_t offset = translator->bytecode.size;
darray_push(&translator->bytecode, &code); darray_push(&translator->bytecode, &byte);
return offset; return offset;
} }
void set_registers(Translated *translator, size_t count) { size_t push_instruction_code(Translated *translator, uint64_t code) {
size_t offset = translator->bytecode.size;
uint8_t bytes[8];
uint64_to_bytes(code, bytes);
for (size_t i = 0; i < sizeof(bytes); i++) {
darray_push(&translator->bytecode, &(bytes[i]));
}
return offset;
}
void set_registers(Translated *translator, uint8_t count) {
if (count > translator->registerCount) if (count > translator->registerCount)
translator->registerCount = count; translator->registerCount = count;
} }
@@ -81,16 +107,21 @@ void set_registers(Translated *translator, size_t count) {
size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) { size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) {
switch (parsedValue->type) { switch (parsedValue->type) {
case AST_STRING: case AST_STRING:
return translate_parsed_string(translated, *((ParsedString*)parsedValue->data)); return translate_parsed_string(translated,
*((ParsedString *)parsedValue->data));
case AST_DECLARATION: case AST_DECLARATION:
return translate_parsed_declaration(translated, *((DArray*)parsedValue->data)); return translate_parsed_declaration(translated,
*((DArray *)parsedValue->data));
case AST_NUMBER: case AST_NUMBER:
return translate_parsed_number(translated, (char*)parsedValue->data, 0); return translate_parsed_number(translated, (char *)parsedValue->data, 0);
case AST_NULL: case AST_NULL:
set_registers(translated, 1); set_registers(translated, 1);
size_t output = push_instruction_code(translated, OP_LOAD_NULL); size_t output = push_instruction_byte(translated, OP_LOAD_NULL);
push_instruction_code(translated, 0); push_instruction_byte(translated, 0);
return output; return output;
case AST_FUNCTION:
return translate_parsed_function(translated,
(ParsedFunction *)parsedValue->data);
} }
return 0; return 0;
} }

View File

@@ -4,33 +4,37 @@
#include "../dynamic_array/darray.h" #include "../dynamic_array/darray.h"
#include "../memory.h" #include "../memory.h"
#include "../parser/parser.h" #include "../parser/parser.h"
#include "../hashmap/hashmap.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
typedef enum { OP_LOAD_CONST = 255, OP_DECLARE, OP_LOAD_NULL } OperationType; typedef enum { OP_LOAD_CONST, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION } OperationType;
typedef enum { TYPE_OP_STRING = 255, TYPE_OP_NUMBER } types; typedef enum { TYPE_OP_STRING, TYPE_OP_NUMBER } types;
typedef struct { typedef struct {
void *data; void *data;
size_t capacity; size_t capacity;
size_t size; size_t size;
struct hashmap * hashmap;
} ConstantArena; } ConstantArena;
typedef struct { typedef struct {
size_t registerCount; uint8_t registerCount;
DArray bytecode; DArray bytecode;
ConstantArena constants; ConstantArena constants;
} Translated; } Translated;
void arena_resize(ConstantArena *arena, size_t new_size);
void *arena_get(ConstantArena *arena, size_t offset); void *arena_get(ConstantArena *arena, size_t offset);
size_t arena_push(ConstantArena *arena, const void *data, size_t length); size_t arena_push(ConstantArena *arena, const void *data, size_t length);
void set_instruction_code(Translated * translator, size_t offset, uint64_t code); size_t push_instruction_byte(Translated *translator, uint8_t byte);
size_t push_instruction_code(Translated *translator, uint64_t code); size_t push_instruction_code(Translated *translator, uint64_t code);
void set_registers(Translated *translator, size_t count); void set_registers(Translated *translator, uint8_t count);
Translated init_translator(); Translated init_translator();

View File

@@ -1,6 +1,3 @@
null
"h" "h"
"e" "e"
"ll" "ll"