This commit is contained in:
2026-06-21 14:35:48 +10:00
parent f97cec4567
commit ff98aa63b4
11 changed files with 903 additions and 760 deletions

5
src/Bytecode/Heap/get.c Normal file
View File

@@ -0,0 +1,5 @@
#include "../../../include/ground.h"
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx) {
return &heap->heap[idx];
}

5
src/Bytecode/Heap/set.c Normal file
View File

@@ -0,0 +1,5 @@
#include "../../../include/ground.h"
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value) {
heap->heap[idx] = value;
}

View File

@@ -0,0 +1,600 @@
#include "../../../include/ground.h"
#include <stdint.h>
#include <inttypes.h>
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
static const void* jumpTable[] = {
&&IF, &&JUMP, &&END,
&&INPUT, &&PRINT, &&PRINTLN,
&&SET, &&GETTYPE, &&EXISTS,
&&SETLIST, &&SETLISTAT, &&GETLISTAT, &&GETLISTSIZE, &&LISTAPPEND,
&&GETSTRSIZE, &&GETSTRCHARAT,
&&ADD, &&SUBTRACT, &&MULTIPLY, &&DIVIDE,
&&EQUAL, &&INEQUAL, &&NOT, &&GREATER, &&LESSER,
&&AND, &&OR, &&XOR, &&NEG, &&SHIFT,
&&STOI, &&STOD, &&ITOC, &&CTOI, &&TOSTRING,
&&FUN, &&RETURN, &&ENDFUN, &&CALL, &&CALLMETHOD,
&&STRUCT, &&ENDSTRUCT, &&INIT, &&GETFIELD, &&SETFIELD,
&&USE, &&EXTERN, &&CREATELABEL,
&&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
};
// Jump to the spot
goto *jumpTable[instruction->type];
IF: {
return -1;
}
JUMP: {
return -1;
}
END: {
return -2;
}
INPUT: {
return -1;
}
PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]);
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
}
return -1;
}
PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = Ground.Bytecode.Heap.get(heap, instruction->args.at[i]);
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
}
printf("\n");
return -1;
}
SET: {
Ground.Bytecode.Heap.set(heap, instruction->args.at[0], *Ground.Bytecode.Heap.get(heap, instruction->args.at[1]));
return -1;
}
GETTYPE: {
Ground.Log.Warning("GETTYPE is deprecated");
return -1;
}
EXISTS: {
Ground.Log.Warning("EXISTS is deprecated");
return -1;
}
SETLIST: {
return -1;
}
SETLISTAT: {
return -1;
}
GETLISTAT: {
return -1;
}
GETLISTSIZE: {
return -1;
}
LISTAPPEND: {
return -1;
}
GETSTRSIZE: {
return -1;
}
GETSTRCHARAT: {
return -1;
}
ADD: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int + right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int + right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double + right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double + right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_String: {
switch (right->type.type) {
case GroundType_String: {
char* buf = malloc(sizeof(char) * (left->as.String.len + right->as.String.len + 1));
if (buf == NULL) {
Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
sprintf(buf, "%s%s", left->as.String.cstr, right->as.String.cstr);
*final = Ground.New.Value.String(Ground.New.String(buf));
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
SUBTRACT: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int - right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int - right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double - right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double - right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
MULTIPLY: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int * right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int * right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double * right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double * right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
DIVIDE: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int / right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int / right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double / right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double / right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
EQUAL: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Int == right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Int == right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(false);
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Double == right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Double == right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(false);
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
*final = Ground.New.Value.Bool(left->as.Char == right->as.Char);
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
*final = Ground.New.Value.Bool(left->as.Bool == right->as.Bool);
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr));
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false);
break;
}
}
return -1;
}
INEQUAL: {
GroundValue* final = Ground.Bytecode.Heap.get(heap, instruction->args.at[2]);
GroundValue* left = Ground.Bytecode.Heap.get(heap, instruction->args.at[0]);
GroundValue* right = Ground.Bytecode.Heap.get(heap, instruction->args.at[1]);
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Int != right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Int != right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(true);
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Double != right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Double != right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(true);
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
*final = Ground.New.Value.Bool(left->as.Char != right->as.Char);
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
*final = Ground.New.Value.Bool(left->as.Bool != right->as.Bool);
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(!strcmp(left->as.String.cstr, right->as.String.cstr));
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false);
break;
}
}
return -1;
}
NOT: {
Ground.Bytecode.Heap.set(heap, instruction->args.at[1], Ground.New.Value.Bool(!Ground.Bytecode.Heap.get(heap, instruction->args.at[0])->as.Bool));
return -1;
}
GREATER: {
return -1;
}
LESSER: {
return -1;
}
AND: {
return -1;
}
OR: {
return -1;
}
XOR: {
return -1;
}
NEG: {
return -1;
}
SHIFT: {
return -1;
}
STOI: {
return -1;
}
STOD: {
return -1;
}
ITOC: {
return -1;
}
CTOI: {
return -1;
}
TOSTRING: {
return -1;
}
FUN: {
return -1;
}
RETURN: {
return -1;
}
ENDFUN: {
return -1;
}
CALL: {
return -1;
}
CALLMETHOD: {
return -1;
}
STRUCT: {
return -1;
}
ENDSTRUCT: {
return -1;
}
INIT: {
return -1;
}
GETFIELD: {
return -1;
}
SETFIELD: {
return -1;
}
USE: {
return -1;
}
EXTERN: {
return -1;
}
CREATELABEL: {
return -1;
}
PAUSE: {
return -1;
}
DROP: {
return -1;
}
LICENSE: {
return -1;
}
ERRORCMD: {
return -1;
}
THROW: {
return -1;
}
CATCH: {
return -1;
}
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
Ground.Flags.error = true;
return -1;
}

