Function to bytecode, fix function calling
This commit is contained in:
@@ -31,8 +31,11 @@ static void printValue(GroundBytecodeValue* val) {
|
|||||||
case GroundType_String:
|
case GroundType_String:
|
||||||
printf("%s", val->as.String.cstr);
|
printf("%s", val->as.String.cstr);
|
||||||
break;
|
break;
|
||||||
|
case GroundType_Function:
|
||||||
|
printf("<function>");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("<fixme>");
|
printf("<fixme opt=%d>", val->type.type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -714,22 +717,22 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
free(function->closure->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundBytecodeHeap newHeap = {
|
function->closure->capacity = heap->capacity;
|
||||||
.capacity = heap->capacity,
|
function->closure->len = heap->len;
|
||||||
.len = heap->len,
|
function->closure->heap = malloc(sizeof(GroundBytecodeValue) * heap->capacity);
|
||||||
.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.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
|
||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GroundSize i = 0; i < heap->len; i++) {
|
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;
|
return CONTINUE;
|
||||||
@@ -766,14 +769,14 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load function arguments into the heap
|
// load function arguments into the heap
|
||||||
for (GroundSize i = 0; i < function->args.count; i++) {
|
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++) {
|
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
|
// Now we run the thingy
|
||||||
|
|||||||
@@ -47,6 +47,97 @@ static GroundBytecodeValue readValue(FILE* f) {
|
|||||||
v.as.String.len = len;
|
v.as.String.len = len;
|
||||||
break;
|
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: {
|
default: {
|
||||||
Ground.Log.Error("unknown value type in Ground.Bytecode.load");
|
Ground.Log.Error("unknown value type in Ground.Bytecode.load");
|
||||||
Ground.Flags.error = true;
|
Ground.Flags.error = true;
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
#include "../../include/ground.h"
|
#include "../../include/ground.h"
|
||||||
#include <stdio.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) {
|
static void writeValue(FILE* f, GroundBytecodeValue* v) {
|
||||||
switch (v->type.type) {
|
switch (v->type.type) {
|
||||||
@@ -35,6 +50,32 @@ static void writeValue(FILE* f, GroundBytecodeValue* v) {
|
|||||||
fwrite(v->as.String.cstr, 1, len, f);
|
fwrite(v->as.String.cstr, 1, len, f);
|
||||||
break;
|
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: {
|
default: {
|
||||||
uint8_t tag = 0xFF;
|
uint8_t tag = 0xFF;
|
||||||
fwrite(&tag, 1, 1, f);
|
fwrite(&tag, 1, 1, f);
|
||||||
@@ -61,15 +102,7 @@ void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path) {
|
|||||||
writeValue(f, &bytecode->heap.heap[i]);
|
writeValue(f, &bytecode->heap.heap[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
count = bytecode->program.len;
|
writeProgram(f, &bytecode->program);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user