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