#include "parser.h" #include "interpreter.h" #include "compiler.h" #include "types.h" #include #include 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; }