mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
86 lines
2.0 KiB
C
86 lines
2.0 KiB
C
#include "toy_bytecode.h"
|
|
#include "toy_console_colors.h"
|
|
|
|
#include "toy_routine.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
//utils
|
|
static void expand(Toy_Bytecode* bc, unsigned int amount) {
|
|
if (bc->count + amount > bc->capacity) {
|
|
|
|
while (bc->count + amount > bc->capacity) { //expand as much as needed
|
|
bc->capacity = bc->capacity < 8 ? 8 : bc->capacity * 2;
|
|
}
|
|
|
|
bc->ptr = realloc(bc->ptr, bc->capacity);
|
|
|
|
if (bc->ptr == NULL) {
|
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Bytecode' of %d capacity\n" TOY_CC_RESET, (int)(bc->capacity));
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void emitByte(Toy_Bytecode* bc, unsigned char byte) {
|
|
expand(bc, 1);
|
|
bc->ptr[bc->count++] = byte;
|
|
}
|
|
|
|
//bytecode
|
|
static void writeBytecodeHeader(Toy_Bytecode* bc) {
|
|
emitByte(bc, TOY_VERSION_MAJOR);
|
|
emitByte(bc, TOY_VERSION_MINOR);
|
|
emitByte(bc, TOY_VERSION_PATCH);
|
|
|
|
//check strlen for the build string
|
|
const char* build = Toy_private_version_build();
|
|
size_t len = strlen(build) + 1;
|
|
|
|
//BUGFIX: ensure the end of the header has 4-byte alignment
|
|
if (len % 4 != 1) { //1 to fill the 4th byte above
|
|
len += 4 - (len % 4) +1; //ceil
|
|
}
|
|
|
|
expand(bc, len);
|
|
memcpy(bc->ptr + bc->count, build, len);
|
|
bc->count += len;
|
|
|
|
bc->ptr[bc->count] = '\0';
|
|
}
|
|
|
|
static void writeBytecodeBody(Toy_Bytecode* bc, Toy_Ast* ast) {
|
|
//a 'module' is a routine that runs at the root-level of a file
|
|
//since routines can be recursive, this distinction is important
|
|
//eventually, the bytecode may support multiple modules packed into one file
|
|
void* module = Toy_compileRoutine(ast);
|
|
|
|
size_t len = (size_t)(((int*)module)[0]);
|
|
|
|
expand(bc, len);
|
|
memcpy(bc->ptr + bc->count, module, len);
|
|
bc->count += len;
|
|
}
|
|
|
|
//exposed functions
|
|
Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast) {
|
|
//setup
|
|
Toy_Bytecode bc;
|
|
|
|
bc.ptr = NULL;
|
|
bc.capacity = 0;
|
|
bc.count = 0;
|
|
|
|
//build
|
|
writeBytecodeHeader(&bc);
|
|
writeBytecodeBody(&bc, ast);
|
|
|
|
return bc;
|
|
}
|
|
|
|
void Toy_freeBytecode(Toy_Bytecode bc) {
|
|
free(bc.ptr);
|
|
}
|