Functions are written, but not yet executed, untested

This commit is contained in:
2025-02-10 20:17:53 +11:00
parent 344c265918
commit 7a8c415b3f
2 changed files with 104 additions and 50 deletions

View File

@@ -1,17 +1,5 @@
fn name() {
//return 42;
}
fn name(param1: int, param2: float, param3: string, param4) {
//return 42;
}
fn name(foobar: bool const) { fn name(foobar: bool const) {
//return 42; //return 42;
} }

View File

@@ -89,6 +89,12 @@ static void emitFloat(unsigned char** handle, unsigned int* capacity, unsigned i
emitByte(handle, capacity, count, *(ptr++)); emitByte(handle, capacity, count, *(ptr++));
} }
static void emitBuffer(unsigned char** handle, unsigned int* capacity, unsigned int* count, unsigned char* buffer, unsigned int bufferSize) {
expand(handle, capacity, count, bufferSize); //4-byte aligned
memcpy((*handle) + *count, buffer, bufferSize);
*count += bufferSize;
}
//curry writing utils //curry writing utils
#define EMIT_BYTE(mb, part, byte) \ #define EMIT_BYTE(mb, part, byte) \
emitByte((&((*mb)->part)), &((*mb)->part##Capacity), &((*mb)->part##Count), byte) emitByte((&((*mb)->part)), &((*mb)->part##Capacity), &((*mb)->part##Count), byte)
@@ -137,10 +143,6 @@ static unsigned int emitCStringToData(unsigned char** dataHandle, unsigned int*
} }
static unsigned int emitString(Toy_ModuleCompiler** mb, Toy_String* str) { static unsigned int emitString(Toy_ModuleCompiler** mb, Toy_String* str) {
//4-byte alignment
unsigned int length = str->info.length + 1;
length = (length + 3) & ~3;
//the address within the data section //the address within the data section
unsigned int dataAddr = 0; unsigned int dataAddr = 0;
@@ -174,11 +176,53 @@ static unsigned int emitString(Toy_ModuleCompiler** mb, Toy_String* str) {
return 1; return 1;
} }
// static unsigned int emitParameter(Toy_ModuleCompiler** mb, Toy_String* str) { static unsigned int emitParameters(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
// //recursive checks
// } if (ast == NULL) {
return 0;
}
else if (ast->type == TOY_AST_AGGREGATE) {
unsigned int total = 0;
total += emitParameters(mb, ast->aggregate.left);
total += emitParameters(mb, ast->aggregate.right);
return total;
}
else if (ast->type != TOY_AST_VALUE) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown AST type passed to 'emitParameters()'\n" TOY_CC_RESET);
exit(-1);
return 0;
}
//check the string type
if (TOY_VALUE_IS_STRING(ast->value.value) == false || TOY_VALUE_AS_STRING(ast->value.value)->info.type != TOY_STRING_NAME) {
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Function parameters must be name strings\n" TOY_CC_RESET);
mb->panic = true;
return 0;
}
//the address within the data section
unsigned int dataAddr = emitCStringToData(&(mb->data), &(mb->dataCapacity), &(mb->dataCount), TOY_VALUE_AS_STRING(ast->value.value)->name.data);
//check the param index for that entry i.e. don't reuse parameter names
for (unsigned int i = 0; i < mb->paramCount; i++) {
if (mb->param[i] == dataAddr) {
//not allowed
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Function parameters must have unique names\n" TOY_CC_RESET);
mb->panic = true;
return 0;
}
}
//emit to the param index
EMIT_INT(&mb, param, dataAddr);
//this returns the number of written parameters
return 1;
}
static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* ast); //forward declare for recursion static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* ast); //forward declare for recursion
static void writeModuleCompilerBody(Toy_ModuleCompiler* mb, Toy_Ast* ast);
static unsigned char* writeModuleCompilerResult(Toy_ModuleCompiler* mb);
static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAssign ast, bool chainedAssignment); //forward declare for chaining of var declarations static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAssign ast, bool chainedAssignment); //forward declare for chaining of var declarations
static unsigned int writeInstructionValue(Toy_ModuleCompiler** mb, Toy_AstValue ast) { static unsigned int writeInstructionValue(Toy_ModuleCompiler** mb, Toy_AstValue ast) {
@@ -909,7 +953,8 @@ static unsigned int writeInstructionAssign(Toy_ModuleCompiler** mb, Toy_AstVarAs
static unsigned int writeInstructionAccess(Toy_ModuleCompiler** mb, Toy_AstVarAccess ast) { static unsigned int writeInstructionAccess(Toy_ModuleCompiler** mb, Toy_AstVarAccess ast) {
if (!(ast.child->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.child->value.value) && TOY_VALUE_AS_STRING(ast.child->value.value)->info.type == TOY_STRING_NAME)) { if (!(ast.child->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.child->value.value) && TOY_VALUE_AS_STRING(ast.child->value.value)->info.type == TOY_STRING_NAME)) {
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Found a non-name-string in a value node when trying to write access\n" TOY_CC_RESET); fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: Found a non-name-string in a value node when trying to write access\n" TOY_CC_RESET);
exit(-1); (*mb)->panic = true;
return 0;
} }
Toy_String* name = TOY_VALUE_AS_STRING(ast.child->value.value); Toy_String* name = TOY_VALUE_AS_STRING(ast.child->value.value);
@@ -950,9 +995,49 @@ static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFn
.right->value.value.as.string.name (param4: any) .right->value.value.as.string.name (param4: any)
*/ */
//URGENT: currently a no-op //generate the submodule
(void)mb; Toy_ModuleCompiler compiler = { 0 };
(void)ast;
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
//compile the ast to memory
unsigned int paramCount = emitParameters(&compiler, ast.params);
writeModuleCompilerBody(&compiler, ast.body);
unsigned char* submodule = writeModuleCompilerResult(&compiler);
//cleanup the compiler
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);
Toy_private_resizeEscapeArray(compiler.continueEscapes, 0);
free(compiler.param);
free(compiler.code);
free(compiler.jumps);
free(compiler.data);
free(compiler.subs);
//write the submodule to the subs section
unsigned int subsAddr = (*mb)->subsCount;
emitBuffer(&((*mb)->subs), &((*mb)->subsCapacity), &((*mb)->subsCount), submodule, *((unsigned int*)submodule));
free(submodule);
//read the function as a value, with the address as a parameter
EMIT_BYTE(mb, code, TOY_OPCODE_READ);
EMIT_BYTE(mb, code, TOY_VALUE_FUNCTION);
EMIT_BYTE(mb, code, (unsigned char)paramCount);
EMIT_BYTE(mb, code, 0);
EMIT_INT(mb, code, subsAddr);
//delcare the function
EMIT_BYTE(mb, code, TOY_OPCODE_DECLARE);
EMIT_BYTE(mb, code, TOY_VALUE_FUNCTION);
EMIT_BYTE(mb, code, ast.name->info.length); //quick optimisation to skip a 'strlen()' call
EMIT_BYTE(mb, code, true); //functions are const for now
//time to write to the actual function name
emitString(mb, ast.name);
return 0; return 0;
} }
@@ -1085,15 +1170,18 @@ static unsigned int writeModuleCompilerCode(Toy_ModuleCompiler** mb, Toy_Ast* as
return result; return result;
} }
static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) { static void writeModuleCompilerBody(Toy_ModuleCompiler* mb, Toy_Ast* ast) {
//code //this is separated from 'writeModuleCompilerResult', to separate the concerns for modules & functions
writeModuleCompilerCode(&mb, ast); writeModuleCompilerCode(&mb, ast);
EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator EMIT_BYTE(&mb, code, TOY_OPCODE_RETURN); //end terminator
EMIT_BYTE(&mb, code, 0); //4-byte alignment EMIT_BYTE(&mb, code, 0); //4-byte alignment
EMIT_BYTE(&mb, code, 0); EMIT_BYTE(&mb, code, 0);
EMIT_BYTE(&mb, code, 0); EMIT_BYTE(&mb, code, 0);
}
static unsigned char* writeModuleCompilerResult(Toy_ModuleCompiler* mb) {
//if an error occurred, just exit //if an error occurred, just exit
if (mb->panic) { if (mb->panic) {
return NULL; return NULL;
@@ -1186,36 +1274,14 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast)
//exposed functions //exposed functions
unsigned char* Toy_compileModule(Toy_Ast* ast) { unsigned char* Toy_compileModule(Toy_Ast* ast) {
//setup //setup
Toy_ModuleCompiler compiler; Toy_ModuleCompiler compiler = { 0 };
compiler.code = NULL;
compiler.codeCapacity = 0;
compiler.codeCount = 0;
compiler.jumps = NULL;
compiler.jumpsCapacity = 0;
compiler.jumpsCount = 0;
compiler.param = NULL;
compiler.paramCapacity = 0;
compiler.paramCount = 0;
compiler.data = NULL;
compiler.dataCapacity = 0;
compiler.dataCount = 0;
compiler.subs = NULL;
compiler.subsCapacity = 0;
compiler.subsCount = 0;
compiler.currentScopeDepth = 0;
compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY); compiler.breakEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY); compiler.continueEscapes = Toy_private_resizeEscapeArray(NULL, TOY_ESCAPE_INITIAL_CAPACITY);
compiler.panic = false;
//compile the ast to memory //compile the ast to memory
unsigned char* buffer = writeModuleCompiler(&compiler, ast); writeModuleCompilerBody(&compiler, ast);
unsigned char* buffer = writeModuleCompilerResult(&compiler);
//cleanup //cleanup
Toy_private_resizeEscapeArray(compiler.breakEscapes, 0); Toy_private_resizeEscapeArray(compiler.breakEscapes, 0);