Function to bytecode, fix function calling

This commit is contained in:
2026-07-04 13:11:01 +10:00
parent 6385a726cf
commit 396a6d9a1b
3 changed files with 148 additions and 21 deletions

View File

@@ -31,8 +31,11 @@ static void printValue(GroundBytecodeValue* val) {
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
case GroundType_Function:
printf("<function>");
break;
default:
printf("<fixme>");
printf("<fixme opt=%d>", val->type.type);
break;
}
}
@@ -714,22 +717,22 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
Ground.Flags.error = true;
return CONTINUE;
}
} else {
free(function->closure->heap);
}
GroundBytecodeHeap newHeap = {
.capacity = heap->capacity,
.len = heap->len,
.heap = malloc(sizeof(GroundBytecodeValue) * heap->capacity)
};
function->closure->capacity = heap->capacity;
function->closure->len = heap->len;
function->closure->heap = malloc(sizeof(GroundBytecodeValue) * heap->capacity);
if (newHeap.heap == NULL) {
if (function->closure->heap == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
Ground.Flags.error = true;
return CONTINUE;
}
for (GroundSize i = 0; i < heap->len; i++) {
newHeap.heap[i] = Ground.Copy.BytecodeValue(&heap->heap[i]);
function->closure->heap[i] = Ground.Copy.BytecodeValue(&heap->heap[i]);
}
return CONTINUE;
@@ -768,12 +771,12 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
// load function arguments into the heap
for (GroundSize i = 0; i < function->args.count; i++) {
newHeap.heap[i] = Ground.Copy.BytecodeValue(HEAP_GET(heap, i + 1)); // +1 because arg 1 is where fn args start
newHeap.heap[i] = Ground.Copy.BytecodeValue(HEAP_GET(heap, instruction->args.at[i + 1]));
}
// function arguments are the first indexes, copy after
// function arguments are the first indexes, copy closure after
for (GroundSize i = function->args.count; i < newHeap.len; i++) {
newHeap.heap[i] = Ground.Copy.BytecodeValue(&function->closure->heap[i]);
newHeap.heap[i] = Ground.Copy.BytecodeValue(&function->closure->heap[i - function->args.count]);
}
// Now we run the thingy

View File

@@ -47,6 +47,97 @@ static GroundBytecodeValue readValue(FILE* f) {
v.as.String.len = len;
break;
}
case 5: {
v.type.type = GroundType_Function;
uint8_t isNative;
fread(&isNative, 1, 1, f);
v.as.Function.isNativeFunction = isNative ? true : false;
uint64_t argCount;
fread(&argCount, 8, 1, f);
v.as.Function.args.count = argCount;
v.as.Function.args.capacity = argCount;
if (argCount > 0) {
v.as.Function.args.at = malloc(sizeof(GroundFunctionArg) * argCount);
if (v.as.Function.args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
for (uint64_t i = 0; i < argCount; i++) {
uint64_t nameLen;
fread(&nameLen, 8, 1, f);
GroundIdentifier* id = malloc(sizeof(GroundIdentifier));
if (id == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
id->string = malloc(nameLen + 1);
if (id->string == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
if (nameLen > 0) {
fread(id->string, 1, nameLen, f);
}
id->string[nameLen] = '\0';
id->referenceCount = 1;
v.as.Function.args.at[i].as.id = id;
}
} else {
v.as.Function.args.at = NULL;
}
v.as.Function.program.ground = malloc(sizeof(GroundBytecodeProgram));
if (v.as.Function.program.ground == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
uint64_t instCount;
fread(&instCount, 8, 1, f);
if (instCount > 0) {
v.as.Function.program.ground->at = malloc(sizeof(GroundBytecodeInstruction) * instCount);
if (v.as.Function.program.ground->at == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
for (uint64_t i = 0; i < instCount; i++) {
uint8_t type;
fread(&type, 1, 1, f);
v.as.Function.program.ground->at[i].type = (enum GroundInstructionType)type;
uint64_t instArgCount;
fread(&instArgCount, 8, 1, f);
if (instArgCount > 0) {
v.as.Function.program.ground->at[i].args.at = malloc(sizeof(GroundSize) * instArgCount);
if (v.as.Function.program.ground->at[i].args.at == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.load");
Ground.Flags.error = true;
return v;
}
fread(v.as.Function.program.ground->at[i].args.at, sizeof(GroundSize), instArgCount, f);
} else {
v.as.Function.program.ground->at[i].args.at = NULL;
}
v.as.Function.program.ground->at[i].args.len = instArgCount;
v.as.Function.program.ground->at[i].args.capacity = instArgCount;
}
v.as.Function.program.ground->len = instCount;
v.as.Function.program.ground->capacity = instCount;
} else {
v.as.Function.program.ground->at = NULL;
v.as.Function.program.ground->len = 0;
v.as.Function.program.ground->capacity = 0;
}
v.as.Function.closure = NULL;
break;
}
default: {
Ground.Log.Error("unknown value type in Ground.Bytecode.load");
Ground.Flags.error = true;

View File

@@ -1,5 +1,20 @@
#include "../../include/ground.h"
#include <stdio.h>
#include <string.h>
static void writeProgram(FILE* f, GroundBytecodeProgram* program) {
uint64_t count = program->len;
fwrite(&count, 8, 1, f);
for (GroundSize i = 0; i < count; i++) {
uint8_t type = (uint8_t)program->at[i].type;
fwrite(&type, 1, 1, f);
uint64_t argCount = program->at[i].args.len;
fwrite(&argCount, 8, 1, f);
if (argCount > 0) {
fwrite(program->at[i].args.at, sizeof(GroundSize), argCount, f);
}
}
}
static void writeValue(FILE* f, GroundBytecodeValue* v) {
switch (v->type.type) {
@@ -35,6 +50,32 @@ static void writeValue(FILE* f, GroundBytecodeValue* v) {
fwrite(v->as.String.cstr, 1, len, f);
break;
}
case GroundType_Function: {
uint8_t tag = 5;
fwrite(&tag, 1, 1, f);
uint8_t isNative = v->as.Function.isNativeFunction ? 1 : 0;
fwrite(&isNative, 1, 1, f);
uint64_t argCount = v->as.Function.args.count;
fwrite(&argCount, 8, 1, f);
for (GroundSize i = 0; i < argCount; i++) {
char* name = v->as.Function.args.at[i].as.id != NULL
? v->as.Function.args.at[i].as.id->string : "";
uint64_t len = strlen(name);
fwrite(&len, 8, 1, f);
fwrite(name, 1, len, f);
}
if (!v->as.Function.isNativeFunction && v->as.Function.program.ground != NULL) {
writeProgram(f, v->as.Function.program.ground);
} else {
uint64_t zero = 0;
fwrite(&zero, 8, 1, f);
}
// closures are generated at runtime, not persisted
break;
}
default: {
uint8_t tag = 0xFF;
fwrite(&tag, 1, 1, f);
@@ -61,15 +102,7 @@ void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path) {
writeValue(f, &bytecode->heap.heap[i]);
}
count = bytecode->program.len;
fwrite(&count, 8, 1, f);
for (GroundSize i = 0; i < count; i++) {
uint8_t type = (uint8_t)bytecode->program.at[i].type;
fwrite(&type, 1, 1, f);
uint64_t argCount = bytecode->program.at[i].args.len;
fwrite(&argCount, 8, 1, f);
fwrite(bytecode->program.at[i].args.at, 8, argCount, f);
}
writeProgram(f, &bytecode->program);
fclose(f);
}