Start work on interpreter
This commit is contained in:
1136
src/include/uthash.h
Normal file
1136
src/include/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
97
src/interpreter.c
Normal file
97
src/interpreter.c
Normal 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
18
src/interpreter.h
Normal 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
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "interpreter.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
char* getFileContents(const char* filename) {
|
char* getFileContents(const char* filename) {
|
||||||
@@ -44,4 +45,5 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
char* file = getFileContents(argv[1]);
|
char* file = getFileContents(argv[1]);
|
||||||
GroundProgram program = parseFile(file);
|
GroundProgram program = parseFile(file);
|
||||||
|
interpretGroundProgram(&program);
|
||||||
}
|
}
|
||||||
|
|||||||
196
src/types.c
196
src/types.c
@@ -1,4 +1,5 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
GroundValue createIntGroundValue(int64_t in) {
|
GroundValue createIntGroundValue(int64_t in) {
|
||||||
GroundValue gv;
|
GroundValue gv;
|
||||||
@@ -35,6 +36,39 @@ GroundValue createBoolGroundValue(bool in) {
|
|||||||
return gv;
|
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) {
|
void freeGroundValue(GroundValue* gv) {
|
||||||
if (gv->type == STRING && gv->data.stringVal != NULL) {
|
if (gv->type == STRING && gv->data.stringVal != NULL) {
|
||||||
free(gv->data.stringVal);
|
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 createGroundInstruction(GroundInstType type) {
|
||||||
GroundInstruction gi;
|
GroundInstruction gi;
|
||||||
gi.type = type;
|
gi.type = type;
|
||||||
@@ -88,3 +155,132 @@ void addArgToInstruction(GroundInstruction* gi, GroundArg arg) {
|
|||||||
gi->args.args[gi->args.length - 1] = 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(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
11
src/types.h
11
src/types.h
@@ -82,7 +82,7 @@ GroundValue createIntGroundValue(int64_t in);
|
|||||||
|
|
||||||
// Creates a GroundValue containing (in), with type DOUBLE.
|
// Creates a GroundValue containing (in), with type DOUBLE.
|
||||||
GroundValue createDoubleGroundValue(double in);
|
GroundValue createDoubleGroundValue(double in);
|
||||||
;
|
|
||||||
// Creates a GroundValue containing (in), with type STRING.
|
// Creates a GroundValue containing (in), with type STRING.
|
||||||
GroundValue createStringGroundValue(const char* in);
|
GroundValue createStringGroundValue(const char* in);
|
||||||
|
|
||||||
@@ -95,6 +95,9 @@ GroundValue createBoolGroundValue(bool in);
|
|||||||
// If (gv) contains any data stored on the heap, frees it.
|
// If (gv) contains any data stored on the heap, frees it.
|
||||||
void freeGroundValue(GroundValue* gv);
|
void freeGroundValue(GroundValue* gv);
|
||||||
|
|
||||||
|
// Prints out a GroundValue.
|
||||||
|
void printGroundValue(GroundValue* gv);
|
||||||
|
|
||||||
// Initializes a GroundArg with type VALUE
|
// Initializes a GroundArg with type VALUE
|
||||||
GroundArg createValueGroundArg(GroundValue 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.
|
// Frees all data stored on the heap in a GroundArg.
|
||||||
void freeGroundArg(GroundArg* ga);
|
void freeGroundArg(GroundArg* ga);
|
||||||
|
|
||||||
|
// Prints out a GroundArg.
|
||||||
|
void printGroundArg(GroundArg* ga);
|
||||||
|
|
||||||
// Initializes a GroundInstruction, with inst type (type).
|
// Initializes a GroundInstruction, with inst type (type).
|
||||||
GroundInstruction createGroundInstruction(GroundInstType type);
|
GroundInstruction createGroundInstruction(GroundInstType type);
|
||||||
|
|
||||||
@@ -113,4 +119,7 @@ void freeGroundInstruction(GroundInstruction* gi);
|
|||||||
// Adds arg (arg) to the GroundInstruction (gi).
|
// Adds arg (arg) to the GroundInstruction (gi).
|
||||||
void addArgToInstruction(GroundInstruction* gi, GroundArg arg);
|
void addArgToInstruction(GroundInstruction* gi, GroundArg arg);
|
||||||
|
|
||||||
|
// Prints out a GroundInstruction.
|
||||||
|
void printGroundInstruction(GroundInstruction* gi);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1
tests/simple.grnd
Normal file
1
tests/simple.grnd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
print
|
||||||
Reference in New Issue
Block a user