Start work on the interpreter
This commit is contained in:
@@ -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[] = {
|
||||||
|
&&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;
|
||||||
|
}
|
||||||
|
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;
|
break;
|
||||||
case GroundInstruction_JUMP:
|
|
||||||
|
case GroundType_Double:
|
||||||
|
printf("%f", val->as.Double);
|
||||||
break;
|
break;
|
||||||
case GroundInstruction_END:
|
|
||||||
|
case GroundType_Bool:
|
||||||
|
printf(val->as.Bool ? "true" : "false");
|
||||||
break;
|
break;
|
||||||
case GroundInstruction_INPUT:
|
|
||||||
|
case GroundType_Char:
|
||||||
|
printf("%c", val->as.Char);
|
||||||
break;
|
break;
|
||||||
case GroundInstruction_PRINT:
|
|
||||||
|
case GroundType_String:
|
||||||
|
printf("%s", val->as.String.cstr);
|
||||||
break;
|
break;
|
||||||
case GroundInstruction_PRINTLN:
|
|
||||||
break;
|
default:
|
||||||
case GroundInstruction_SET:
|
printf("<fixme>");
|
||||||
break;
|
|
||||||
case GroundInstruction_GETTYPE:
|
|
||||||
break;
|
|
||||||
case GroundInstruction_EXISTS:
|
|
||||||
break;
|
|
||||||
case GroundInstruction_SETLIST:
|
|
||||||
break;
|
|
||||||
case GroundInstruction_SETLISTAT:
|
|
||||||
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;
|
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: {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user