From 0b0823837fd6a73e1fda0bdbf0b65d51a5e7b770 Mon Sep 17 00:00:00 2001 From: Alexandre Plateau Date: Sun, 20 Oct 2024 22:37:36 +0200 Subject: [PATCH] fix(macro processor): empty\? should work with nil when evaluated as a macro tail also works in macros with non-list nodes --- src/arkreactor/Compiler/Macros/Processor.cpp | 20 ++++++++++--------- .../resources/LangSuite/macro-tests.ark | 19 ++++++++++++++++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/arkreactor/Compiler/Macros/Processor.cpp b/src/arkreactor/Compiler/Macros/Processor.cpp index 032b5a4d8..1574859b5 100644 --- a/src/arkreactor/Compiler/Macros/Processor.cpp +++ b/src/arkreactor/Compiler/Macros/Processor.cpp @@ -396,16 +396,16 @@ namespace Ark::internal { if (node.list().size() > 2) throwMacroProcessingError(fmt::format("When expanding `empty?' inside a macro, got {} arguments, expected 1", argcount), node); - if (Node& lst = node.list()[1]; lst.nodeType() == NodeType::List) // only apply len at compile time if we can + if (Node& lst = node.list()[1]; lst.nodeType() == NodeType::List && isConstEval(lst)) { - if (isConstEval(lst)) - { - if (!lst.list().empty() && lst.list()[0] == getListNode()) - setWithFileAttributes(node, node, lst.list().size() - 1 == 0 ? getTrueNode() : getFalseNode()); - else - setWithFileAttributes(node, node, lst.list().size() == 0 ? getTrueNode() : getFalseNode()); - } + // only apply len at compile time if we can + if (!lst.list().empty() && lst.list()[0] == getListNode()) + setWithFileAttributes(node, node, lst.list().size() - 1 == 0 ? getTrueNode() : getFalseNode()); + else + setWithFileAttributes(node, node, lst.list().empty() ? getTrueNode() : getFalseNode()); } + else if (lst == getNilNode()) + setWithFileAttributes(node, node, getTrueNode()); } else if (name == "@") { @@ -487,6 +487,7 @@ namespace Ark::internal else if (!sublist.list().empty()) { sublist.list().erase(sublist.constList().begin()); + sublist.list().insert(sublist.list().begin(), getListNode()); setWithFileAttributes(node, node, sublist); } else @@ -692,7 +693,8 @@ namespace Ark::internal return it != Language::operators.end() || it2 != Builtins::builtins.end() || findNearestMacro(node.string()) != nullptr || - node.string() == "list"; + node.string() == "list" || + node.string() == "nil"; } case NodeType::List: diff --git a/tests/unittests/resources/LangSuite/macro-tests.ark b/tests/unittests/resources/LangSuite/macro-tests.ark index d33598b78..faef3ddf5 100644 --- a/tests/unittests/resources/LangSuite/macro-tests.ark +++ b/tests/unittests/resources/LangSuite/macro-tests.ark @@ -27,8 +27,23 @@ (test:eq (add_two 1 2) 3) (test:eq (add_two nice_value 2) 14) - ($ c (* 4 (/ 10 2))) - (test:eq c 20) }) + ($ c (a b) (* a b)) + (test:eq (c 4 10) 40) + + ($ d (a b) (/ a b)) + (test:eq (d 10 2) 5) }) + + (test:case "node manipulation" { + ($ node_tail () (tail (begin 1 2 3))) + ($ length () (len (fun () 5))) + ($ not_empty_node () (empty? (fun () ()))) + ($ empty_node () (empty? ())) + + (test:eq (length) 3) + (test:eq (not_empty_node) false) + (test:eq (empty_node) true) + # because it removes the "begin" + (test:eq (node_tail) [1 2 3]) }) (test:case "conditional macros" { (test:expect ($if (and true true) true false))