change to uint8_t for bytecode to reduce wasted bytes
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
let x(hello,lol,world, WORLD,HELLOOOO,LOLLLLLL, WORLD)=let f(x)="bruh"
|
|
||||||
35
src/main.c
35
src/main.c
@@ -13,12 +13,15 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
const char FILE_IDENTIFIER[] = "ARBI";
|
const char FILE_IDENTIFIER[] = "ARBI";
|
||||||
const uint64_t version_number = 0;
|
const uint32_t version_number = 0;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
clock_t start,end;
|
||||||
|
double time_spent;
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
if (argc <= 1)
|
if (argc <= 1)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -35,37 +38,48 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LexerState state = {path, file, 0, 0, &tokens};
|
LexerState state = {path, file, 0, 0, &tokens};
|
||||||
|
start = clock();
|
||||||
lexer(state);
|
lexer(state);
|
||||||
|
end = clock();
|
||||||
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
|
printf("Lexer time taken: %f seconds\n", time_spent);
|
||||||
fclose(state.file);
|
fclose(state.file);
|
||||||
|
|
||||||
DArray ast;
|
DArray ast;
|
||||||
|
|
||||||
darray_init(&ast, sizeof(ParsedValue));
|
darray_init(&ast, sizeof(ParsedValue));
|
||||||
|
|
||||||
|
|
||||||
|
start = clock();
|
||||||
parser(path, &ast, &tokens, false);
|
parser(path, &ast, &tokens, false);
|
||||||
|
end = clock();
|
||||||
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
|
printf("Parser time taken: %f seconds\n", time_spent);
|
||||||
darray_free(&tokens, free_token);
|
darray_free(&tokens, free_token);
|
||||||
|
|
||||||
Translated translated = init_translator();
|
Translated translated = init_translator();
|
||||||
|
|
||||||
|
|
||||||
|
start = clock();
|
||||||
translate(&translated, &ast);
|
translate(&translated, &ast);
|
||||||
|
end = clock();
|
||||||
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
|
printf("Translation time taken: %f seconds\n", time_spent);
|
||||||
|
|
||||||
darray_free(&ast, free_parsed);
|
darray_free(&ast, free_parsed);
|
||||||
|
|
||||||
file = fopen("out.arbin", "wb");
|
file = fopen("out.arbin", "wb");
|
||||||
|
|
||||||
uint64_t regCount = (uint64_t)translated.registerCount;
|
|
||||||
uint64_t constantsSize = (uint64_t)translated.constants.size;
|
uint64_t constantsSize = (uint64_t)translated.constants.size;
|
||||||
uint64_t bytecodeSize = (uint64_t)translated.bytecode.size;
|
uint64_t bytecodeSize = (uint64_t)translated.bytecode.size;
|
||||||
|
|
||||||
uint64_t version_number_htole64ed = htole64(version_number);
|
uint32_t version_number_htole32ed = htole32(version_number);
|
||||||
regCount = htole64(regCount);
|
|
||||||
regCount = htole64(regCount);
|
|
||||||
constantsSize = htole64(constantsSize);
|
constantsSize = htole64(constantsSize);
|
||||||
bytecodeSize = htole64(bytecodeSize);
|
bytecodeSize = htole64(bytecodeSize);
|
||||||
|
|
||||||
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file);
|
fwrite(&FILE_IDENTIFIER, sizeof(char), strlen(FILE_IDENTIFIER), file);
|
||||||
fwrite(&version_number_htole64ed, sizeof(uint64_t), 1, file);
|
fwrite(&version_number_htole32ed, sizeof(uint32_t), 1, file);
|
||||||
fwrite(®Count, sizeof(uint64_t), 1, file);
|
fwrite(&translated.registerCount, sizeof(uint8_t), 1, file);
|
||||||
fwrite(&constantsSize, sizeof(uint64_t), 1, file);
|
fwrite(&constantsSize, sizeof(uint64_t), 1, file);
|
||||||
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file);
|
fwrite(&bytecodeSize, sizeof(uint64_t), 1, file);
|
||||||
fwrite(translated.constants.data, 1, translated.constants.size, file);
|
fwrite(translated.constants.data, 1, translated.constants.size, file);
|
||||||
@@ -77,8 +91,15 @@ int main(int argc, char *argv[]) {
|
|||||||
generate_siphash_key();
|
generate_siphash_key();
|
||||||
|
|
||||||
init_types();
|
init_types();
|
||||||
|
|
||||||
|
start = clock();
|
||||||
runtime(translated);
|
runtime(translated);
|
||||||
|
|
||||||
|
end = clock();
|
||||||
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
printf("Execution time taken: %f seconds\n", time_spent);
|
||||||
|
|
||||||
free_translator(&translated);
|
free_translator(&translated);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.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_CLASS = init_argon_class("BASE_CLASS");
|
BASE_CLASS = init_argon_class("BASE_CLASS");
|
||||||
|
|
||||||
@@ -25,14 +33,22 @@ void init_types() {
|
|||||||
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);
|
||||||
|
|
||||||
@@ -49,10 +65,10 @@ void load_const(Translated *translated, RuntimeState *state) {
|
|||||||
|
|
||||||
void run_instruction(Translated *translated, RuntimeState *state,
|
void run_instruction(Translated *translated, RuntimeState *state,
|
||||||
struct Stack stack) {
|
struct Stack stack) {
|
||||||
OperationType opcode = pop_bytecode(translated, state);
|
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);
|
||||||
|
|||||||
@@ -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,7 +29,7 @@ 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
|
## OP_LOAD_FUNCTION
|
||||||
|
|
||||||
|
|||||||
@@ -17,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;
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
#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,
|
||||||
ParsedFunction *parsedFunction) {
|
ParsedFunction *parsedFunction) {
|
||||||
DArray temp_bytecode;
|
|
||||||
darray_init(&temp_bytecode, sizeof(uint64_t));
|
|
||||||
DArray main_bytecode = translated->bytecode;
|
DArray main_bytecode = translated->bytecode;
|
||||||
translated->bytecode = temp_bytecode;
|
DArray _temp_bytecode;
|
||||||
|
darray_init(&_temp_bytecode, sizeof(uint8_t));
|
||||||
|
translated->bytecode = _temp_bytecode;
|
||||||
translate_parsed(translated, parsedFunction->body);
|
translate_parsed(translated, parsedFunction->body);
|
||||||
size_t function_bytecode_offset =
|
size_t function_bytecode_offset =
|
||||||
arena_push(&translated->constants, translated->bytecode.data,
|
arena_push(&translated->constants, translated->bytecode.data,
|
||||||
translated->bytecode.size*translated->bytecode.element_size);
|
translated->bytecode.size*translated->bytecode.element_size);
|
||||||
size_t function_bytecode_length = translated->bytecode.size;
|
size_t function_bytecode_length = translated->bytecode.size;
|
||||||
|
darray_free(&translated->bytecode, NULL);
|
||||||
translated->bytecode = main_bytecode;
|
translated->bytecode = main_bytecode;
|
||||||
darray_free(&temp_bytecode, NULL);
|
size_t start = push_instruction_byte(translated, OP_LOAD_FUNCTION);
|
||||||
size_t start = push_instruction_code(translated, OP_LOAD_FUNCTION);
|
|
||||||
size_t offset = arena_push(&translated->constants, parsedFunction->name,
|
size_t offset = arena_push(&translated->constants, parsedFunction->name,
|
||||||
strlen(parsedFunction->name));
|
strlen(parsedFunction->name));
|
||||||
push_instruction_code(translated, offset);
|
push_instruction_code(translated, offset);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -9,6 +9,12 @@
|
|||||||
#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;
|
||||||
@@ -56,25 +62,29 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) {
|
|||||||
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,
|
|
||||||
uint64_t code) {
|
|
||||||
size_t *ptr = (translator->bytecode.data + offset);
|
|
||||||
*ptr = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t push_instruction_code(Translated *translator, uint64_t code) {
|
size_t push_instruction_byte(Translated *translator, uint8_t byte) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -91,8 +101,8 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) {
|
|||||||
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:
|
case AST_FUNCTION:
|
||||||
return translate_parsed_function(translated,
|
return translate_parsed_function(translated,
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef enum { OP_LOAD_CONST = 255, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION } 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;
|
||||||
@@ -17,7 +17,7 @@ typedef struct {
|
|||||||
} ConstantArena;
|
} ConstantArena;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t registerCount;
|
uint8_t registerCount;
|
||||||
DArray bytecode;
|
DArray bytecode;
|
||||||
ConstantArena constants;
|
ConstantArena constants;
|
||||||
} Translated;
|
} Translated;
|
||||||
@@ -26,11 +26,11 @@ 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();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user