Start work on lambda functions (WIP)

This commit is contained in:
2026-02-28 15:59:29 +11:00
parent cb0a1251c8
commit 92045c6bb9
5 changed files with 125 additions and 2 deletions

View File

@@ -1129,6 +1129,120 @@ static inline ResultType(Nothing, charptr) parseCloseCurly(SolsParser* parser) {
return Error(Nothing, charptr, "Extra closing curly brace");
}
static inline ResultType(Nothing, charptr) parseLambda(SolsParser* parser) {
ResultType(SolsToken, Nothing) openBracket = parserConsume(parser);
if (openBracket.error || openBracket.as.success.type != STT_OPEN_PAREN) {
return Error(Nothing, charptr, "Expecting '(' after 'lambda'");
}
ResultType(SolsType, charptr) type = createSolsType(STT_FUN);
if (type.error) {
return Error(Nothing, charptr, type.as.error);
}
ResultType(SolsNode, charptr) node = createSolsNode(SNT_LAMBDA);
if (node.error) {
return Error(Nothing, charptr, node.as.error);
}
// Parse type signature
for (;;) {
ResultType(SolsToken, Nothing) next = parserPeek(parser, 1);
if (next.error) {
return Error(Nothing, charptr, "Expecting ')' at end of lambda argument list");
}
if (next.as.success.type == STT_CLOSE_PAREN) {
parserConsume(parser);
break;
}
if (type.error) {
return Error(Nothing, charptr, type.as.error);
}
// Pattern of type, name
SolsType tmpType;
if (next.as.success.type == STT_TYPE) {
tmpType = next.as.success.as.type;
} else if (next.as.success.type == STT_IDENTIFIER) {
tmpType.identifierType = next.as.success.as.idName;
} else {
return Error(Nothing, charptr, "Expecting a type or identifier of type in lambda argument list");
}
parserConsume(parser);
char* argName;
next = parserPeek(parser, 1);
if (next.as.success.type == STT_IDENTIFIER) {
argName = next.as.success.as.idName;
} else {
return Error(Nothing, charptr, "Expecting identifier after type in lambda argument list");
}
// Add type to constructed SolsType
addChildToSolsType(&type.as.success, tmpType, argName);
parserConsume(parser);
}
// Parse type at the end
ResultType(SolsToken, Nothing) retType = parserPeek(parser, 1);
if (retType.error) {
return Error(Nothing, charptr, "Expecting return type or identifier of type after lambda argument list");
}
if (retType.as.success.type == STT_TYPE) {
type.as.success.returnType = malloc(sizeof(SolsType));
if (type.as.success.returnType == NULL) {
return Error(Nothing, charptr, "Failed to allocate memory for type");
}
*type.as.success.returnType = retType.as.success.as.type;
} else if (retType.as.success.type == STT_IDENTIFIER) {
type.as.success.returnType = malloc(sizeof(SolsType));
if (type.as.success.returnType == NULL) {
return Error(Nothing, charptr, "Failed to allocate memory for type");
}
type.as.success.returnType->identifierType = retType.as.success.as.idName;
} else {
return Error(Nothing, charptr, "Expecting return type or identifier of type after lambda argument list");
}
// Add type to node
node.as.success.as.type = type.as.success;
parserConsume(parser); // Consumes return type
// Skip newlines before the opening curly brace
while (parserPeek(parser, 1).as.success.type == STT_LINE_END) {
parserConsume(parser);
}
if (parserPeek(parser, 1).as.success.type != STT_OPEN_CURLY) {
return Error(Nothing, charptr, "Expecting opening curly brace ({) for lambda body");
}
parserConsume(parser); // Consumes {
// Add node to parent
addChildToSolsNode(parser->currentParent, node.as.success);
// Parse code block
ResultType(Nothing, charptr) res = parseCodeBlock(parser);
if(res.error) return res;
// Last child of parent is code block, we need to move it
SolsNode codeBlock = parser->currentParent->children.at[parser->currentParent->children.count - 1];
parser->currentParent->children.count--;
// We need to get the actual node from the parent to modify it
SolsNode* lambdaNode = &parser->currentParent->children.at[parser->currentParent->children.count - 1];
addChildToSolsNode(lambdaNode, codeBlock);
return Success(Nothing, charptr, {});
}
ResultType(Nothing, charptr) parse(SolsParser* parser) {
parser->currentParent = &parser->output;
for (;;) {