View File

@@ -0,0 +1,17 @@
#include "../../../include/ground.h"
#include <stdint.h>
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) {
for (GroundSize i = 0; i < program->len; i++) {
int64_t status = Ground.Bytecode.Instruction.execute(&program->at[i], heap);
if (Ground.Flags.error) {
return;
}
switch (status) {
case -1: break;
case -2: return;
default: i = status; break;
}
}
}

View File

@@ -0,0 +1,5 @@
#include "../../../include/ground.h"
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program) {
// TODO: Implement optimisation
}

View File

@@ -11,617 +11,5 @@
*/
int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* heap) {
static const void* jumpTable[] = {
&&IF, &&JUMP, &&END,
&&INPUT, &&PRINT, &&PRINTLN,
&&SET, &&GETTYPE, &&EXISTS,
&&SETLIST, &&SETLISTAT, &&GETLISTAT, &&GETLISTSIZE, &&LISTAPPEND,
&&GETSTRSIZE, &&GETSTRCHARAT,
&&ADD, &&SUBTRACT, &&MULTIPLY, &&DIVIDE,
&&EQUAL, &&INEQUAL, &&NOT, &&GREATER, &&LESSER,
&&AND, &&OR, &&XOR, &&NEG, &&SHIFT,
&&STOI, &&STOD, &&ITOC, &&CTOI, &&TOSTRING,
&&FUN, &&RETURN, &&ENDFUN, &&CALL, &&CALLMETHOD,
&&STRUCT, &&ENDSTRUCT, &&INIT, &&GETFIELD, &&SETFIELD,
&&USE, &&EXTERN, &&CREATELABEL,
&&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
};
// Preprocess any ValueRefs
for (GroundSize i = 0; i < instruction->args.len; i++) {
if (instruction->args.at[i].type == GroundArg_ValueRef) {
GroundSize offset = instruction->args.at[i]._offset;
instruction->args.at[i] = Ground.New.Arg.Value(heap[offset]);
}
}
// Jump to the spot
goto *jumpTable[instruction->type];
IF: {
if (instruction->args.at[0].as.value.as.Bool) {
return instruction->args.at[1]._offset;
}
return -1;
}
JUMP: {
return instruction->args.at[0]._offset;
}
END: {
return -2;
}
INPUT: {
char input[2048];
fgets(input, sizeof(input) - 1, stdin);
input[2047] = '\0';
GroundString string = Ground.New.String(input);
GroundValue value = Ground.New.Value.String(string);
heap[instruction->args.at[0]._offset] = value;
return -1;
}
PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = &instruction->args.at[i].as.value;
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
}
return -1;
}
PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
GroundValue* val = &instruction->args.at[i].as.value;
switch (val->type.type) {
case GroundType_Int:
printf("%" PRId64, val->as.Int);
break;
case GroundType_Double:
printf("%f", val->as.Double);
break;
case GroundType_Bool:
printf(val->as.Bool ? "true" : "false");
break;
case GroundType_Char:
printf("%c", val->as.Char);
break;
case GroundType_String:
printf("%s", val->as.String.cstr);
break;
default:
printf("<fixme>");
break;
}
}
printf("\n");
return -1;
}
SET: {
GroundSize offset = instruction->args.at[0]._offset;
heap[offset] = instruction->args.at[1].as.value;
return -1;
}
GETTYPE: {
Ground.Log.Warning("GETTYPE is deprecated");
return -1;
}
EXISTS: {
Ground.Log.Warning("EXISTS is deprecated");
return -1;
}
SETLIST: {
return -1;
}
SETLISTAT: {
return -1;
}
GETLISTAT: {
return -1;
}
GETLISTSIZE: {
return -1;
}
LISTAPPEND: {
return -1;
}
GETSTRSIZE: {
return -1;
}
GETSTRCHARAT: {
return -1;
}
ADD: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int + right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int + right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double + right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double + right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_String: {
switch (right->type.type) {
case GroundType_String: {
char* buf = malloc(sizeof(char) * (left->as.String.len + right->as.String.len + 1));
if (buf == NULL) {
Ground.Log.Error("malloc failed (instruction ADD{string, string, dirref}) in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
sprintf(buf, "%s%s", left->as.String.cstr, right->as.String.cstr);
*final = Ground.New.Value.String(Ground.New.String(buf));
break;
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
}
default: {
Ground.Log.Error("invalid add operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
SUBTRACT: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int - right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int - right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double - right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double - right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
MULTIPLY: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int * right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int * right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double * right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double * right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
DIVIDE: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Int(left->as.Int / right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Int / right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Double(left->as.Double / right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Double(left->as.Double / right->as.Double);
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
break;
}
default: {
Ground.Log.Error("invalid subtract operation in Ground.Instruction.execute()");
Ground.Flags.error = true;
break;
}
}
return -1;
}
EQUAL: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Int == right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Int == right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(false);
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Double == right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Double == right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(false);
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
*final = Ground.New.Value.Bool(left->as.Char == right->as.Char);
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
*final = Ground.New.Value.Bool(left->as.Bool == right->as.Bool);
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr));
} else {
*final = Ground.New.Value.Bool(false);
}
break;
}
default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false);
break;
}
}
return -1;
}
INEQUAL: {
GroundValue* final = &heap[instruction->args.at[2]._offset];
GroundValue* left = &instruction->args.at[0].as.value;
GroundValue* right = &instruction->args.at[1].as.value;
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Int != right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Int != right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(true);
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
*final = Ground.New.Value.Bool(left->as.Double != right->as.Int);
break;
}
case GroundType_Double: {
*final = Ground.New.Value.Bool(left->as.Double != right->as.Double);
break;
}
default: {
*final = Ground.New.Value.Bool(true);
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
*final = Ground.New.Value.Bool(left->as.Char != right->as.Char);
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
*final = Ground.New.Value.Bool(left->as.Bool != right->as.Bool);
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
*final = Ground.New.Value.Bool(!strcmp(left->as.String.cstr, right->as.String.cstr));
} else {
*final = Ground.New.Value.Bool(true);
}
break;
}
default: {
// FIXME implement for complex types
*final = Ground.New.Value.Bool(false);
break;
}
}
return -1;
}
NOT: {
heap[instruction->args.at[1]._offset] = Ground.New.Value.Bool(!instruction->args.at[0].as.value.as.Bool);
return -1;
}
GREATER: {
return -1;
}
LESSER: {
return -1;
}
AND: {
return -1;
}
OR: {
return -1;
}
XOR: {
return -1;
}
NEG: {
return -1;
}
SHIFT: {
return -1;
}
STOI: {
return -1;
}
STOD: {
return -1;
}
ITOC: {
return -1;
}
CTOI: {
return -1;
}
TOSTRING: {
return -1;
}
FUN: {
return -1;
}
RETURN: {
return -1;
}
ENDFUN: {
return -1;
}
CALL: {
return -1;
}
CALLMETHOD: {
return -1;
}
STRUCT: {
return -1;
}
ENDSTRUCT: {
return -1;
}
INIT: {
return -1;
}
GETFIELD: {
return -1;
}
SETFIELD: {
return -1;
}
USE: {
return -1;
}
EXTERN: {
return -1;
}
CREATELABEL: {
return -1;
}
PAUSE: {
return -1;
}
DROP: {
return -1;
}
LICENSE: {
return -1;
}
ERRORCMD: {
return -1;
}
THROW: {
return -1;
}
CATCH: {
return -1;
}
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
Ground.Flags.error = true;
return -1;
}

