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

770 lines
28 KiB
C
Raw Normal View History

2026-06-21 14:35:48 +10:00
#include "../../../include/ground.h"
2026-06-25 18:57:53 +10:00
#include "../../linenoise/linenoise.h"
2026-06-21 14:35:48 +10:00
#include <stdint.h>
#include <inttypes.h>
2026-06-24 10:17:58 +10:00
#include <stdio.h>
#include <stdlib.h>
2026-06-21 16:39:05 +10:00
#include <string.h>
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val))
2026-07-02 11:35:56 +10:00
static void printValue(GroundBytecodeValue* val) {
2026-06-21 16:39:05 +10:00
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;
}
}
2026-06-21 14:35:48 +10:00
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
};
goto *jumpTable[instruction->type];
IF: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* cond = HEAP_GET(heap, instruction->args.at[0]);
2026-06-21 16:13:00 +10:00
if (cond->as.Bool) {
return instruction->args.at[1];
}
2026-06-21 14:35:48 +10:00
return -1;
}
JUMP: {
2026-06-21 16:13:00 +10:00
return instruction->args.at[0];
2026-06-21 14:35:48 +10:00
}
END: {
return -2;
}
INPUT: {
2026-06-25 18:57:53 +10:00
char* input = linenoise("");
2026-07-02 11:35:56 +10:00
HEAP_SET(heap, instruction->args.at[0], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(input))));
2026-06-25 18:57:53 +10:00
free(input);
2026-06-21 14:35:48 +10:00
return -1;
}
PRINT: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
2026-06-21 16:39:05 +10:00
printValue(HEAP_GET(heap, instruction->args.at[i]));
2026-06-21 14:35:48 +10:00
}
return -1;
}
PRINTLN: {
for (GroundSize i = 0; i < instruction->args.len; i++) {
2026-06-21 16:39:05 +10:00
printValue(HEAP_GET(heap, instruction->args.at[i]));
2026-06-21 14:35:48 +10:00
}
printf("\n");
return -1;
}
SET: {
2026-06-21 16:39:05 +10:00
HEAP_SET(heap, instruction->args.at[0], *HEAP_GET(heap, instruction->args.at[1]));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int(left->as.Int + right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Int + right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double + right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double + right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-06-21 16:39:05 +10:00
GroundSize total = left->as.String.len + right->as.String.len;
char* buf = malloc(total + 1);
2026-06-21 14:35:48 +10:00
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);
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(buf)));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int(left->as.Int - right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Int - right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double - right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double - right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int(left->as.Int * right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Int * right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double * right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double * right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int(left->as.Int / right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Int / right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double / right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(left->as.Double / right->as.Double));
2026-06-21 14:35:48 +10:00
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: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int == right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int == right->as.Double));
2026-06-21 14:35:48 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double == right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double == right->as.Double));
2026-06-21 14:35:48 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Char == right->as.Char));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool == right->as.Bool));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr) == 0));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
}
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
break;
}
}
return -1;
}
INEQUAL: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-21 14:35:48 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int != right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int != right->as.Double));
2026-06-21 14:35:48 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-21 14:35:48 +10:00
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double != right->as.Int));
2026-06-21 14:35:48 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double != right->as.Double));
2026-06-21 14:35:48 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-21 14:35:48 +10:00
break;
}
}
break;
}
case GroundType_Char: {
if (right->type.type == GroundType_Char) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Char != right->as.Char));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-21 14:35:48 +10:00
}
break;
}
case GroundType_Bool: {
if (right->type.type == GroundType_Bool) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool != right->as.Bool));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-21 14:35:48 +10:00
}
break;
}
case GroundType_String: {
if (right->type.type == GroundType_String) {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(strcmp(left->as.String.cstr, right->as.String.cstr) != 0));
2026-06-21 14:35:48 +10:00
} else {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-21 14:35:48 +10:00
}
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-21 14:35:48 +10:00
break;
}
}
return -1;
}
NOT: {
2026-07-02 11:35:56 +10:00
HEAP_SET(heap, instruction->args.at[1], Ground.New.BytecodeValue(Ground.New.Value.Bool(!HEAP_GET(heap, instruction->args.at[0])->as.Bool)));
2026-06-21 14:35:48 +10:00
return -1;
}
GREATER: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-24 10:17:58 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int > right->as.Int));
2026-06-24 10:17:58 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int > right->as.Double));
2026-06-24 10:17:58 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-24 10:17:58 +10:00
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double > right->as.Int));
2026-06-24 10:17:58 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double > right->as.Double));
2026-06-24 10:17:58 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-24 10:17:58 +10:00
break;
}
}
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-24 10:17:58 +10:00
break;
}
}
2026-06-21 14:35:48 +10:00
return -1;
}
LESSER: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-24 10:17:58 +10:00
switch (left->type.type) {
case GroundType_Int: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int < right->as.Int));
2026-06-24 10:17:58 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Int < right->as.Double));
2026-06-24 10:17:58 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-24 10:17:58 +10:00
break;
}
}
break;
}
case GroundType_Double: {
switch (right->type.type) {
case GroundType_Int: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double < right->as.Int));
2026-06-24 10:17:58 +10:00
break;
}
case GroundType_Double: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Double < right->as.Double));
2026-06-24 10:17:58 +10:00
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(true));
2026-06-24 10:17:58 +10:00
break;
}
}
break;
}
default: {
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(false));
2026-06-24 10:17:58 +10:00
break;
}
}
2026-06-21 14:35:48 +10:00
return -1;
}
AND: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-24 10:17:58 +10:00
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool && right->as.Bool));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
OR: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-24 10:17:58 +10:00
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool || right->as.Bool));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
XOR: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[2]);
GroundBytecodeValue* left = HEAP_GET(heap, instruction->args.at[0]);
GroundBytecodeValue* right = HEAP_GET(heap, instruction->args.at[1]);
2026-06-24 10:17:58 +10:00
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Bool(left->as.Bool != right->as.Bool));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
NEG: {
return -1;
}
SHIFT: {
return -1;
}
STOI: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
2026-06-24 10:17:58 +10:00
char* status = NULL;
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int(strtoll(in->as.String.cstr, &status, 0)));
2026-06-24 10:17:58 +10:00
if (status != in->as.String.cstr) {
Ground.Flags.error = true;
Ground.Log.Error("Failed converting string to double");
}
2026-06-21 14:35:48 +10:00
return -1;
}
STOD: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
2026-06-24 10:17:58 +10:00
char* status = NULL;
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Double(strtod(in->as.String.cstr, &status)));
2026-06-24 10:17:58 +10:00
if (status != in->as.String.cstr) {
Ground.Flags.error = true;
Ground.Log.Error("Failed converting string to double");
}
2026-06-21 14:35:48 +10:00
return -1;
}
ITOC: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
2026-06-24 10:17:58 +10:00
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Char((char)in->as.Int));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
CTOI: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
2026-06-24 10:17:58 +10:00
2026-07-02 11:35:56 +10:00
*final = Ground.New.BytecodeValue(Ground.New.Value.Int((int64_t)in->as.Char));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
TOSTRING: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* final = HEAP_GET(heap, instruction->args.at[1]);
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
2026-06-24 10:17:58 +10:00
char buf[4096];
switch (in->type.type) {
case GroundType_Int: {
snprintf(buf, sizeof(buf), "%" PRId64, in->as.Int);
break;
}
case GroundType_Double: {
snprintf(buf, sizeof(buf), "%f", in->as.Double);
break;
}
case GroundType_Char: {
snprintf(buf, sizeof(buf), "%c", in->as.Char);
break;
}
case GroundType_Bool: {
snprintf(buf, sizeof(buf), in->as.Bool ? "true" : "false");
break;
}
case GroundType_String: {
2026-07-02 11:35:56 +10:00
*in = Ground.New.BytecodeValue(Ground.New.Value.String(final->as.String));
2026-06-24 10:17:58 +10:00
return -1;
}
default: {
// TODO: implement tostring for complex types
snprintf(buf, sizeof(buf), "<FIXME>");
break;
}
}
2026-07-02 11:35:56 +10:00
*in = Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(buf)));
2026-06-24 10:17:58 +10:00
2026-06-21 14:35:48 +10:00
return -1;
}
FUN: {
2026-06-24 10:17:58 +10:00
// no-op
2026-06-21 14:35:48 +10:00
return -1;
}
RETURN: {
return -1;
}
ENDFUN: {
2026-06-24 10:17:58 +10:00
// no-op
2026-06-21 14:35:48 +10:00
return -1;
}
CALL: {
return -1;
}
CALLMETHOD: {
return -1;
}
STRUCT: {
2026-06-24 10:17:58 +10:00
// no-op
2026-06-21 14:35:48 +10:00
return -1;
}
ENDSTRUCT: {
2026-06-24 10:17:58 +10:00
// no-op
2026-06-21 14:35:48 +10:00
return -1;
}
INIT: {
return -1;
}
GETFIELD: {
return -1;
}
SETFIELD: {
return -1;
}
USE: {
return -1;
}
EXTERN: {
return -1;
}
CREATELABEL: {
2026-06-24 10:17:58 +10:00
// no-op
2026-06-21 14:35:48 +10:00
return -1;
}
PAUSE: {
return -1;
}
DROP: {
2026-07-02 11:35:56 +10:00
GroundBytecodeValue* in = HEAP_GET(heap, instruction->args.at[0]);
Ground.Free.BytecodeValue(in);
*in = Ground.New.BytecodeValue(Ground.New.Value.Int(0));
2026-06-21 14:35:48 +10:00
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;
}