Start work on lambda functions (WIP)
This commit is contained in:
@@ -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 (;;) {
|
||||
|
||||
Reference in New Issue
Block a user