WIP bytecode and routine, read more

The tests are failing in a strange way, with the error message 'corrupted top size'. I don't know what it means, and it seems to be caused by a call to printf() within 'test_bytecode.c'. I need a break, as this is making me dizzy.
This commit is contained in:
2024-09-19 12:45:35 +10:00
parent 47ac1c5b30
commit 083ee950dd
7 changed files with 222 additions and 3 deletions

67
source/toy_bytecode.c Normal file
View File

@@ -0,0 +1,67 @@
#include "toy_bytecode.h"
#include "toy_memory.h"
#include <stdio.h>
#include <string.h>
//utils
static void expand(Toy_Bytecode* bc, int amount) {
if (bc->count + amount > bc->capacity) {
int oldCapacity = bc->capacity;
bc->capacity = TOY_GROW_CAPACITY(oldCapacity);
bc->ptr = TOY_GROW_ARRAY(unsigned char, bc->ptr, oldCapacity, bc->capacity);
}
}
static void emitByte(Toy_Bytecode* bc, unsigned char byte) {
expand(bc, 1);
bc->ptr[bc->count++] = byte;
}
static void writeModule(Toy_Bytecode* bc, Toy_Ast* ast) {
//
}
//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();
int len = (int)strlen(build) + 1;
expand(bc, len);
sprintf((char*)(bc->ptr + bc->count), "%.*s", len, build);
bc->count += len;
}
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
writeModule(bc, ast);
}
//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) {
TOY_FREE_ARRAY(unsigned char, bc.ptr, bc.capacity);
}

13
source/toy_bytecode.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include "toy_common.h"
#include "toy_ast.h"
typedef struct Toy_Bytecode {
unsigned char* ptr;
int capacity;
int count;
} Toy_Bytecode;
TOY_API Toy_Bytecode Toy_compileBytecode(Toy_Ast* ast);
TOY_API void Toy_freeBytecode(Toy_Bytecode bc);

View File

@@ -1,7 +1,7 @@
#include "toy_common.h"
//defined separately, as compilation can take several seconds, invalidating the comparisons of the given macros
static const char* build = __DATE__ " " __TIME__ ";incomplete dev branch";
static const char* build = __DATE__ " " __TIME__ ", Toy branch 'dev'";
const char* Toy_private_version_build() {
return build;

58
source/toy_routine.c Normal file
View File

@@ -0,0 +1,58 @@
#include "toy_routine.h"
#include "toy_memory.h"
#include <stdio.h>
#include <string.h>
//utils
static void expand(void** handle, int* capacity, int* count) {
if ((*count) +1 > (*capacity)) {
int oldCapacity = (*capacity);
(*capacity) = TOY_GROW_CAPACITY(oldCapacity);
(*handle) = TOY_GROW_ARRAY(unsigned char, (*handle), oldCapacity, (*capacity));
}
}
static void emitByte(void** handle, int* capacity, int* count, unsigned char byte) {
expand(handle, capacity, count);
((unsigned char*)(*handle))[(*count)++] = byte;
}
//routine
//TODO
//exposed functions
Toy_Routine Toy_compileRoutine(Toy_Ast* ast) {
//setup
Toy_Routine rt;
rt.param = NULL;
rt.paramCapacity = 0;
rt.paramCount = 0;
rt.code = NULL;
rt.codeCapacity = 0;
rt.codeCount = 0;
rt.data = NULL;
rt.dataCapacity = 0;
rt.dataCount = 0;
rt.jump = NULL;
rt.jumpCapacity = 0;
rt.jumpCount = 0;
//build
//TODO
return rt;
}
void freeRoutine(Toy_Routine rt) {
TOY_FREE_ARRAY(unsigned char, rt.param, rt.paramCapacity);
TOY_FREE_ARRAY(unsigned char, rt.code, rt.codeCapacity);
TOY_FREE_ARRAY(unsigned char, rt.data, rt.dataCapacity);
TOY_FREE_ARRAY(int, rt.jump, rt.jumpCapacity);
}

28
source/toy_routine.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "toy_common.h"
#include "toy_ast.h"
//routine - holds the individual parts of a compiled routine
typedef struct Toy_Routine {
unsigned char* param; //c-string params in sequence
int paramCapacity;
int paramCount;
unsigned char* code; //the instruction set
int codeCapacity;
int codeCount;
unsigned char* data; //{type,val} tuples of data
int dataCapacity;
int dataCount;
int* jump; //each 'jump' is the starting address of an element within 'data'
int jumpCapacity;
int jumpCount;
//TODO: duplicate the data and jumps for subroutines
} Toy_Routine;
TOY_API Toy_Routine Toy_compileRoutine(Toy_Ast* ast);
TOY_API void Toy_freeRoutine(Toy_Routine routine);