View File

@@ -1,148 +1,15 @@
#include "../../include/ground.h"
#include <string.h>
#include <stdlib.h>
#include <uthash.h>
static inline void doLabels(GroundProgram* program, GroundState* state) {
for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_CREATELABEL) {
if (instruction->args.len > 0) {
GroundArg* arg = &instruction->args.at[0];
GroundLabel* label = NULL;
HASH_FIND_STR(state->labels, arg->as.ref->string, label);
if (label == NULL) {
label = malloc(sizeof(GroundLabel));
if (label == NULL) {
Ground.Log.Error("malloc failed in Ground.Internal.run()");
Ground.Flags.error = true;
return;
}
strncpy(label->name, arg->as.ref->string, 2047);
label->name[2047] = '\0';
label->lineNum = i;
HASH_ADD_STR(state->labels, name, label);
}
}
}
}
for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_JUMP) {
GroundArg* arg = &instruction->args.at[0];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
} else if (instruction->type == GroundInstruction_IF) {
GroundArg* arg = &instruction->args.at[1];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
} else if (instruction->type == GroundInstruction_CATCH) {
GroundArg* arg = &instruction->args.at[1];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
}
}
}
/*
* Assigns an offset to each variable referenced.
*/
static inline GroundSize doOffsets(GroundProgram* program, GroundState* state) {
GroundSize size = 0;
for (GroundSize i = 0; i < program->len; i++) {
for (GroundSize j = 0; j < program->at[i].args.len; j++) {
GroundArg* arg = &program->at[i].args.at[j];
if (
arg->type == GroundArg_Value ||
arg->type == GroundArg_Label ||
arg->type == GroundArg_LineRef
) continue;
GroundVariable* item = NULL;
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
if (item == NULL) {
item = malloc(sizeof(GroundVariable));
if (item == NULL) {
Ground.Log.Error("malloc failed in Ground.Internal.run()");
Ground.Flags.error = true;
return 0;
}
item->value = Ground.New.Value.Int(0);
strncpy(item->name, arg->as.ref->string, 2047);
item->_offset = size++;
HASH_ADD_STR(state->variables, name, item);
}
arg->_offset = item->_offset;
size++;
}
}
return size;
}
void _GroundInternalRun(GroundProgram* program, GroundState* state) {
// Precompute some really cool stuff
doLabels(program, state);
if (Ground.Flags.error) return;
GroundSize size = doOffsets(program, state);
if (Ground.Flags.error) return;
GroundValue* heap = malloc(sizeof(GroundValue) * size);
for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction instruction = Ground.Copy.Instruction(&program->at[i]);
int64_t status = Ground.Instruction.execute(&instruction, heap);
switch (status) {
case -2:
return;
case -1:
break;
default:
if (status < program->len) {
i = status - 1;
} else {
Ground.Log.Error("out of bounds jump in Ground.Internal.Run()");
Ground.Flags.error = true;
return;
}
}
Ground.Free.Instruction(&instruction);
GroundBytecode bytecode = Ground.New.Bytecode(program, state);
if (Ground.Flags.error) {
return;
}
Ground.Bytecode.Program.optimise(&bytecode.program);
if (Ground.Flags.error) {
return;
}
Ground.Bytecode.Program.execute(&bytecode.program, &bytecode.heap);
}

