Function calling now works, only need return

This commit is contained in:
2026-03-01 13:39:27 +11:00
parent dc09883e46
commit bf71a0dfac
3 changed files with 59 additions and 27 deletions

View File

@@ -7,7 +7,7 @@ if [[ ! -v OUTPUT ]]; then
fi
if [[ ! -v CFLAGS ]]; then
CFLAGS="-O3 -Wall -Wextra -pedantic"
CFLAGS="-O3 -Wall -Wextra -pedantic -ggdb"
fi
gcc "$0" -o "$OUTPUT" $CFLAGS -lgroundvm

View File

@@ -756,12 +756,31 @@ ResultType(GroundProgram, charptr) generateLambdaNode(SolsNode* node, SolsScope*
ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* scope) {
GroundProgram gp = groundCreateProgram();
// Register the function in the current scope so calls can resolve it
// node->children.at[0] is the identifier node for the function name
if (node->children.count < 2 || node->children.at[0].type != SNT_IDENTIFIER) {
return Error(GroundProgram, charptr, "Invalid def node shape (expected name + body)");
}
char* fnName = node->children.at[0].as.idName;
SolsVariable* existing = findSolsVariable(scope, fnName);
if (existing == NULL) {
addVariableToScope(scope, fnName, node->as.type);
} else {
if (existing->typeinfo.type != STT_FUN) {
return Error(GroundProgram, charptr, "A non-function variable already exists with this name");
}
if (compareTypes(&existing->typeinfo, &node->as.type) == false) {
return Error(GroundProgram, charptr, "Function already exists with a different type signature");
}
}
// Generate function signature
GroundInstruction signature = groundCreateInstruction(FUN);
node->accessArg = groundCreateReference(VALREF, node->children.at[0].as.idName);
node->accessArg = groundCreateReference(VALREF, fnName);
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, node->children.at[0].as.idName));
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, fnName));
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType);
if (arg.error) {
return Error(GroundProgram, charptr, arg.as.error);

View File

@@ -1413,47 +1413,54 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
return Error(Nothing, charptr, node.as.error);
}
ResultType(SolsToken, Nothing) idToken = parserPeek(parser, -1);
if (idToken.error) {
return Error(Nothing, charptr, "Couldn't get id token for some odd reason");
// The identifier (function name) was already parsed as a node right before '('
if (parser->currentParent->children.count < 1 ||
parser->currentParent->children.at[parser->currentParent->children.count - 1].type != SNT_IDENTIFIER) {
return Error(Nothing, charptr, "Expecting identifier before '(' for function call");
}
node.as.success.as.idName = idToken.as.success.as.idName;
SolsNode callee = parser->currentParent->children.at[parser->currentParent->children.count - 1];
parser->currentParent->children.count--; // remove callee identifier node; we'll replace it with the call node
// create a node for each expression between commas
node.as.success.as.idName = callee.as.idName;
node.as.success.line = callee.line;
// Empty argument list: foo()
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 1);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')' or a value");
}
SolsTokens tokens;
if (peek.as.success.type == STT_CLOSE_PAREN) {
parserConsume(parser); // consume ')'
addChildToSolsNode(parser->currentParent, node.as.success);
return Success(Nothing, charptr, {});
}
// Parse each argument expression separated by commas until ')'
for (;;) {
ResultType(SolsTokens, charptr) resultTokens = createSolsTokens();
if (resultTokens.error) {
return Error(Nothing, charptr, resultTokens.as.error);
}
tokens = resultTokens.as.success;
SolsTokens tokens = resultTokens.as.success;
size_t curlys = 0;
size_t parens = 0;
for (;;) {
peek = parserPeek(parser, 1);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')'");
}
if (peek.as.success.type == STT_OPEN_PAREN) {
parens++;
}
if (peek.as.success.type == STT_OPEN_PAREN) parens++;
if (peek.as.success.type == STT_CLOSE_PAREN) {
if (parens == 0) {
break;
}
if (parens == 0) break;
parens--;
}
if (peek.as.success.type == STT_OPEN_CURLY) {
curlys++;
}
if (peek.as.success.type == STT_CLOSE_CURLY) {
curlys--;
}
if (peek.as.success.type == STT_OPEN_CURLY) curlys++;
if (peek.as.success.type == STT_CLOSE_CURLY) curlys--;
if (curlys == 0 && parens == 0 && peek.as.success.type == STT_COMMA) {
break;
@@ -1468,6 +1475,7 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
return Error(Nothing, charptr, newParser.as.error);
}
newParser.as.success.currentParent = &newParser.as.success.output;
ResultType(Nothing, charptr) parsed = parse(&newParser.as.success);
if (parsed.error) {
addToParserErrors(parser, parsed.as.error);
@@ -1477,8 +1485,11 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
if (newParser.as.success.output.children.count < 1) {
return Error(Nothing, charptr, "Expecting a value before ',' or ')'");
}
// One argument expression -> one AST node
addChildToSolsNode(&node.as.success, newParser.as.success.output.children.at[0]);
// Consume ',' or ')'
peek = parserConsume(parser);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')' or ','");
@@ -1486,11 +1497,13 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
if (peek.as.success.type == STT_CLOSE_PAREN) {
break;
}
addChildToSolsNode(parser->currentParent, node.as.success);
if (peek.as.success.type != STT_COMMA) {
return Error(Nothing, charptr, "Expecting ',' or ')'");
}
}
// Add the fully-built call node once
addChildToSolsNode(parser->currentParent, node.as.success);
return Success(Nothing, charptr, {});
}