Function to bytecode, fix function calling
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user