210
src/New/Bytecode.c Normal file
View File

@@ -0,0 +1,210 @@
#include "../../include/ground.h"
static inline void doLabels(GroundProgram* program, GroundState* state) {
for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_CREATELABEL) {
if (instruction->args.len > 0) {
GroundArg* arg = &instruction->args.at[0];
GroundLabel* label = NULL;
HASH_FIND_STR(state->labels, arg->as.ref->string, label);
if (label == NULL) {
label = malloc(sizeof(GroundLabel));
if (label == NULL) {
Ground.Log.Error("malloc failed in Ground.Internal.run()");
Ground.Flags.error = true;
return;
}
strncpy(label->name, arg->as.ref->string, 2047);
label->name[2047] = '\0';
label->lineNum = i;
HASH_ADD_STR(state->labels, name, label);
}
}
}
}
for (GroundSize i = 0; i < program->len; i++) {
GroundInstruction* instruction = &program->at[i];
if (instruction->type == GroundInstruction_JUMP) {
GroundArg* arg = &instruction->args.at[0];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction JUMP at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
} else if (instruction->type == GroundInstruction_IF) {
GroundArg* arg = &instruction->args.at[1];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction IF at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
} else if (instruction->type == GroundInstruction_CATCH) {
GroundArg* arg = &instruction->args.at[1];
GroundSize* line = Ground.State.findLabel(state, arg->as.ref->string);
if (line == NULL) {
char buf[2048];
snprintf(buf, 2047, "couldn't find label '%s' (instruction CATCH at %zu) in Ground.Internal.Run()", arg->as.ref->string, i);
Ground.Log.Error(buf);
Ground.Flags.error = true;
return;
}
arg->_offset = *line;
}
}
}
static inline void addToGroundBytecodeProgram(GroundBytecodeProgram* program, GroundBytecodeInstruction inst) {
if (program->len + 1 >= program->capacity) {
}
}
/*
* Assigns an offset to each variable referenced.
*/
static inline GroundSize doOffsets(GroundProgram* gp, GroundState* state, GroundBytecodeProgram* gbp) {
GroundSize size = 0;
// Add size of state
GroundVariable *s, *tmp;
HASH_ITER(hh, state->variables, s, tmp) {
size++;
}
for (GroundSize i = 0; i < gp->len; i++) {
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
GroundArg* arg = &gp->at[i].args.at[j];
if (
arg->type == GroundArg_Label ||
arg->type == GroundArg_LineRef
) continue;
if (arg->type == GroundArg_Value) {
GroundVariable* item = malloc(sizeof(GroundVariable));
if (item == NULL) {
Ground.Log.Error("malloc failed in Ground.Internal.run()");
Ground.Flags.error = true;
return 0;
}
item->value = Ground.Copy.Value(&arg->as.value);
if (Ground.Flags.error) return 0;
item->_offset = size++;
snprintf(item->name, sizeof(item->name) - 1, "_._.ground_internal_constant_%zu", item->_offset);
HASH_ADD_STR(state->variables, name, item);
continue;
}
GroundVariable* item = NULL;
HASH_FIND_STR(state->variables, arg->as.ref->string, item);
if (item == NULL) {
item = malloc(sizeof(GroundVariable));
if (item == NULL) {
Ground.Log.Error("malloc failed in Ground.Internal.run()");
Ground.Flags.error = true;
return 0;
}
item->value = Ground.New.Value.Int(0);
strncpy(item->name, arg->as.ref->string, 2047);
item->_offset = size++;
HASH_ADD_STR(state->variables, name, item);
}
arg->_offset = item->_offset;
size++;
}
// Convert to GroundBytecodeInstruction
GroundBytecodeInstruction inst = {
.type = gp->at[i].type,
.args.at = malloc(sizeof(GroundSize) * gp->at[i].args.len),
.args.len = gp->at[i].args.len,
.args.capacity = gp->at[i].args.len
};
if (inst.args.at == NULL) {}
for (GroundSize j = 0; j < gp->at[i].args.len; j++) {
inst.args.at[j] = gp->at[i].args.at[j]._offset;
}
gbp->at[i] = inst;
gbp->len++;
}
return size;
}
GroundBytecode _GroundNewBytecode(GroundProgram* program, GroundState* state) {
GroundBytecode bytecode = {
.program = {
.at = malloc(sizeof(GroundBytecodeInstruction) * program->len),
.capacity = program->len,
.len = 0,
},
.heap = {
.heap = NULL,
.capacity = 0,
.len = 0
}
};
if (bytecode.program.at == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Bytecode");
Ground.Flags.error = true;
return bytecode;
}
// Precompute some really cool stuff
doLabels(program, state);
if (Ground.Flags.error) return bytecode;
GroundSize size = doOffsets(program, state, &bytecode.program);
if (Ground.Flags.error) return bytecode;
// Allocate heap
bytecode.heap.heap = malloc(sizeof(GroundValue) * size);
if (bytecode.heap.heap == NULL) {
Ground.Log.Error("malloc failed in Ground.New.Bytecode");
Ground.Flags.error = true;
return bytecode;
}
bytecode.heap.capacity = size;
bytecode.heap.len = size;
GroundVariable *s, *tmp;
// Copy constants into heap
GroundSize i = 0;
HASH_ITER(hh, state->variables, s, tmp) {
bytecode.heap.heap[i] = Ground.Copy.Value(&s->value);
if (Ground.Flags.error) return bytecode;
i++;
}
return bytecode;
}

