function calling works in theory (can't test yet)

This commit is contained in:
2026-07-03 15:14:41 +10:00
parent a06d3ba55d
commit ce483dacc2
6 changed files with 169 additions and 71 deletions

View File

@@ -9,6 +9,11 @@
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val))
#define CONTINUE (struct GroundExecutionResult) { _GER_CONTINUE }
#define JUMP(idx) (struct GroundExecutionResult) { .type = _GER_JUMP, .as.line = idx }
#define END(res) (struct GroundExecutionResult) { .type = _GER_END, .as.end = res }
#define RETURN(val) (struct GroundExecutionResult) { .type = _GER_RETURN, .as.value = val }
static void printValue(GroundBytecodeValue* val) {
switch (val->type.type) {
case GroundType_Int:
@@ -32,7 +37,7 @@ static void printValue(GroundBytecodeValue* val) {
}
}
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
static const void* jumpTable[] = {
&&IF, &&JUMP, &&END,
@@ -55,67 +60,67 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
IF: {
GroundBytecodeValue* cond = HEAP_GET(heap, instruction->args.at[0]);
if (cond->as.Bool) {
return instruction->args.at[1];
return JUMP(instruction->args.at[1]);
}
return -1;
return CONTINUE;
}
JUMP: {
return instruction->args.at[0];
return JUMP(instruction->args.at[0]);
}
END: {
return -2;
return END( HEAP_GET(heap, instruction->args.at[0])->as.Int );
}
INPUT: {
char* input = linenoise("");
HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input))));
free(input);
return -1;
return CONTINUE;
}
PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
printValue(HEAP_GET(heap, instruction->args.at[i]));
}
return -1;
return CONTINUE;
}
PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
printValue(HEAP_GET(heap, instruction->args.at[i]));
}
printf("\n");
return -1;
return CONTINUE;
}
SET: {
HEAP_SET(heap, instruction->args.at[0], *HEAP_GET(heap, instruction->args.at[1]));
return -1;
return CONTINUE;
}
GETTYPE: {
Ground.Log.Warning("GETTYPE is deprecated");
return -1;
return CONTINUE;
}
EXISTS: {
Ground.Log.Warning("EXISTS is deprecated");
return -1;
return CONTINUE;
}
SETLIST: {
return -1;
return CONTINUE;
}
SETLISTAT: {
return -1;
return CONTINUE;
}
GETLISTAT: {
return -1;
return CONTINUE;
}
GETLISTSIZE: {
return -1;
return CONTINUE;
}
LISTAPPEND: {
return -1;
return CONTINUE;
}
GETSTRSIZE: {
return -1;
return CONTINUE;
}
GETSTRCHARAT: {
return -1;
return CONTINUE;
}
ADD: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -186,7 +191,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
SUBTRACT: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -236,7 +241,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
MULTIPLY: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -286,7 +291,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
DIVIDE: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -336,7 +341,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
EQUAL: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -407,7 +412,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
INEQUAL: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -478,11 +483,11 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
NOT: {
HEAP_SET(heap, instruction->args.at[1], Ground.New.BytecodeValue(Ground.New.Value.Bool(!HEAP_GET(heap, instruction->args.at[0])->as.Bool)));
return -1;
return CONTINUE;
}
GREATER: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -529,7 +534,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
LESSER: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -576,7 +581,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break;
}
}
return -1;
return CONTINUE;
}
AND: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -585,7 +590,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool && right->as.Bool));
return -1;
return CONTINUE;
}
OR: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -594,7 +599,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool || right->as.Bool));
return -1;
return CONTINUE;
}
XOR: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -603,13 +608,13 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool != right->as.Bool));
return -1;
return CONTINUE;
}
NEG: {
return -1;
return CONTINUE;
}
SHIFT: {
return -1;
return CONTINUE;
}
STOI: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -624,7 +629,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
Ground.Log.Error("Failed converting string to double");
}
return -1;
return CONTINUE;
}
STOD: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -639,7 +644,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
Ground.Log.Error("Failed converting string to double");
}
return -1;
return CONTINUE;
}
ITOC: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -647,7 +652,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*final = Ground.New.BytecodeValue(Ground.New.Value.Char((char)in->as.Int));
return -1;
return CONTINUE;
}
CTOI: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -655,7 +660,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*final = Ground.New.BytecodeValue(Ground.New.Value.Int((int64_t)in->as.Char));
return -1;
return CONTINUE;
}
TOSTRING: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -682,7 +687,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
}
case GroundType_String: {
*in = Ground.New.BytecodeValue(Ground.New.Value.String(final->as.String));
return -1;
return CONTINUE;
}
default: {
@@ -694,76 +699,120 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*in = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(buf)));
return -1;
return CONTINUE;
}
FUN: {
// no-op
return -1;
// make a copy of the current state and attach it to the function
GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
if (function->closure == NULL) {}
return CONTINUE;
}
RETURN: {
return -1;
return RETURN( *HEAP_GET(heap, instruction->args.at[0]) );
}
ENDFUN: {
// no-op
return -1;
return CONTINUE;
}
CALL: {
return -1;
// call !function $value... &returnIdx
GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
if (function->isNativeFunction) {
// TODO implement calling native functions
return CONTINUE;
}
if (function->closure == NULL) {
Ground.Log.Error("unexpected NULL closure in Ground.Bytecode.Instruction.execute");
Ground.Flags.error = true;
return CONTINUE;
}
// amount of captured variables + amount of function args
GroundSize heapSize = function->closure->len + function->args.count;
GroundBytecodeHeap newHeap = { malloc(sizeof(GroundBytecodeValue) * heapSize), heapSize, heapSize };
if (newHeap.heap == NULL) {
Ground.Log.Error("malloc failed in Ground.Bytecode.Instruction.execute");
Ground.Flags.error = true;
return CONTINUE;
}
// 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
}
// function arguments are the first indexes, copy after
for (GroundSize i = function->args.count; i < newHeap.len; i++) {
newHeap.heap[i] = Ground.Copy.BytecodeValue(&function->closure->heap[i]);
}
// Now we run the thingy
GroundBytecodeValue result = Ground.Bytecode.Program.execute(function->program.ground, &newHeap);
// And store the result
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], result);
return CONTINUE;
}
CALLMETHOD: {
return -1;
return CONTINUE;
}
STRUCT: {
// no-op
return -1;
return CONTINUE;
}
ENDSTRUCT: {
// no-op
return -1;
return CONTINUE;
}
INIT: {
return -1;
return CONTINUE;
}
GETFIELD: {
return -1;
return CONTINUE;
}
SETFIELD: {
return -1;
return CONTINUE;
}
USE: {
return -1;
return CONTINUE;
}
EXTERN: {
return -1;
return CONTINUE;
}
CREATELABEL: {
// no-op
return -1;
return CONTINUE;
}
PAUSE: {
return -1;
return CONTINUE;
}
DROP: {
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
Ground.Free.BytecodeValue(in);
*in = Ground.New.BytecodeValue(Ground.New.Value.Int(0));
return -1;
return CONTINUE;
}
LICENSE: {
return -1;
return CONTINUE;
}
ERRORCMD: {
return -1;
return CONTINUE;
}
THROW: {
return -1;
return CONTINUE;
}
CATCH: {
return -1;
return CONTINUE;
}
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
Ground.Flags.error = true;
return -1;
return CONTINUE;
}