Files
ground-rewrite/src/Bytecode/Instruction/execute.c

601 lines
20 KiB
C
Raw Normal View History

2026-06-21 14:35:48 +10:00
#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;
}