Start work on interpreter

This commit is contained in:
2025-11-23 18:34:30 +11:00
parent 31cc30ee48
commit a69901be7b
7 changed files with 1460 additions and 1 deletions

1136
src/include/uthash.h Normal file

File diff suppressed because it is too large Load Diff

97
src/interpreter.c Normal file
View File

@@ -0,0 +1,97 @@
#include "interpreter.h"
#include "parser.h"
#include "types.h"
#include "include/uthash.h"
#include <stdlib.h>
int currentInstruction = 0;
void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) {
printf("Ground runtime error:\n ErrorType: ");
switch (error) {
case ARG_TYPE_MISMATCH: {
printf("ArgTypeMismatch");
break;
}
case TOO_FEW_ARGS: {
printf("TooFewArgs");
break;
}
case TOO_MANY_ARGS: {
printf("TooManyArgs");
break;
}
default:
case FIXME: {
printf("FIXME (please report issue to https://chsp.au/ground/cground)");
}
}
printf("\n");
if (what != NULL) {
printf(" ErrorContext: %s\n", what);
}
if (where != NULL) {
printf(" ErrorInstruction: ");
printGroundInstruction(where);
printf("\n");
}
if (whereLine > -1) {
printf(" ErrorLine: %d\n", whereLine + 1);
}
exit(1);
}
void interpretGroundProgram(GroundProgram* in) {
// Preprocess all labels
for (int i = 0; i < in->size; i++) {
if (in->instructions[i].type == CREATELABEL) {
// labelHashmap.addLabel()
}
}
while (currentInstruction < in->size) {
interpretGroundInstruction(&in->instructions[currentInstruction]);
currentInstruction++;
}
}
void interpretGroundInstruction(GroundInstruction* in) {
switch (in->type) {
// We can safely ignore any CREATELABEL instructions, these have been preprocessed
case CREATELABEL: {
break;
}
case PRINT: {
if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
}
for (int i = 0; i < in->args.length; i++) {
printGroundArg(&in->args.args[i]);
printf(" ");
}
break;
}
case PRINTLN: {
if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
}
for (int i = 0; i < in->args.length; i++) {
printGroundArg(&in->args.args[i]);
printf(" ");
}
printf("\n");
break;
}
case END: {
if (in->args.length < 1) {
exit(0);
} else {
}
break;
}
default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
}
}
}

18
src/interpreter.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef INTERPRETER_H
#define INTERPRETER_H
#include "types.h"
#include "parser.h"
#include "include/uthash.h"
typedef enum GroundRuntimeError {
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, FIXME
} GroundRuntimeError;
typedef struct GroundLabel {
} GroundLabel;
void interpretGroundProgram(GroundProgram* in);
void interpretGroundInstruction(GroundInstruction* in);
#endif

View File

@@ -1,4 +1,5 @@
#include "parser.h"
#include "interpreter.h"
#include <stdio.h>
char* getFileContents(const char* filename) {
@@ -44,4 +45,5 @@ int main(int argc, char** argv) {
}
char* file = getFileContents(argv[1]);
GroundProgram program = parseFile(file);
interpretGroundProgram(&program);
}

View File

