diff --git a/src/lexer/SolsToken.h b/src/lexer/SolsToken.h index c306fb3..c3cc979 100644 --- a/src/lexer/SolsToken.h +++ b/src/lexer/SolsToken.h @@ -10,7 +10,7 @@ #include "SolsLiteral.h" typedef enum SolsTokenType { - STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO, STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END + STT_IDENTIFIER, STT_LITERAL, STT_TYPE, STT_DOT, STT_OPEN_CURLY, STT_CLOSE_CURLY, STT_OPEN_PAREN, STT_CLOSE_PAREN, STT_OP_ADD, STT_OP_SUB, STT_OP_MUL, STT_OP_DIV, STT_OP_ADDTO, STT_OP_SUBTO, STT_OP_MULTO, STT_OP_DIVTO, STT_OP_INCREMENT, STT_OP_DECREMENT, STT_OP_SET, STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER, STT_KW_DEF, STT_KW_LAMBDA, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END } SolsTokenType; typedef char* charptr; diff --git a/src/lexer/SolsType.h b/src/lexer/SolsType.h index 5723add..0d1a1e3 100644 --- a/src/lexer/SolsType.h +++ b/src/lexer/SolsType.h @@ -48,6 +48,14 @@ struct SolsTypeField; // typedef struct SolsType { SolsTypeType type; + + // For use when type is identified with a name + char* identifierType; + + // For use in functions + struct SolsType* returnType; + + // For use by fun, template, object struct { struct SolsTypeField* at; size_t count; diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index f3291bb..3611db0 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -11,6 +11,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = { {"if", STT_KW_IF}, {"while", STT_KW_WHILE}, {"def", STT_KW_DEF}, + {"lambda", STT_KW_LAMBDA}, {"struct", STT_KW_STRUCT}, {"{", STT_OPEN_CURLY}, {"}", STT_CLOSE_CURLY}, diff --git a/src/parser/SolsNode.h b/src/parser/SolsNode.h index bf983b5..8d83331 100644 --- a/src/parser/SolsNode.h +++ b/src/parser/SolsNode.h @@ -11,7 +11,7 @@ #include "../lexer/SolsToken.h" typedef enum SolsNodeType { - SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT + SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT } SolsNodeType; struct SolsNode; diff --git a/src/parser/parser.c b/src/parser/parser.c index fb8b54a..3dc6b75 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -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 (;;) {