Call functions
This commit is contained in:
@@ -163,13 +163,14 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
|
|||||||
scope.labels = &labels;
|
scope.labels = &labels;
|
||||||
scope.variables = &variables;
|
scope.variables = &variables;
|
||||||
}
|
}
|
||||||
// Preprocess all labels
|
// Preprocess all labels and functions
|
||||||
for (int i = 0; i < in->size; i++) {
|
for (int i = 0; i < in->size; i++) {
|
||||||
if (in->instructions[i].type == CREATELABEL) {
|
if (in->instructions[i].type == CREATELABEL) {
|
||||||
addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i);
|
addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i);
|
||||||
}
|
}
|
||||||
if (in->instructions[i].type == FUN) {
|
if (in->instructions[i].type == FUN) {
|
||||||
GroundFunction* function = createGroundFunction();
|
GroundFunction* function = createGroundFunction();
|
||||||
|
function->startLine = i;
|
||||||
if (in->instructions[i].args.length < 1) {
|
if (in->instructions[i].args.length < 1) {
|
||||||
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", &in->instructions[i], i);
|
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]);
|
addInstructionToProgram(&function->program, in->instructions[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (&function->program.size == 0) {
|
|
||||||
addInstructionToProgram(&function->program, createGroundInstruction(PRINT));
|
|
||||||
}
|
|
||||||
addVariable(scope.variables, functionName, createFunctionGroundValue(function));
|
addVariable(scope.variables, functionName, createFunctionGroundValue(function));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (currentInstruction < in->size) {
|
for (int i = 0; i < in->size; i++) {
|
||||||
interpretGroundInstruction(in->instructions[currentInstruction], &scope);
|
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++;
|
currentInstruction++;
|
||||||
}
|
}
|
||||||
return createIntGroundValue(0);
|
return createNoneGroundValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
|
GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
|
||||||
@@ -1124,7 +1143,16 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
|
|||||||
* fun, return, endfun, pusharg, call
|
* fun, return, endfun, pusharg, call
|
||||||
*/
|
*/
|
||||||
case RETURN: {
|
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: {
|
case CALL: {
|
||||||
if (in->args.length < 2) {
|
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);
|
runtimeError(UNKNOWN_VARIABLE, "Provided reference does not reference a function", in, currentInstruction);
|
||||||
}
|
}
|
||||||
GroundFunction* function = value->data.fnVal;
|
GroundFunction* function = value->data.fnVal;
|
||||||
|
size_t currentCurrentInstruction = currentInstruction;
|
||||||
|
currentInstruction = function->startLine;
|
||||||
GroundValue returnValue = interpretGroundProgram(&function->program, &newScope);
|
GroundValue returnValue = interpretGroundProgram(&function->program, &newScope);
|
||||||
if (returnValue.type != function->returnType) {
|
if (returnValue.type != function->returnType) {
|
||||||
runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from function", in, currentInstruction);
|
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);
|
freeGroundInstruction(in);
|
||||||
return createIntGroundValue(0);
|
return createNoneGroundValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ GroundValue createFunctionGroundValue(GroundFunction* in) {
|
|||||||
return gv;
|
return gv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroundValue createNoneGroundValue() {
|
||||||
|
GroundValue gv;
|
||||||
|
gv.type = NONE;
|
||||||
|
return gv;
|
||||||
|
}
|
||||||
|
|
||||||
GroundValue copyGroundValue(const GroundValue* gv) {
|
GroundValue copyGroundValue(const GroundValue* gv) {
|
||||||
GroundValue newGv;
|
GroundValue newGv;
|
||||||
newGv.type = gv->type;
|
newGv.type = gv->type;
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ typedef struct GroundFunction {
|
|||||||
size_t argSize;
|
size_t argSize;
|
||||||
GroundValueType returnType;
|
GroundValueType returnType;
|
||||||
GroundProgram program;
|
GroundProgram program;
|
||||||
|
size_t startLine;
|
||||||
} GroundFunction;
|
} GroundFunction;
|
||||||
|
|
||||||
|
|
||||||
@@ -142,6 +143,9 @@ GroundValue createListGroundValue(List in);
|
|||||||
// Creates a GroundValue conatining (in), with type FUNCTION.
|
// Creates a GroundValue conatining (in), with type FUNCTION.
|
||||||
GroundValue createFunctionGroundValue(GroundFunction* in);
|
GroundValue createFunctionGroundValue(GroundFunction* in);
|
||||||
|
|
||||||
|
// Creates a Groundvalue with type NONE.
|
||||||
|
GroundValue createNoneGroundValue();
|
||||||
|
|
||||||
// Creates a deep copy of a GroundValue
|
// Creates a deep copy of a GroundValue
|
||||||
GroundValue copyGroundValue(const GroundValue* gv);
|
GroundValue copyGroundValue(const GroundValue* gv);
|
||||||
|
|
||||||
|
|||||||
19
tests/fib.grnd
Normal file
19
tests/fib.grnd
Normal file
@@ -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
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
fun !dingus -string -int &x
|
fun !dingus -string -int &x
|
||||||
|
return "dinglefart"
|
||||||
endfun
|
endfun
|
||||||
|
|
||||||
call !dingus &e
|
call !dingus &e
|
||||||
|
println $e
|
||||||
|
|||||||
Reference in New Issue
Block a user