From a9ef7c884e4c35348afd1a41c986bff1cce8a2ff Mon Sep 17 00:00:00 2001 From: Mattias Ajander <mattias@ajander.se> Date: Mon, 7 Apr 2025 00:20:12 +0200 Subject: [PATCH] WIP for command line arguemtns. Calling length on an empty args list causes segfault. --- examples/args.funk | 2 ++ include/ast/expression/MethodCallNode.h | 1 + source/ast/BlockNode.cc | 5 +++++ source/ast/declaration/VariableNode.cc | 3 ++- source/ast/expression/ListNode.cc | 2 +- source/ast/expression/MethodCallNode.cc | 6 +++++ source/parser/Parser.cc | 29 ++++++++++++++++--------- 7 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 examples/args.funk diff --git a/examples/args.funk b/examples/args.funk new file mode 100644 index 0000000..ba06c4d --- /dev/null +++ b/examples/args.funk @@ -0,0 +1,2 @@ +print("A list of arguments with length: ", ARGS.length()); +print("The arguments are:", ARGS); diff --git a/include/ast/expression/MethodCallNode.h b/include/ast/expression/MethodCallNode.h index 5242745..220a8f4 100644 --- a/include/ast/expression/MethodCallNode.h +++ b/include/ast/expression/MethodCallNode.h @@ -1,4 +1,5 @@ #pragma once +#include "ast/declaration/VariableNode.h" #include "ast/expression/CallNode.h" #include "ast/expression/ListNode.h" #include "logging/LogMacros.h" diff --git a/source/ast/BlockNode.cc b/source/ast/BlockNode.cc index 826cdfb..8f16957 100644 --- a/source/ast/BlockNode.cc +++ b/source/ast/BlockNode.cc @@ -13,6 +13,11 @@ BlockNode::~BlockNode() void BlockNode::add(Node* statement) { + if (statement == nullptr) + { + LOG_WARN("Attempted to add null statement to block"); + return; + } statements.push_back(statement); } diff --git a/source/ast/declaration/VariableNode.cc b/source/ast/declaration/VariableNode.cc index 69958e1..dbff58a 100644 --- a/source/ast/declaration/VariableNode.cc +++ b/source/ast/declaration/VariableNode.cc @@ -32,6 +32,7 @@ Node* VariableNode::evaluate() const String VariableNode::to_s() const { + if (value == nullptr) { return "Variable: " + identifier; } return "Variable: " + identifier + " = " + value->to_s(); } @@ -74,4 +75,4 @@ void VariableNode::set_value(ExpressionNode* new_value) } else { throw RuntimeError(get_location(), "Cannot modify immutable variable '" + identifier + "'"); } } -} // namespace funk \ No newline at end of file +} // namespace funk diff --git a/source/ast/expression/ListNode.cc b/source/ast/expression/ListNode.cc index a09e44c..c6837df 100644 --- a/source/ast/expression/ListNode.cc +++ b/source/ast/expression/ListNode.cc @@ -33,7 +33,7 @@ NodeValue ListNode::get_value() const { ExpressionNode* result{dynamic_cast<ExpressionNode*>(evaluate())}; if (!result) { throw RuntimeError(location, "List did not evaluate to an expression"); } - return result->get_value(); + return NodeValue(result->to_s()); } size_t ListNode::length() const diff --git a/source/ast/expression/MethodCallNode.cc b/source/ast/expression/MethodCallNode.cc index 2a4afbc..cefdb12 100644 --- a/source/ast/expression/MethodCallNode.cc +++ b/source/ast/expression/MethodCallNode.cc @@ -20,6 +20,12 @@ Node* MethodCallNode::evaluate() const Node* evaluated_object{object->evaluate()}; if (!evaluated_object) { throw RuntimeError(location, "Failed to evaluate object for method call"); } + if (auto var_node = dynamic_cast<VariableNode*>(evaluated_object)) + { + Node* var_value = var_node->get_value_node(); + if (var_value) { evaluated_object = var_value; } + } + if (auto list_node = dynamic_cast<ListNode*>(evaluated_object)) { if (identifier.get_lexeme() == "length") diff --git a/source/parser/Parser.cc b/source/parser/Parser.cc index d35ab70..2e098f2 100644 --- a/source/parser/Parser.cc +++ b/source/parser/Parser.cc @@ -10,20 +10,22 @@ Node* Parser::parse(const Vector<String>& args) { LOG_DEBUG("Parse program"); - if (!args.empty()) - { - String arg_list{}; - for (const String& arg : args) { arg_list += arg + ", "; } - LOG_INFO("Arguments: " + arg_list.substr(0, arg_list.length() - 2)); - } - - // TODO: Handle arguments - BlockNode* block = new BlockNode(SourceLocation(filename, 0, 0)); + + LOG_DEBUG("Parsing arguments"); + + // Create a Vector of ExpressionNodes for the arguments + Vector<ExpressionNode*> list{}; + // Populate the Vector with LiteralNodes + for (const String& arg : args) { list.push_back(new LiteralNode(SourceLocation(filename, 0, 0), arg)); } + // Create a ListNode for the arguments + ExpressionNode* args_list{new ListNode(SourceLocation(filename, 0, 0), TokenType::TEXT, list)}; + // Create a DeclarationNode for the arguments + block->add(new DeclarationNode(SourceLocation(filename, 0, 0), true, TokenType::TEXT, "ARGS", args_list)); + // Parse the rest of the program while (!done()) { block->add(parse_statement()); } return block; } - Parser Parser::load(String filename) { Lexer lexer{read_file(filename), filename}; @@ -72,6 +74,13 @@ Node* Parser::parse_statement() { LOG_DEBUG("Parse statement"); + if (check(TokenType::COMMENT) || check(TokenType::BLOCK_COMMENT)) + { + LOG_INFO("Skipping comment"); + next(); + return nullptr; + } + Node* control{parse_control()}; if (control) { return control; } -- GitLab