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

@@ -336,6 +336,23 @@ struct GroundBytecode {
GroundBytecodeHeap heap; GroundBytecodeHeap heap;
}; };
// --- Internal Ground components, avoid use outside of Ground ---
enum GroundExecutionResultType {
_GER_CONTINUE, _GER_JUMP, _GER_RETURN, _GER_END
};
struct GroundExecutionResult {
enum GroundExecutionResultType type;
union {
GroundBytecodeValue value;
GroundSize line;
GroundInt end;
} as;
};
// //
// INTERFACE // INTERFACE
// //
@@ -428,6 +445,8 @@ struct _Ground {
GroundState (*State) (GroundState* in); GroundState (*State) (GroundState* in);
GroundIdentifier* (*Identifier) (GroundIdentifier* in); GroundIdentifier* (*Identifier) (GroundIdentifier* in);
GroundBytecodeValue (*BytecodeValue) (GroundBytecodeValue* in);
} Copy; } Copy;
struct { struct {
@@ -481,11 +500,11 @@ struct _Ground {
void (*save) (GroundBytecode* bytecode, const char* path); void (*save) (GroundBytecode* bytecode, const char* path);
GroundBytecode (*load) (const char* path); GroundBytecode (*load) (const char* path);
struct { struct {
void (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap); GroundBytecodeValue (*execute) (GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
void (*optimise) (GroundBytecodeProgram* program); void (*optimise) (GroundBytecodeProgram* program);
} Program; } Program;
struct { struct {
int64_t (*execute) (GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap); struct GroundExecutionResult (*execute) (GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
} Instruction; } Instruction;
struct { struct {
void (*set) (GroundBytecodeHeap* heap, GroundSize idx, GroundValue value); void (*set) (GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);

View File

@@ -25,6 +25,8 @@ sources = files(
'src/Copy/Identifier.c', 'src/Copy/Identifier.c',
'src/Copy/BytecodeValue.c',
'src/Free/Function.c', 'src/Free/Function.c',
'src/Free/List.c', 'src/Free/List.c',
'src/Free/Object.c', 'src/Free/Object.c',

View File

@@ -9,6 +9,11 @@
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)]) #define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val)) #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) { static void printValue(GroundBytecodeValue* val) {
switch (val->type.type) { switch (val->type.type) {
case GroundType_Int: 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[] = { static const void* jumpTable[] = {
&&IF, &&JUMP, &&END, &&IF, &&JUMP, &&END,
@@ -55,67 +60,67 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
IF: { IF: {
GroundBytecodeValue* cond = HEAP_GET(heap, instruction->args.at[0]); GroundBytecodeValue* cond = HEAP_GET(heap, instruction->args.at[0]);
if (cond->as.Bool) { if (cond->as.Bool) {
return instruction->args.at[1]; return JUMP(instruction->args.at[1]);
} }
return -1; return CONTINUE;
} }
JUMP: { JUMP: {
return instruction->args.at[0]; return JUMP(instruction->args.at[0]);
} }
END: { END: {
return -2; return END( HEAP_GET(heap, instruction->args.at[0])->as.Int );
} }
INPUT: { INPUT: {
char* input = linenoise(""); char* input = linenoise("");
HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input)))); HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input))));
free(input); free(input);
return -1; return CONTINUE;
} }
PRINT: { PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
printValue(HEAP_GET(heap, instruction->args.at[i])); printValue(HEAP_GET(heap, instruction->args.at[i]));
} }
return -1; return CONTINUE;
} }
PRINTLN: { PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) { for (GroundSize i = 0; i < instruction->args.len; i++) {
printValue(HEAP_GET(heap, instruction->args.at[i])); printValue(HEAP_GET(heap, instruction->args.at[i]));
} }
printf("\n"); printf("\n");
return -1; return CONTINUE;
} }
SET: { SET: {
HEAP_SET(heap, instruction->args.at[0], *HEAP_GET(heap, instruction->args.at[1])); HEAP_SET(heap, instruction->args.at[0], *HEAP_GET(heap, instruction->args.at[1]));
return -1; return CONTINUE;
} }
GETTYPE: { GETTYPE: {
Ground.Log.Warning("GETTYPE is deprecated"); Ground.Log.Warning("GETTYPE is deprecated");
return -1; return CONTINUE;
} }
EXISTS: { EXISTS: {
Ground.Log.Warning("EXISTS is deprecated"); Ground.Log.Warning("EXISTS is deprecated");
return -1; return CONTINUE;
} }
SETLIST: { SETLIST: {
return -1; return CONTINUE;
} }
SETLISTAT: { SETLISTAT: {
return -1; return CONTINUE;
} }
GETLISTAT: { GETLISTAT: {
return -1; return CONTINUE;
} }
GETLISTSIZE: { GETLISTSIZE: {
return -1; return CONTINUE;
} }
LISTAPPEND: { LISTAPPEND: {
return -1; return CONTINUE;
} }
GETSTRSIZE: { GETSTRSIZE: {
return -1; return CONTINUE;
} }
GETSTRCHARAT: { GETSTRCHARAT: {
return -1; return CONTINUE;
} }
ADD: { ADD: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -186,7 +191,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
SUBTRACT: { SUBTRACT: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -236,7 +241,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
MULTIPLY: { MULTIPLY: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -286,7 +291,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
DIVIDE: { DIVIDE: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -336,7 +341,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
EQUAL: { EQUAL: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -407,7 +412,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
INEQUAL: { INEQUAL: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -478,11 +483,11 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
NOT: { NOT: {
HEAP_SET(heap, instruction->args.at[1], Ground.New.BytecodeValue(Ground.New.Value.Bool(!HEAP_GET(heap, instruction->args.at[0])->as.Bool))); 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: { GREATER: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -529,7 +534,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
LESSER: { LESSER: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
@@ -576,7 +581,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
break; break;
} }
} }
return -1; return CONTINUE;
} }
AND: { AND: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); 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)); *final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool && right->as.Bool));
return -1; return CONTINUE;
} }
OR: { OR: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); 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)); *final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool || right->as.Bool));
return -1; return CONTINUE;
} }
XOR: { XOR: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]); 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)); *final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool != right->as.Bool));
return -1; return CONTINUE;
} }
NEG: { NEG: {
return -1; return CONTINUE;
} }
SHIFT: { SHIFT: {
return -1; return CONTINUE;
} }
STOI: { STOI: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]); 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"); Ground.Log.Error("Failed converting string to double");
} }
return -1; return CONTINUE;
} }
STOD: { STOD: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]); 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"); Ground.Log.Error("Failed converting string to double");
} }
return -1; return CONTINUE;
} }
ITOC: { ITOC: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]); 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)); *final = Ground.New.BytecodeValue(Ground.New.Value.Char((char)in->as.Int));
return -1; return CONTINUE;
} }
CTOI: { CTOI: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]); 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)); *final = Ground.New.BytecodeValue(Ground.New.Value.Int((int64_t)in->as.Char));
return -1; return CONTINUE;
} }
TOSTRING: { TOSTRING: {
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]); GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
@@ -682,7 +687,7 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
} }
case GroundType_String: { case GroundType_String: {
*in = Ground.New.BytecodeValue(Ground.New.Value.String(final->as.String)); *in = Ground.New.BytecodeValue(Ground.New.Value.String(final->as.String));
return -1; return CONTINUE;
} }
default: { default: {
@@ -694,76 +699,120 @@ int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction
*in = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(buf))); *in = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(buf)));
return -1; return CONTINUE;
} }
FUN: { FUN: {
// no-op // make a copy of the current state and attach it to the function
return -1; GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
if (function->closure == NULL) {}
return CONTINUE;
} }
RETURN: { RETURN: {
return -1; return RETURN( *HEAP_GET(heap, instruction->args.at[0]) );
} }
ENDFUN: { ENDFUN: {
// no-op // no-op
return -1; return CONTINUE;
} }
CALL: { 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: { CALLMETHOD: {
return -1; return CONTINUE;
} }
STRUCT: { STRUCT: {
// no-op // no-op
return -1; return CONTINUE;
} }
ENDSTRUCT: { ENDSTRUCT: {
// no-op // no-op
return -1; return CONTINUE;
} }
INIT: { INIT: {
return -1; return CONTINUE;
} }
GETFIELD: { GETFIELD: {
return -1; return CONTINUE;
} }
SETFIELD: { SETFIELD: {
return -1; return CONTINUE;
} }
USE: { USE: {
return -1; return CONTINUE;
} }
EXTERN: { EXTERN: {
return -1; return CONTINUE;
} }
CREATELABEL: { CREATELABEL: {
// no-op // no-op
return -1; return CONTINUE;
} }
PAUSE: { PAUSE: {
return -1; return CONTINUE;
} }
DROP: { DROP: {
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]); GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
Ground.Free.BytecodeValue(in); Ground.Free.BytecodeValue(in);
*in = Ground.New.BytecodeValue(Ground.New.Value.Int(0)); *in = Ground.New.BytecodeValue(Ground.New.Value.Int(0));
return -1; return CONTINUE;
} }
LICENSE: { LICENSE: {
return -1; return CONTINUE;
} }
ERRORCMD: { ERRORCMD: {
return -1; return CONTINUE;
} }
THROW: { THROW: {
return -1; return CONTINUE;
} }
CATCH: { CATCH: {
return -1; return CONTINUE;
} }
Ground.Log.Error("operation fell through in Ground.Instruction.execute()"); Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
Ground.Flags.error = true; Ground.Flags.error = true;
return -1; return CONTINUE;
} }

