From df361ede5e694c41095d7be4eabf86d0ee6a1162 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Fri, 18 Apr 2025 09:53:43 +0000
Subject: [PATCH] fix function parameter parser

---
 src/Parser/Parser.cpp                   |   22 +++++++++++
 src/Parser/Parser.hpp                   |    9 ++++
 test_scripts/function_test.vs           |    7 +++
 src/Interpreter/OperationsFactory.hpp   |   19 +++++++++
 src/Interpreter/ReturnStatementNode.hpp |   40 ++++++++++++++++++++
 src/Interpreter/ReturnException.hpp     |   19 +++++++++
 src/Symbols/Value.hpp                   |    4 +-
 7 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/src/Interpreter/OperationsFactory.hpp b/src/Interpreter/OperationsFactory.hpp
index 2034a72..f69bb14 100644
--- a/src/Interpreter/OperationsFactory.hpp
+++ b/src/Interpreter/OperationsFactory.hpp
@@ -14,6 +14,7 @@
 #include "Parser/ParsedExpression.hpp"
 #include "Symbols/ParameterContainer.hpp"
 #include "Symbols/Value.hpp"
+#include "Interpreter/ReturnStatementNode.hpp"
 
 namespace Interpreter {
 
@@ -81,6 +82,24 @@
             ns,
             Operations::Operation{Operations::Type::FunctionCall, functionName, std::move(stmt)});
     }
+    /**
+     * @brief Record a return statement operation inside a function.
+     * @param pexpr Parsed expression for return value, or nullptr for void return.
+     * @param ns Current namespace (function scope).
+     * @param fileName Source filename.
+     * @param line Line number of return.
+     * @param column Column number of return.
+     */
+    static void callReturn(const Parser::ParsedExpressionPtr &pexpr,
+                           const std::string & ns,
+                           const std::string & fileName,
+                           int line,
+                           size_t column) {
+        std::unique_ptr<ExpressionNode> expr = pexpr ? buildExpressionFromParsed(pexpr) : nullptr;
+        auto stmt = std::make_unique<ReturnStatementNode>(std::move(expr), fileName, line, column);
+        Operations::Container::instance()->add(ns,
+            Operations::Operation{Operations::Type::Return, std::string(), std::move(stmt)});
+    }
 };
 
 }  // namespace Interpreter
diff --git a/src/Interpreter/ReturnException.hpp b/src/Interpreter/ReturnException.hpp
new file mode 100644
index 0000000..7c6f68b
--- /dev/null
+++ b/src/Interpreter/ReturnException.hpp
@@ -0,0 +1,19 @@
+// ReturnException.hpp
+#ifndef INTERPRETER_RETURN_EXCEPTION_HPP
+#define INTERPRETER_RETURN_EXCEPTION_HPP
+
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+/**
+ * @brief Exception used to unwind the call stack when a return statement is executed.
+ */
+class ReturnException {
+  public:
+    explicit ReturnException(const Symbols::Value &value) : value_(value) {}
+    const Symbols::Value &value() const { return value_; }
+  private:
+    Symbols::Value value_;
+};
+} // namespace Interpreter
+#endif // INTERPRETER_RETURN_EXCEPTION_HPP
\ No newline at end of file
diff --git a/src/Interpreter/ReturnStatementNode.hpp b/src/Interpreter/ReturnStatementNode.hpp
new file mode 100644
index 0000000..687031d
--- /dev/null
+++ b/src/Interpreter/ReturnStatementNode.hpp
@@ -0,0 +1,40 @@
+// ReturnStatementNode.hpp
+#ifndef INTERPRETER_RETURN_STATEMENT_NODE_HPP
+#define INTERPRETER_RETURN_STATEMENT_NODE_HPP
+
+#include <memory>
+#include <string>
+#include "StatementNode.hpp"
+#include "ExpressionNode.hpp"
+#include "ReturnException.hpp"
+#include "Symbols/Value.hpp"
+
+namespace Interpreter {
+
+/**
+ * @brief Statement node representing a return statement inside a function.
+ */
+class ReturnStatementNode : public StatementNode {
+    std::unique_ptr<ExpressionNode> expr_;
+  public:
+    explicit ReturnStatementNode(std::unique_ptr<ExpressionNode> expr,
+                                 const std::string &file_name,
+                                 int line,
+                                 size_t column) :
+        StatementNode(file_name, line, column), expr_(std::move(expr)) {}
+
+    void interpret(Interpreter &interpreter) const override {
+        Symbols::Value retVal;
+        if (expr_) {
+            retVal = expr_->evaluate(interpreter);
+        }
+        throw ReturnException(retVal);
+    }
+
+    std::string toString() const override {
+        return std::string("return") + (expr_ ? (" " + expr_->toString()) : std::string());
+    }
+};
+
+} // namespace Interpreter
+#endif // INTERPRETER_RETURN_STATEMENT_NODE_HPP
\ No newline at end of file
diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp
index 3e2bde8..3934023 100644
--- a/src/Parser/Parser.cpp
+++ b/src/Parser/Parser.cpp
@@ -142,6 +142,28 @@
         id_token.column_number);
 }
 