View File

@@ -32,6 +32,8 @@ GroundType _GroundNewType(enum GroundTypeType type, ...);
GroundIdentifier* _GroundNewIdentifier(const char* id);
GroundBytecode _GroundNewBytecode (GroundProgram* program, GroundState* state);
void _GroundFreeValue(GroundValue* in);
void _GroundFreeList(GroundList* in);
void _GroundFreeString(GroundString* in);
@@ -93,6 +95,13 @@ void _GroundLogWarning(const char* message);
void _GroundLogPrintErrors();
void _GroundBytecodeProgramExecute(GroundBytecodeProgram* program, GroundBytecodeHeap* heap);
void _GroundBytecodeProgramOptimise(GroundBytecodeProgram* program);
int64_t _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap);
void _GroundBytecodeHeapSet(GroundBytecodeHeap* heap, GroundSize idx, GroundValue value);
GroundValue* _GroundBytecodeHeapGet(GroundBytecodeHeap* heap, GroundSize idx);
struct _Ground Ground = {
@@ -136,6 +145,8 @@ struct _Ground Ground = {
.Type = _GroundNewType,
.Identifier = _GroundNewIdentifier,
.Bytecode = _GroundNewBytecode,
},
.Free = {
@@ -210,4 +221,18 @@ struct _Ground Ground = {
.errors = NULL,
.warnings = NULL,
},
.Bytecode = {
.Program = {
.execute = _GroundBytecodeProgramExecute,
.optimise = _GroundBytecodeProgramOptimise,
},
.Instruction = {
.execute = _GroundBytecodeInstructionExecute,
},
.Heap = {
.set = _GroundBytecodeHeapSet,
.get = _GroundBytecodeHeapGet,
},
},
};