View File

@@ -1,18 +1,22 @@
#include "../../../include/ground.h" #include "../../../include/ground.h"
#include <stdint.h> #include <stdint.h>
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) { GroundBytecodeValue _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) {
GroundSize i = 0; GroundSize i = 0;
while (i < program->len) { while (i < program->len) {
int64_t status = Ground.Bytecode.Instruction.execute(&program->at[i], heap); struct GroundExecutionResult status = Ground.Bytecode.Instruction.execute(&program->at[i], heap);
if (Ground.Flags.error) { if (Ground.Flags.error) {
return; return Ground.New.BytecodeValue(Ground.New.Value.Int(1));
} }
switch (status) { switch (status.type) {
case -1: i++; break;
case -2: return; case _GER_CONTINUE: i++; break;
default: i = status; break; case _GER_RETURN: return status.as.value;
case _GER_JUMP: i = status.as.line; break;
case _GER_END: exit(status.as.end);
} }
} }
return Ground.New.BytecodeValue(Ground.New.Value.Int(0));
} }

22
src/Copy/BytecodeValue.c Normal file
View File

@@ -0,0 +1,22 @@
#include "../../include/ground.h"
GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value) {
GroundBytecodeValue newValue = *value;
switch (value->type.type) {
case GroundType_Int:
case GroundType_Double:
case GroundType_Bool:
case GroundType_Char:
break;
case GroundType_String: {
newValue.as.String = Ground.Copy.String(&value->as.String);
break;
}
// TODO: Implement copying for everything else
default: break;
}
return newValue;
}

View File

@@ -66,6 +66,8 @@ GroundState _GroundCopyState(GroundState* in);
GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier); GroundIdentifier* _GroundCopyIdentifier(GroundIdentifier* identifier);
GroundBytecodeValue _GroundCopyBytecodeValue(GroundBytecodeValue* value);
void _GroundListAppend(GroundList* list, GroundValue value); void _GroundListAppend(GroundList* list, GroundValue value);
@@ -99,10 +101,10 @@ void _GroundLogWarning(const char* message);
void _GroundLogPrintErrors(); void _GroundLogPrintErrors();
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap); GroundBytecodeValue _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program); void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program);
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap); struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path); void _GroundBytecodeSave(GroundBytecode* bytecode, const char* path);
GroundBytecode _GroundBytecodeLoad(const char* path); GroundBytecode _GroundBytecodeLoad(const char* path);