forked from ground/ground
199 lines
5.7 KiB
C
199 lines
5.7 KiB
C
#include "parser.h"
|
|
#include "interpreter.h"
|
|
#include "compiler.h"
|
|
#include "types.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
|
|
GroundProgram groundCreateProgram() {
|
|
return (GroundProgram) {
|
|
.instructions = malloc(sizeof(GroundInstruction)),
|
|
.size = 0
|
|
};
|
|
}
|
|
void groundAddInstructionToProgram(GroundProgram* program, GroundInstruction instruction) {
|
|
addInstructionToProgram(program, instruction);
|
|
}
|
|
|
|
GroundInstruction groundCreateInstruction(GroundInstType type) {
|
|
return (GroundInstruction) {
|
|
.type = type,
|
|
.args.args = malloc(sizeof(GroundArg)),
|
|
.args.length = 0
|
|
};
|
|
}
|
|
|
|
void groundAddValueToInstruction(GroundInstruction* inst, GroundValue value) {
|
|
addArgToInstruction(inst, createValueGroundArg(value));
|
|
}
|
|
|
|
void groundAddReferenceToInstruction(GroundInstruction* inst, GroundArg value) {
|
|
addArgToInstruction(inst, value);
|
|
}
|
|
|
|
GroundArg groundCreateReference(GroundArgType type, char* ref) {
|
|
return (GroundArg) {
|
|
.type = type,
|
|
.value.refName = ref
|
|
};
|
|
}
|
|
|
|
GroundValue groundCreateValue(GroundValueType type, ...) {
|
|
va_list args;
|
|
va_start(args, type);
|
|
|
|
GroundValue gv;
|
|
switch (type) {
|
|
case INT: {
|
|
gv = createIntGroundValue(va_arg(args, int64_t));
|
|
break;
|
|
}
|
|
case DOUBLE: {
|
|
gv = createDoubleGroundValue(va_arg(args, double));
|
|
break;
|
|
}
|
|
case STRING: {
|
|
gv = createStringGroundValue(va_arg(args, char*));
|
|
break;
|
|
}
|
|
case CHAR: {
|
|
gv = createCharGroundValue((char)va_arg(args, int));
|
|
break;
|
|
}
|
|
case BOOL: {
|
|
gv = createBoolGroundValue((bool)va_arg(args, int));
|
|
break;
|
|
}
|
|
case LIST: {
|
|
gv = createListGroundValue(va_arg(args, List));
|
|
break;
|
|
}
|
|
case FUNCTION: {
|
|
gv = createFunctionGroundValue(va_arg(args, GroundFunction*));
|
|
break;
|
|
}
|
|
case STRUCTVAL: {
|
|
gv.type = STRUCTVAL;
|
|
gv.data.structVal = malloc(sizeof(GroundStruct));
|
|
*gv.data.structVal = va_arg(args, GroundStruct);
|
|
break;
|
|
}
|
|
case NONE: {
|
|
gv = createNoneGroundValue();
|
|
break;
|
|
}
|
|
case CUSTOM: {
|
|
// CUSTOM values are created from structs
|
|
GroundStruct* gstruct = va_arg(args, GroundStruct*);
|
|
gv.type = CUSTOM;
|
|
gv.data.customVal = malloc(sizeof(GroundObject));
|
|
*gv.data.customVal = createObject(*gstruct);
|
|
|
|
// Deep copy the struct definition so it stays valid
|
|
gv.customType = malloc(sizeof(GroundStruct));
|
|
gv.customType->size = gstruct->size;
|
|
gv.customType->fields = malloc(gstruct->size * sizeof(GroundStructField));
|
|
for (size_t i = 0; i < gstruct->size; i++) {
|
|
strncpy(gv.customType->fields[i].id, gstruct->fields[i].id, 64);
|
|
gv.customType->fields[i].value = copyGroundValue(&gstruct->fields[i].value);
|
|
}
|
|
break;
|
|
}
|
|
case ERROR: {
|
|
// FIXME
|
|
gv = createNoneGroundValue();
|
|
break;
|
|
}
|
|
default: {
|
|
gv = createNoneGroundValue();
|
|
break;
|
|
}
|
|
}
|
|
|
|
va_end(args);
|
|
return gv;
|
|
}
|
|
|
|
GroundValue groundRunProgram(GroundProgram* program) {
|
|
GroundVariable* variables = NULL;
|
|
GroundLabel* labels = NULL;
|
|
GroundScope scope = {
|
|
.variables = &variables,
|
|
.labels = &labels,
|
|
.isMainScope = true
|
|
};
|
|
return interpretGroundProgram(program, &scope);
|
|
}
|
|
|
|
void groundPrintProgram(GroundProgram* program) {
|
|
for (size_t i = 0; i < program->size; i++) {
|
|
printGroundInstruction(&program->instructions[i]);
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
GroundProgram groundParseFile(const char* code) {
|
|
return parseFile(code);
|
|
}
|
|
|
|
GroundStruct groundCreateStruct() {
|
|
GroundStruct gs;
|
|
gs.size = 0;
|
|
gs.fields = malloc(sizeof(GroundStructField));
|
|
return gs;
|
|
}
|
|
|
|
void groundAddValueToScope(GroundScope* gs, const char* name, GroundValue value) {
|
|
addVariable(gs->variables, name, value);
|
|
}
|
|
|
|
void groundAddFieldToStruct(GroundStruct* gstruct, char* name, GroundValue field) {
|
|
addFieldToStruct(gstruct, name, field);
|
|
}
|
|
|
|
char* groundCompileProgram(GroundProgram* program) {
|
|
return compileGroundProgram(program);
|
|
}
|
|
|
|
GroundValue groundRunFunction(GroundFunction* function, size_t argc, ...) {
|
|
va_list args;
|
|
va_start(args, argc);
|
|
|
|
if (function == NULL) {
|
|
return createErrorGroundValue(createGroundError("Null function passed to groundRunFunction", "valueError", NULL, NULL));
|
|
}
|
|
|
|
// Seems to crash some functions
|
|
// GroundScope callScope = copyGroundScope(&function->closure);
|
|
|
|
GroundScope callScope = {
|
|
.labels = malloc(sizeof(GroundLabel*)),
|
|
.variables = malloc(sizeof(GroundVariable*)),
|
|
.isMainScope = false
|
|
};
|
|
*callScope.variables = NULL;
|
|
*callScope.labels = NULL;
|
|
|
|
if (argc != function->argSize) {
|
|
return createErrorGroundValue(createGroundError("Too few or too many arguments for function", "callError", NULL, NULL));
|
|
}
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
GroundValue gv = va_arg(args, GroundValue);
|
|
if (checkFnTypes(&gv, &function->args[i]) == false) {
|
|
return createErrorGroundValue(createGroundError("Mismatched argument type", "callError", NULL, NULL));
|
|
}
|
|
addVariable(callScope.variables, function->args[i].name, gv);
|
|
}
|
|
va_end(args);
|
|
|
|
return interpretGroundProgram(&function->program, &callScope);
|
|
}
|
|
|
|
GroundObjectField* groundFindField(GroundObject head, const char *id) {
|
|
GroundObjectField* s;
|
|
HASH_FIND_STR(head.fields, id, s);
|
|
return s;
|
|
}
|