+// Parse a return statement, e.g., return; or return expression;
+void Parser::parseReturnStatement() {
+    // Consume 'return' keyword
+    auto returnToken = expect(Lexer::Tokens::Type::KEYWORD_RETURN);
+    // Parse optional expression
+    ParsedExpressionPtr expr = nullptr;
+    if (!(currentToken().type == Lexer::Tokens::Type::PUNCTUATION && currentToken().value == ";")) {
+        expr = parseParsedExpression(Symbols::Variables::Type::NULL_TYPE);
+    }
+    // Record return operation
+    Interpreter::OperationsFactory::callReturn(
+        expr,
+        Symbols::SymbolContainer::instance()->currentScopeName(),
+        this->current_filename_,
+        returnToken.line_number,
+        returnToken.column_number);
+    // Consume terminating semicolon
+    expect(Lexer::Tokens::Type::PUNCTUATION, ";");
+}
+
+// Continue with numeric literal parsing
+//
 Symbols::Value Parser::parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) {
     try {
         switch (type) {
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
index af087c6..0eb1180 100644
--- a/src/Parser/Parser.hpp
+++ b/src/Parser/Parser.hpp
@@ -166,12 +166,17 @@
         throw Exception(message, expected, token);
     }
 
-    // parseStatement (unchanged)
+    // parseStatement (updated to handle return)
     void parseStatement() {
         const auto & token_type = currentToken().type;
 
         if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION) {
             parseFunctionDefinition();
+            return;
+        }
+        // Return statement
+        if (token_type == Lexer::Tokens::Type::KEYWORD_RETURN) {
+            parseReturnStatement();
             return;
         }
 
@@ -194,6 +199,8 @@
     void parseFunctionDefinition();
     // Parse a top-level function call statement (e.g., foo(arg1, arg2);)
     void parseCallStatement();
+    // Parse a return statement (e.g., return; or return expr;)
+    void parseReturnStatement();
 
     // --- Parsing helper functions ---
 
diff --git a/src/Symbols/Value.hpp b/src/Symbols/Value.hpp
index fe202ea..f7040c0 100644
--- a/src/Symbols/Value.hpp
+++ b/src/Symbols/Value.hpp
@@ -88,10 +88,10 @@
         trimmed.erase(0, trimmed.find_first_not_of(" \t\n\r"));
         trimmed.erase(trimmed.find_last_not_of(" \t\n\r") + 1);
 
-        // Check bool
+        // Check bool literals
         std::string lower = trimmed;
         std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
-        if (lower == "true" || lower == "false" || lower == "1" || lower == "0") {
+        if (lower == "true" || lower == "false") {
             try {
                 return fromStringToBool(trimmed);
             } catch (...) {
diff --git a/test_scripts/function_test.vs b/test_scripts/function_test.vs
index 6f344b0..4afec4e 100644
--- a/test_scripts/function_test.vs
+++ b/test_scripts/function_test.vs
@@ -5,7 +5,9 @@
 string $variable2 = $variable;
 
 function test = (int $i) {
+    print("Param: ",$i);
     int $result = $i + 1;
+    print("The result is: ", $result);
 }
 
 function increment = (int $i) int {
@@ -13,4 +15,7 @@
 }
 
 
-increment(1);
\ No newline at end of file
+test(1);
+
+int $t = increment(2);
+print("The result is: ", $t);
\ No newline at end of file

--
Gitblit v1.9.3