Start work on the interpreter

This commit is contained in:
2026-06-15 21:33:58 +10:00
parent 80140ed798
commit da75cf7590
3 changed files with 196 additions and 114 deletions

View File

@@ -1,116 +1,175 @@
#include "../../include/ground.h" #include "../../include/ground.h"
#include <stdio.h>
#include <inttypes.h>
#define handle(instruction) handle##instruction##(instruction, state); break; /*
* Return values guide:
* -2: Exit program
* -1: Nothing
* 0-infinity: Jump to instruction number
*/
void _GroundInstructionExecute(GroundInstruction* instruction, GroundState* state) { int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* heap) {
switch (instruction->type) {
case GroundInstruction_IF: static const void* jumpTable[] = {
break; &&IF, &&JUMP, &&END,
case GroundInstruction_JUMP: &&INPUT, &&PRINT, &&PRINTLN,
break; &&SET, &&GETTYPE, &&EXISTS,
case GroundInstruction_END: &&SETLIST, &&SETLISTAT, &&GETLISTAT, &&GETLISTSIZE, &&LISTAPPEND,
break; &&GETSTRSIZE, &&GETSTRCHARAT,
case GroundInstruction_INPUT: &&ADD, &&SUBTRACT, &&MULTIPLY, &&DIVIDE,
break; &&EQUAL, &&INEQUAL, &&NOT, &&GREATER, &&LESSER,
case GroundInstruction_PRINT: &&AND, &&OR, &&XOR, &&NEG, &&SHIFT,
break; &&STOI, &&STOD, &&ITOC, &&CTOI, &&TOSTRING,
case GroundInstruction_PRINTLN: &&FUN, &&RETURN, &&ENDFUN, &&CALL, &&CALLMETHOD,
break; &&STRUCT, &&ENDSTRUCT, &&INIT, &&GETFIELD, &&SETFIELD,
case GroundInstruction_SET: &&USE, &&EXTERN, &&CREATELABEL,
break; &&PAUSE, &&DROP, &&LICENSE, &&ERRORCMD, &&THROW, &&CATCH
case GroundInstruction_GETTYPE: };
break;
case GroundInstruction_EXISTS: // Preprocess any ValueRefs
break; for (size_t i = 0; i < instruction->args.len; i++) {
case GroundInstruction_SETLIST: if (instruction->args.at[i].type == GroundArg_ValueRef) {
break; size_t offset = instruction->args.at[i]._offset;
case GroundInstruction_SETLISTAT: instruction->args.at[i] = Ground.New.Arg.Value(heap[offset]);
break; }
case GroundInstruction_GETLISTAT:
break;
case GroundInstruction_GETLISTSIZE:
break;
case GroundInstruction_LISTAPPEND:
break;
case GroundInstruction_GETSTRSIZE:
break;
case GroundInstruction_GETSTRCHARAT:
break;
case GroundInstruction_ADD:
break;
case GroundInstruction_SUBTRACT:
break;
case GroundInstruction_MULTIPLY:
break;
case GroundInstruction_DIVIDE:
break;
case GroundInstruction_EQUAL:
break;
case GroundInstruction_INEQUAL:
break;
case GroundInstruction_NOT:
break;
case GroundInstruction_GREATER:
break;
case GroundInstruction_LESSER:
break;
case GroundInstruction_AND:
break;
case GroundInstruction_OR:
break;
case GroundInstruction_XOR:
break;
case GroundInstruction_NEG:
break;
case GroundInstruction_SHIFT:
break;
case GroundInstruction_STOI:
break;
case GroundInstruction_STOD:
break;
case GroundInstruction_ITOC:
break;
case GroundInstruction_CTOI:
break;
case GroundInstruction_TOSTRING:
break;
case GroundInstruction_FUN:
break;
case GroundInstruction_RETURN:
break;
case GroundInstruction_ENDFUN:
break;
case GroundInstruction_CALL:
break;
case GroundInstruction_CALLMETHOD:
break;
case GroundInstruction_STRUCT:
break;
case GroundInstruction_ENDSTRUCT:
break;
case GroundInstruction_INIT:
break;
case GroundInstruction_GETFIELD:
break;
case GroundInstruction_SETFIELD:
break;
case GroundInstruction_USE:
break;
case GroundInstruction_EXTERN:
break;
case GroundInstruction_CREATELABEL:
break;
case GroundInstruction_PAUSE:
break;
case GroundInstruction_DROP:
break;
case GroundInstruction_LICENSE:
break;
case GroundInstruction_ERROR:
break;
case GroundInstruction_THROW:
break;
case GroundInstruction_CATCH:
break;
} }
// 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 (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;
}
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: {}
} }

View File

@@ -4,7 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <uthash.h> #include <uthash.h>
void doLabels(GroundProgram* program, GroundState* state) { static inline void doLabels(GroundProgram* program, GroundState* state) {
for (size_t i = 0; i < program->len; i++) { for (size_t i = 0; i < program->len; i++) {
for (size_t j = 0; j < program->len; j++) { for (size_t j = 0; j < program->len; j++) {
@@ -70,7 +70,7 @@ void doLabels(GroundProgram* program, GroundState* state) {
/* /*
* Assigns an offset to each variable referenced. * Assigns an offset to each variable referenced.
*/ */
size_t doOffsets(GroundProgram* program, GroundState* state) { static inline size_t doOffsets(GroundProgram* program, GroundState* state) {
size_t size = 0; size_t size = 0;
for (size_t i = 0; i < program->len; i++) { for (size_t i = 0; i < program->len; i++) {
for (size_t j = 0; j < program->at[i].args.len; j++) { for (size_t j = 0; j < program->at[i].args.len; j++) {
@@ -114,4 +114,27 @@ void _GroundInternalRun(GroundProgram* program, GroundState* state) {
size_t size = doOffsets(program, state); size_t size = doOffsets(program, state);
if (Ground.Flags.error) return; if (Ground.Flags.error) return;
GroundValue* heap = malloc(sizeof(GroundValue) * size);
for (size_t 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;
} else {
Ground.Log.Error("out of bounds jump in Ground.Internal.Run()");
Ground.Flags.error = true;
return;
}
}
// TODO: implement
// Ground.Free.Instruction(&instruction);
}
} }

View File

@@ -56,7 +56,7 @@ void _GroundListAppend(GroundList* list, GroundValue value);
void _GroundInstructionAppend(GroundInstruction* instruction, GroundArg arg); void _GroundInstructionAppend(GroundInstruction* instruction, GroundArg arg);
void _GroundInstructionExecute(GroundInstruction* instruction, GroundState* state); int64_t _GroundInstructionExecute(GroundInstruction* instruction, GroundValue* heap);
void _GroundProgramAppend(GroundProgram* program, GroundInstruction instruction); void _GroundProgramAppend(GroundProgram* program, GroundInstruction instruction);