From 4c6aa97fd5c93e0debc0c9595d6c128cc8da31fc Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Thu, 11 Dec 2025 13:07:37 +1100 Subject: [PATCH] Fix type safety issue --- Makefile | 16 +++++++++++++++- README.md | 12 ++++++++++++ src/interpreter.c | 31 +++++++++++++++++++++++-------- tests/function.grnd | 2 +- tests/uhoh.grnd | 3 +++ 5 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 tests/uhoh.grnd diff --git a/Makefile b/Makefile index cb3c46b..57df3f7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,11 @@ CC = gcc -CFLAGS = -Wall -Wextra -O3 -Isrc/include -Iinclude +CFLAGS = -Wall -Wextra -Isrc/include -Iinclude LDFLAGS = +# Install paths +PREFIX ?= /usr/local +DESTDIR ?= + # Directories SRC_DIR = src BUILD_DIR = build @@ -68,6 +72,16 @@ $(BUILD_DIR) $(BIN_DIR) $(LIB_DIR) $(INC_DIR) $(OBJ_DIR): clean: rm -rf $(BUILD_DIR) +# Install executable, library, and header +.PHONY: install +install: both + mkdir -p $(DESTDIR)$(PREFIX)/bin + mkdir -p $(DESTDIR)$(PREFIX)/lib + mkdir -p $(DESTDIR)$(PREFIX)/include + cp $(EXECUTABLE) $(DESTDIR)$(PREFIX)/bin/ + cp $(SHARED_LIB) $(DESTDIR)$(PREFIX)/lib/ + cp $(HEADER) $(DESTDIR)$(PREFIX)/include/ + # Debug: print variables .PHONY: debug debug: diff --git a/README.md b/README.md index 38285e2..fabf90a 100644 --- a/README.md +++ b/README.md @@ -85,4 +85,16 @@ build - [ ] Custom data structures - [ ] Working with external libraries +## Debugger + +Ground now has an inbuilt debugger. To access this debugger, insert the `PAUSE` instruction (no arguments required) into the program. This should bring you to an interactive prompt. + +Commands: + +* continue: Continues execution of the program +* exit: Stops execution of the program early +* dump: Shows all variables and their contents +* inspect (variable): Shows the contents of a variable +* eval (code): Runs Ground code in the current scope +* help: Shows a help message diff --git a/src/interpreter.c b/src/interpreter.c index 47da9b8..b540286 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -244,6 +244,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) { runtimeError(ARG_TYPE_MISMATCH, "Expecting a TypeRef for arg 2", &in->instructions[i], i); } GroundArg* args = in->instructions[i].args.args; + function->returnType = stringToValueType(args[1].value.refName); size_t length = in->instructions[i].args.length; for (size_t j = 2; j < length; j += 2) { if (args[j].type != TYPEREF) { @@ -591,6 +592,9 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("custom")); break; } + case FUNCTION: { + addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("function")); + } case NONE: { addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("none")); } @@ -617,7 +621,6 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop } else { addVariable(scope->variables, in->args.args[1].value.refName, createBoolGroundValue(false)); } - break; } case SETLIST: { @@ -1318,16 +1321,13 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop } case CALL: { if (in->args.length < 2) { - runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction); - } - if (in->args.length > 2) { - runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction); + runtimeError(TOO_FEW_ARGS, "Expecting 2 or more args", in, currentInstruction); } if (in->args.args[0].type != FNREF) { runtimeError(ARG_TYPE_MISMATCH, "Expecting a FunctionRef for arg 1", in, currentInstruction); } - if (in->args.args[1].type != DIRREF) { - runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 2", in, currentInstruction); + if (in->args.args[in->args.length - 1].type != DIRREF) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef as the last arg", in, currentInstruction); } GroundVariable* variables = NULL; GroundLabel* labels = NULL; @@ -1343,13 +1343,28 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop runtimeError(UNKNOWN_VARIABLE, "Provided reference does not reference a function", in, currentInstruction); } GroundFunction* function = value->data.fnVal; + if (function->argSize < in->args.length - 2) { + runtimeError(TOO_FEW_ARGS, "Incorrect amount of arguments provided for function", in, currentInstruction); + } + if (function->argSize > in->args.length - 2) { + runtimeError(TOO_MANY_ARGS, "Incorrect amount of arguments provided for function", in, currentInstruction); + } + for (size_t i = 0; i < function->argSize; i++) { + if (in->args.args[i + 1].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value", in, currentInstruction); + } + if (in->args.args[i + 1].value.value.type != function->args[i].type) { + runtimeError(ARG_TYPE_MISMATCH, "Mismatched function argument types", in, currentInstruction); + } + addVariable(newScope.variables, function->args[i].name, in->args.args[i + 1].value.value); + } size_t currentCurrentInstruction = currentInstruction; currentInstruction = function->startLine; GroundValue returnValue = interpretGroundProgram(&function->program, &newScope); if (returnValue.type != function->returnType) { runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from function", in, currentInstruction); } - addVariable(scope->variables, in->args.args[1].value.refName, returnValue); + addVariable(scope->variables, in->args.args[in->args.length - 1].value.refName, returnValue); currentInstruction = currentCurrentInstruction; break; } diff --git a/tests/function.grnd b/tests/function.grnd index fb1fc5d..c7a01fb 100644 --- a/tests/function.grnd +++ b/tests/function.grnd @@ -1,5 +1,5 @@ fun !dingus -string -return "dingus" +return "dingle" endfun call !dingus &e diff --git a/tests/uhoh.grnd b/tests/uhoh.grnd new file mode 100644 index 0000000..781fde2 --- /dev/null +++ b/tests/uhoh.grnd @@ -0,0 +1,3 @@ +fun !dingle -int -function &in + call !in &tmp +endfun