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

552 lines
19 KiB
C
Raw Normal View History

2026-06-13 19:45:36 +10:00
#include "../../include/ground.h"
2026-06-15 21:33:58 +10:00
#include <stdio.h>
#include <inttypes.h>
2026-06-16 19:19:37 +10:00
#include <string.h>
2026-06-13 19:45:36 +10:00
2026-06-15 21:33:58 +10:00
/*
* Return values guide:
* -2: Exit program
* -1: Nothing
* 0-infinity: Jump to instruction number
*/
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 (size_t i = 0; i < instruction->args.len; i++) {
if (instruction->args.at[i].type == GroundArg_ValueRef) {
size_t 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;
2026-06-15 20:27:50 +10:00
}
2026-06-15 21:33:58 +10:00
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 (size_t 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 (size_t 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;
}
2026-06-16 19:19:37 +10:00
SET: {
size_t 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;
}
2026-06-15 21:33:58 +10:00
SETLIST: {}
SETLISTAT: {}
GETLISTAT: {}
GETLISTSIZE: {}
LISTAPPEND: {}
GETSTRSIZE: {}
GETSTRCHARAT: {}
2026-06-16 19:19:37 +10:00
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;
}
2026-06-15 21:33:58 +10:00
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: {}
2026-06-16 19:19:37 +10:00
Ground.Log.Error("operation fell through in Ground.Instruction.execute()");
Ground.Flags.error = true;
return -1;
2026-06-13 19:45:36 +10:00
}