Function definitions

This commit is contained in:
2026-02-28 20:27:47 +11:00
parent a434304e95
commit 955927e021
2 changed files with 196 additions and 1 deletions

View File

@@ -1261,6 +1261,151 @@ static inline ResultType(Nothing, charptr) parseLambda(SolsParser* parser) {
return Success(Nothing, charptr, {});
}
static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
// Consume and validate the function name identifier
ResultType(SolsToken, Nothing) nameTok = parserConsume(parser);
if (nameTok.error || nameTok.as.success.type != STT_IDENTIFIER) {
return Error(Nothing, charptr, "Expecting function name after 'def'");
}
ResultType(SolsToken, Nothing) openBracket = parserConsume(parser);
if (openBracket.error || openBracket.as.success.type != STT_OPEN_PAREN) {
return Error(Nothing, charptr, "Expecting '(' after function name in 'def'");
}
ResultType(SolsType, charptr) type = createSolsType(STT_FUN);
if (type.error) {
return Error(Nothing, charptr, type.as.error);
}
ResultType(SolsNode, charptr) node = createSolsNode(SNT_DEF);
if (node.error) {
return Error(Nothing, charptr, node.as.error);
}
// Add function name as the first child node
ResultType(SolsNode, charptr) nameNode = createSolsNode(SNT_IDENTIFIER, nameTok.as.success.as.idName);
if (nameNode.error) {
return Error(Nothing, charptr, nameNode.as.error);
}
nameNode.as.success.line = nameTok.as.success.line;
nameNode.as.success.accessArg = (GroundArg) {
.type = VALREF,
.value.refName = nameTok.as.success.as.idName
};
addChildToSolsNode(&node.as.success, nameNode.as.success);
// Parse type signature
for (;;) {
ResultType(SolsToken, Nothing) next = parserPeek(parser, 1);
if (next.error) {
return Error(Nothing, charptr, "Expecting ')' at end of def 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, comma
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 def 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 def argument list");
}
// Add type to constructed SolsType
addChildToSolsType(&type.as.success, tmpType, argName);
parserConsume(parser);
next = parserPeek(parser, 1);
if (next.error) {
return Error(Nothing, charptr, "Expecting a comma or closing bracket");
}
if (next.as.success.type == STT_CLOSE_PAREN) {
parserConsume(parser);
break;
}
if (next.as.success.type != STT_COMMA) {
return Error(Nothing, charptr, "Expecting a comma or closing bracket");
}
parserConsume(parser);
}
// Parse return type after argument list
ResultType(SolsToken, Nothing) retType = parserPeek(parser, 1);
if (retType.error) {
return Error(Nothing, charptr, "Expecting return type or identifier of type after def 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 def 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);
}
ResultType(SolsToken, Nothing) openCurly = parserConsume(parser);
if (openCurly.error || openCurly.as.success.type != STT_OPEN_CURLY) {
return Error(Nothing, charptr, "Expecting opening curly brace ({) for def body");
}
// 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* defNode = &parser->currentParent->children.at[parser->currentParent->children.count - 1];
addChildToSolsNode(defNode, codeBlock);
return Success(Nothing, charptr, {});
}
ResultType(Nothing, charptr) parse(SolsParser* parser) {
parser->currentParent = &parser->output;
for (;;) {
@@ -1275,6 +1420,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
case STT_KW_IF: PARSER_HANDLE(If);
case STT_KW_WHILE: PARSER_HANDLE(While);
case STT_KW_LAMBDA: PARSER_HANDLE(Lambda);
case STT_KW_DEF: PARSER_HANDLE(Def);
case STT_OP_SET: PARSER_HANDLE(Set);
case STT_OP_ADD: PARSER_HANDLE(Add);
case STT_OP_SUB: PARSER_HANDLE(Sub);