From 166a547a74c44fca77adcec42d685c049026f096 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sat, 6 Dec 2025 14:35:13 +1100 Subject: [PATCH] Call functions --- src/interpreter.c | 53 ++++++++++++++++++++++++++++++++++++--------- src/types.c | 6 +++++ src/types.h | 4 ++++ tests/fib.grnd | 19 ++++++++++++++++ tests/function.grnd | 3 ++- 5 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 tests/fib.grnd diff --git a/src/interpreter.c b/src/interpreter.c index 653833a..843d233 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -163,13 +163,14 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) { scope.labels = &labels; scope.variables = &variables; } - // Preprocess all labels + // Preprocess all labels and functions for (int i = 0; i < in->size; i++) { if (in->instructions[i].type == CREATELABEL) { addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i); } if (in->instructions[i].type == FUN) { GroundFunction* function = createGroundFunction(); + function->startLine = i; if (in->instructions[i].args.length < 1) { runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", &in->instructions[i], i); } @@ -203,18 +204,36 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) { addInstructionToProgram(&function->program, in->instructions[i]); i++; } - if (&function->program.size == 0) { - addInstructionToProgram(&function->program, createGroundInstruction(PRINT)); - } addVariable(scope.variables, functionName, createFunctionGroundValue(function)); - } } - while (currentInstruction < in->size) { - interpretGroundInstruction(in->instructions[currentInstruction], &scope); + for (int i = 0; i < in->size; i++) { + if (in->instructions[i].type == FUN) { + int count = 1; + while (count > 0) { + i++; + if (i >= in->size) { + return createNoneGroundValue(); + } + if (in->instructions[i].type == FUN) { + count++; + } + if (in->instructions[i].type == ENDFUN) { + count--; + } + } + } + int ci = currentInstruction; + GroundValue gv = interpretGroundInstruction(in->instructions[i], &scope); + if (gv.type != NONE) { + return gv; + } + if (ci != currentInstruction) { + i = currentInstruction; + } currentInstruction++; } - return createIntGroundValue(0); + return createNoneGroundValue(); } GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) { @@ -1124,7 +1143,16 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop * fun, return, endfun, pusharg, call */ case RETURN: { - break; + if (in->args.length < 1) { + runtimeError(TOO_FEW_ARGS, "Expecting 1 arg", in, currentInstruction); + } + if (in->args.length > 1) { + runtimeError(TOO_MANY_ARGS, "Expecting 1 arg", in, currentInstruction); + } + if (in->args.args[0].type != VALUE) { + runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction); + } + return in->args.args[0].value.value; } case CALL: { if (in->args.length < 2) { @@ -1153,13 +1181,18 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop runtimeError(UNKNOWN_VARIABLE, "Provided reference does not reference a function", in, currentInstruction); } GroundFunction* function = value->data.fnVal; + 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); + currentInstruction = currentCurrentInstruction; + break; } } freeGroundInstruction(in); - return createIntGroundValue(0); + return createNoneGroundValue(); } diff --git a/src/types.c b/src/types.c index 8e6bdfd..206ff08 100644 --- a/src/types.c +++ b/src/types.c @@ -51,6 +51,12 @@ GroundValue createFunctionGroundValue(GroundFunction* in) { return gv; } +GroundValue createNoneGroundValue() { + GroundValue gv; + gv.type = NONE; + return gv; +} + GroundValue copyGroundValue(const GroundValue* gv) { GroundValue newGv; newGv.type = gv->type; diff --git a/src/types.h b/src/types.h index 2cdd6b8..d035e43 100644 --- a/src/types.h +++ b/src/types.h @@ -118,6 +118,7 @@ typedef struct GroundFunction { size_t argSize; GroundValueType returnType; GroundProgram program; + size_t startLine; } GroundFunction; @@ -142,6 +143,9 @@ GroundValue createListGroundValue(List in); // Creates a GroundValue conatining (in), with type FUNCTION. GroundValue createFunctionGroundValue(GroundFunction* in); +// Creates a Groundvalue with type NONE. +GroundValue createNoneGroundValue(); + // Creates a deep copy of a GroundValue GroundValue copyGroundValue(const GroundValue* gv); diff --git a/tests/fib.grnd b/tests/fib.grnd new file mode 100644 index 0000000..c1d9a60 --- /dev/null +++ b/tests/fib.grnd @@ -0,0 +1,19 @@ +set &a 0 +set &b 1 +set &n 92 + +set &i 0 +@loop + equal $i $n &done + if $done %end + + add $a $b &temp + set &a $b + set &b $temp + + add $i 1 &i + jump %loop + +@end +println "Fibonacci result:" $a +end diff --git a/tests/function.grnd b/tests/function.grnd index bc98f01..2d4f46d 100644 --- a/tests/function.grnd +++ b/tests/function.grnd @@ -1,5 +1,6 @@ fun !dingus -string -int &x - + return "dinglefart" endfun call !dingus &e +println $e