From e368b7401e3fd46630190460ffd53e5cd82f6afe Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Sun, 1 Mar 2026 14:18:32 +1100 Subject: [PATCH] Returning from functions --- src/codegen/SolsScope.h | 1 + src/codegen/codegen.c | 34 ++++++++++++++++++++++++++-- src/lexer/SolsToken.h | 2 +- src/lexer/lexer.c | 1 + src/main.c | 4 +++- src/parser/SolsNode.h | 2 +- src/parser/parser.c | 50 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/codegen/SolsScope.h b/src/codegen/SolsScope.h index 7b0d025..1f4d12e 100644 --- a/src/codegen/SolsScope.h +++ b/src/codegen/SolsScope.h @@ -14,6 +14,7 @@ typedef struct SolsVariable { typedef struct SolsScope { SolsVariable* variables; size_t tmpCounter; + SolsType returnType; } SolsScope; // Adds a variable to the SolsScope. diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 48768cb..b1a8e26 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -38,7 +38,8 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) { case SNT_PUTS: case SNT_IF: case SNT_WHILE: - case SNT_CODE_BLOCK: { + case SNT_CODE_BLOCK: + case SNT_RETURN: { return Error(SolsType, charptr, "Specified node does not return data"); } case SNT_OP_SET: { @@ -733,7 +734,8 @@ ResultType(GroundProgram, charptr) generateLambdaNode(SolsNode* node, SolsScope* // Lambdas do NOT have access to external state SolsScope lambdaScope = { .variables = NULL, - .tmpCounter = 0 + .tmpCounter = 0, + .returnType = *node->as.type.returnType }; for (size_t i = 0; i < node->as.type.children.count; i++) { @@ -803,6 +805,9 @@ ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* sc // Create a scope for function arguments SolsScope functionScope = copySolsScope(scope); + // Set the scope's return type + functionScope.returnType = *node->as.type.returnType; + for (size_t i = 0; i < node->as.type.children.count; i++) { addVariableToScope(&functionScope, node->as.type.children.at[i].name, node->as.type.children.at[i].type); } @@ -873,6 +878,30 @@ ResultType(GroundProgram, charptr) generateFunctionCallNode(SolsNode* node, Sols } +ResultType(GroundProgram, charptr) generateReturnNode(SolsNode* node, SolsScope* scope) { + if (node->children.count < 1) { + return Error(GroundProgram, charptr, "Expecting a value in return"); + } + + ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope); + if (type.error) { + return Error(GroundProgram, charptr, type.as.error); + } + + if (compareTypes(&type.as.success, &scope->returnType) == false) { + return Error(GroundProgram, charptr, "Mismatched return type"); + } + + GroundProgram program = groundCreateProgram(); + GroundInstruction inst = groundCreateInstruction(RETURN); + + groundAddReferenceToInstruction(&inst, node->children.at[0].accessArg); + + groundAddInstructionToProgram(&program, inst); + + return Success(GroundProgram, charptr, program); +} + ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) { GroundProgram program = groundCreateProgram(); @@ -922,6 +951,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope case SNT_LAMBDA: generate(Lambda); case SNT_DEF: generate(Def); case SNT_FUNCTION_CALL: generate(FunctionCall); + case SNT_RETURN: generate(Return); } return Success(GroundProgram, charptr, program); } diff --git a/src/lexer/SolsToken.h b/src/lexer/SolsToken.h index c883ba5..d3c7466 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_LAMBDA, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA + 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_RETURN, STT_KW_STRUCT, STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE, STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA } SolsTokenType; typedef char* charptr; diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index da5b8b9..908a9d0 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -12,6 +12,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = { {"while", STT_KW_WHILE}, {"def", STT_KW_DEF}, {"lambda", STT_KW_LAMBDA}, + {"return", STT_KW_RETURN}, {"struct", STT_KW_STRUCT}, {"{", STT_OPEN_CURLY}, {"}", STT_CLOSE_CURLY}, diff --git a/src/main.c b/src/main.c index 473fed7..d429284 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include "lexer/SolsType.h" #include "lexer/lexer.h" #include "parser/parser.h" #include "codegen/codegen.h" @@ -87,7 +88,8 @@ int main(int argc, char** argv) { SolsScope scope = { .variables = NULL, - .tmpCounter = 0 + .tmpCounter = 0, + .returnType = createSolsType(STT_INT).as.success }; // Do codegen on root node diff --git a/src/parser/SolsNode.h b/src/parser/SolsNode.h index e9b75b6..f77a139 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_LAMBDA, SNT_FUNCTION_CALL, 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_FUNCTION_CALL, SNT_RETURN, 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 08c840e..db1c2a7 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1507,6 +1507,55 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser) return Success(Nothing, charptr, {}); } +static inline ResultType(Nothing, charptr) parseReturn(SolsParser* parser) { + + // Collect tokens for node + ResultType(SolsTokens, charptr) tokens = createSolsTokens(); + if (tokens.error) { + return Error(Nothing, charptr, tokens.as.error); + } + + ResultType(SolsToken, Nothing) peek = parserPeek(parser, 0); + if (peek.error) return Error(Nothing, charptr, "ruh roh"); + + for (;;) { + ResultType(SolsToken, Nothing) peek = parserPeek(parser, 1); + if (peek.error) break; + // Return and puts share the same high precedence + if (getPrecedence(&peek.as.success) <= STP_PUTS) { + break; + } + parserConsume(parser); + addTokenToSolsTokens(&tokens.as.success, peek.as.success); + } + + // Create node + ResultType(SolsNode, charptr) node = createSolsNode(SNT_RETURN); + if (node.error) return Error(Nothing, charptr, node.as.error); + node.as.success.line = peek.as.success.line; + + // Parse selected tokens + ResultType(SolsParser, charptr) returnParser = createSolsParser(&tokens.as.success); + if (returnParser.error) return Error(Nothing, charptr, returnParser.as.error); + returnParser.as.success.currentParent = &returnParser.as.success.output; + ResultType(Nothing, charptr) parsed = parse(&returnParser.as.success); + + // Add any error messages from parsing + if (parsed.error) { + addToParserErrors(parser, parsed.as.error); + return Success(Nothing, charptr, {}); + } + + // Copy nodes into the sols node + for (size_t i = 0; i < returnParser.as.success.output.children.count; i++) { + addChildToSolsNode(&node.as.success, returnParser.as.success.output.children.at[i]); + } + + addChildToSolsNode(parser->currentParent, node.as.success); + + return Success(Nothing, charptr, {}); +} + static inline ResultType(Nothing, charptr) parseOpenParen(SolsParser* parser) { return Error(Nothing, charptr, "WIP"); } @@ -1530,6 +1579,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_RETURN: PARSER_HANDLE(Return); case STT_KW_DEF: PARSER_HANDLE(Def); case STT_OP_SET: PARSER_HANDLE(Set); case STT_OP_ADD: PARSER_HANDLE(Add);