@@ -1,4 +1,5 @@
#include "types.h"
#include <inttypes.h>
GroundValue createIntGroundValue(int64_t in) {
GroundValue gv;
@@ -35,6 +36,39 @@ GroundValue createBoolGroundValue(bool in) {
return gv;
}
void printGroundValue(GroundValue* gv) {
switch (gv->type) {
case INT: {
printf("%" PRId64 "", gv->data.intVal);
break;
}
case DOUBLE: {
printf("%f", gv->data.doubleVal);
break;
}
case STRING: {
printf("%s", gv->data.stringVal);
break;
}
case CHAR: {
printf("%c", gv->data.charVal);
break;
}
case BOOL: {
if (gv->data.boolVal) {
printf("true");
} else {
printf("false");
}
break;
}
default: {
printf("FIXME");
break;
}
}
}
void freeGroundValue(GroundValue* gv) {
if (gv->type == STRING && gv->data.stringVal != NULL) {
free(gv->data.stringVal);
@@ -63,6 +97,39 @@ void freeGroundArg(GroundArg* ga) {
}
}
void printGroundArg(GroundArg* ga) {
switch (ga->type) {
case VALUE: {
printGroundValue(&ga->value.value);
break;
}
case DIRREF: {
printf("&%s", ga->value.refName);
break;
}
case VALREF: {
printf("$%s", ga->value.refName);
break;
}
case LINEREF: {
printf("%%%s", ga->value.refName);
break;
}
case LABEL: {
printf("@%s", ga->value.refName);
break;
}
case FNREF: {
printf("!%s", ga->value.refName);
break;
}
case TYPEREF: {
printf("-%s", ga->value.refName);
break;
}
}
}
GroundInstruction createGroundInstruction(GroundInstType type) {
GroundInstruction gi;
gi.type = type;
@@ -88,3 +155,132 @@ void addArgToInstruction(GroundInstruction* gi, GroundArg arg) {
gi->args.args[gi->args.length - 1] = arg;
}
void printGroundInstruction(GroundInstruction* gi) {
switch (gi->type) {
case IF:
printf("if");
break;
case JUMP:
printf("jump");
break;
case END:
printf("end");
break;
case INPUT:
printf("input");
break;
case PRINT:
printf("print");
break;
case PRINTLN:
printf("println");
break;
case SET:
printf("set");
break;
case GETTYPE:
printf("gettype");
break;
case EXISTS:
printf("exists");
break;
case SETLIST:
printf("setlist");
break;
case SETLISTAT:
printf("setlistat");
break;
case GETLISTAT:
printf("getlistat");
break;
case GETLISTSIZE:
printf("getlistsize");
break;
case LISTAPPEND:
printf("listappend");
break;
case GETSTRSIZE:
printf("getstrsize");
break;
case GETSTRCHARAT:
printf("getstrcharat");
break;
case ADD:
printf("add");
break;
case SUBTRACT:
printf("subtract");
break;
case MULTIPLY:
printf("multiply");
break;
case DIVIDE:
printf("divide");
break;
case EQUAL:
printf("equal");
break;
case INEQUAL:
printf("inequal");
break;
case NOT:
printf("not");
break;
case GREATER:
printf("greater");
break;
case LESSER:
printf("lesser");
break;
case STOI:
printf("stoi");
break;
case STOD:
printf("stod");
break;
case TOSTRING:
printf("tostring");
break;
case FUN:
printf("fun");
break;
case RETURN:
printf("return");
break;
case ENDFUN:
printf("endfun");
break;
case PUSHARG:
printf("pusharg");
break;
case CALL:
printf("call");
break;
case STRUCT:
printf("struct");
break;
case ENDSTRUCT:
printf("endstruct");
break;
case INIT:
printf("init");
break;
case USE:
printf("use");
break;
case EXTERN:
printf("extern");
break;
case CREATELABEL:
printf("createlabel");
break;
default:
printf("FIXME");
break;
}
printf(" ");
for (int i = 0; i < gi->args.length; i++) {
printGroundArg(&gi->args.args[i]);
printf(" ");
}
}

View File

@@ -82,7 +82,7 @@ GroundValue createIntGroundValue(int64_t in);
// Creates a GroundValue containing (in), with type DOUBLE.
GroundValue createDoubleGroundValue(double in);
;
// Creates a GroundValue containing (in), with type STRING.
GroundValue createStringGroundValue(const char* in);
@@ -95,6 +95,9 @@ GroundValue createBoolGroundValue(bool in);
// If (gv) contains any data stored on the heap, frees it.
void freeGroundValue(GroundValue* gv);
// Prints out a GroundValue.
void printGroundValue(GroundValue* gv);
// Initializes a GroundArg with type VALUE
GroundArg createValueGroundArg(GroundValue value);
@@ -104,6 +107,9 @@ GroundArg createRefGroundArg(GroundArgType type, const char* refname);
// Frees all data stored on the heap in a GroundArg.
void freeGroundArg(GroundArg* ga);
// Prints out a GroundArg.
void printGroundArg(GroundArg* ga);
// Initializes a GroundInstruction, with inst type (type).
GroundInstruction createGroundInstruction(GroundInstType type);
@@ -113,4 +119,7 @@ void freeGroundInstruction(GroundInstruction* gi);
// Adds arg (arg) to the GroundInstruction (gi).
void addArgToInstruction(GroundInstruction* gi, GroundArg arg);
// Prints out a GroundInstruction.
void printGroundInstruction(GroundInstruction* gi);
#endif

1
tests/simple.grnd Normal file
View File

@@ -0,0 +1 @@
print