Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/macro proc on windows #484

Merged
merged 4 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ jobs:

- name: Summarize for PR
id: summary
if: ${{ steps.PR.outputs.number != null }}
if: steps.PR.outputs.pr_found == 'true'
shell: bash
run: |
echo "FUZZ_SUMMARY<<EOF" >> $GITHUB_ENV
Expand All @@ -256,15 +256,15 @@ jobs:
echo "EOF" >> $GITHUB_ENV

- name: Summarize
if: ${{ steps.PR.outputs.number == null }}
if: steps.PR.outputs.pr_found == 'false'
shell: bash
run: |
afl-whatsup -s -d output
afl-showmap -C -i output -o /dev/null -- ./${BUILD_FOLDER}/arkscript @@ -L ./lib

- name: Find Comment
uses: peter-evans/find-comment@v3
if: ${{ steps.PR.outputs.number != null }}
if: steps.PR.outputs.pr_found == 'true'
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
Expand All @@ -273,7 +273,7 @@ jobs:

- name: Create or update comment
uses: peter-evans/create-or-update-comment@v4
if: ${{ steps.PR.outputs.number != null }}
if: steps.PR.outputs.pr_found == 'true'
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ elseif (MSVC)
/wd4244 # disable warning about data loss (size_t -> char)
/wd4505 # disable warning about unused static function was deleted
/wd4068) # disable warnings about unknown pragmas.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8000000") # set stack size to 8MB
endif ()

# Link libraries
Expand Down
55 changes: 0 additions & 55 deletions include/Ark/Compiler/Macros/Pipeline.hpp

This file was deleted.

16 changes: 14 additions & 2 deletions include/Ark/Compiler/Macros/Processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@

#include <Ark/Compiler/AST/Node.hpp>
#include <Ark/Compiler/Macros/MacroScope.hpp>
#include <Ark/Compiler/Macros/Pipeline.hpp>

#include <unordered_map>
#include <memory>
#include <string>

namespace Ark::internal
{
class MacroExecutor;

/**
* @brief The class handling the macros definitions and calls, given an AST
*
Expand Down Expand Up @@ -55,7 +57,7 @@ namespace Ark::internal
unsigned m_debug; ///< The debug level
Node m_ast; ///< The modified AST
std::vector<MacroScope> m_macros; ///< Handling macros in a scope fashion
MacroExecutorPipeline m_executor_pipeline;
std::vector<std::shared_ptr<MacroExecutor>> m_executors;
std::vector<std::string> m_predefined_macros; ///< Already existing macros, non-keywords, non-builtins
std::unordered_map<std::string, Node> m_defined_functions;

Expand Down Expand Up @@ -162,6 +164,16 @@ namespace Ark::internal

void setWithFileAttributes(const Node origin, Node& output, const Node& macro);

/**
* @brief Check if the given node has exactly the provided argument count, otherwise throws an error
*
* @param node a list node with a macro application, eg (= a b)
* @param expected expected argument count, not counting the macro
* @param name the name of the macro being applied
* @param kind the macro kind, empty by default (eg "operator", "condition")
*/
void checkMacroArgCount(const Node& node, std::size_t expected, const std::string& name, const std::string& kind = "");

/**
* @brief Evaluate only the macros
*
Expand Down
21 changes: 0 additions & 21 deletions src/arkreactor/Compiler/Macros/Pipeline.cpp

This file was deleted.

142 changes: 99 additions & 43 deletions src/arkreactor/Compiler/Macros/Processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <Ark/Constants.hpp>
#include <Ark/Exceptions.hpp>
#include <Ark/Builtins/Builtins.hpp>
#include <Ark/Compiler/Macros/Executor.hpp>
#include <Ark/Compiler/Macros/Executors/Symbol.hpp>
#include <Ark/Compiler/Macros/Executors/Function.hpp>
#include <Ark/Compiler/Macros/Executors/Conditional.hpp>
Expand All @@ -19,10 +20,9 @@ namespace Ark::internal
m_debug(debug)
{
// create executors pipeline
m_executor_pipeline = MacroExecutorPipeline(
{ std::make_shared<SymbolExecutor>(this),
std::make_shared<ConditionalExecutor>(this),
std::make_shared<FunctionExecutor>(this) });
m_executors = { { std::make_shared<SymbolExecutor>(this),
std::make_shared<ConditionalExecutor>(this),
std::make_shared<FunctionExecutor>(this) } };

m_predefined_macros = {
"symcat",
Expand Down Expand Up @@ -205,7 +205,15 @@ namespace Ark::internal
MaxMacroProcessingDepth),
node);

return m_executor_pipeline.applyMacro(node, depth);
for (const auto& executor : m_executors)
{
if (executor->canHandle(node))
{
if (executor->applyMacro(node, depth))
return true;
}
}
return false;
}

void MacroProcessor::unify(const std::unordered_map<std::string, Node>& map, Node& target, Node* parent, const std::size_t index, const std::size_t unify_depth)
Expand Down Expand Up @@ -251,6 +259,20 @@ namespace Ark::internal
output.setPos(origin.line(), origin.col());
}

void MacroProcessor::checkMacroArgCount(const Node& node, std::size_t expected, const std::string& name, const std::string& kind)
{
const std::size_t argcount = node.constList().size();
if (argcount != expected + 1)
throwMacroProcessingError(
fmt::format(
"Interpreting a `{}'{} with {} arguments, expected {}.",
name,
kind.empty() ? kind : " " + kind,
argcount,
expected),
node);
}

Node MacroProcessor::evaluate(Node& node, unsigned depth, const bool is_not_body)
{
if (node.nodeType() == NodeType::Symbol)
Expand All @@ -262,29 +284,6 @@ namespace Ark::internal
}
if (node.nodeType() == NodeType::List && node.constList().size() > 1 && node.list()[0].nodeType() == NodeType::Symbol)
{
#define GEN_NOT_BODY(str_name, error_handler, ret) \
else if (name == (str_name) && is_not_body) \
{ \
if (node.list().size() != 3) (error_handler); \
Node one = evaluate(node.list()[1], depth + 1, is_not_body), \
two = evaluate(node.list()[2], depth + 1, is_not_body); \
return ret; \
}

#define GEN_COMPARATOR(str_name, cond) GEN_NOT_BODY( \
str_name, \
throwMacroProcessingError( \
fmt::format("Interpreting a `{}' condition with {} arguments, expected 2.", str_name, argcount), \
node), \
(cond) ? getTrueNode() : getFalseNode())

#define GEN_OP(str_name, op) GEN_NOT_BODY( \
str_name, \
throwMacroProcessingError( \
fmt::format("Interpreting a `{}' operation with {} arguments, expected 2.", str_name, argcount), \
node), \
(one.nodeType() == two.nodeType() && two.nodeType() == NodeType::Number) ? Node(one.number() op two.number()) : node)

const std::string& name = node.list()[0].string();
const std::size_t argcount = node.list().size() - 1;
if (const Node* macro = findNearestMacro(name); macro != nullptr)
Expand All @@ -293,21 +292,79 @@ namespace Ark::internal
if (node.list()[0].nodeType() == NodeType::Unused)
node.list().erase(node.constList().begin());
}
GEN_COMPARATOR("=", one == two)
GEN_COMPARATOR("!=", !(one == two))
GEN_COMPARATOR("<", one < two)
GEN_COMPARATOR(">", !(one < two) && !(one == two))
GEN_COMPARATOR("<=", one < two || one == two)
GEN_COMPARATOR(">=", !(one < two))
GEN_OP("+", +)
GEN_OP("-", -)
GEN_OP("*", *)
GEN_OP("/", /)
else if (name == "=" && is_not_body)
{
checkMacroArgCount(node, 2, "=", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one == two) ? getTrueNode() : getFalseNode();
}
else if (name == "!=" && is_not_body)
{
checkMacroArgCount(node, 2, "!=", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one != two) ? getTrueNode() : getFalseNode();
}
else if (name == "<" && is_not_body)
{
checkMacroArgCount(node, 2, "<", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one < two) ? getTrueNode() : getFalseNode();
}
else if (name == ">" && is_not_body)
{
checkMacroArgCount(node, 2, ">", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return !(one < two) && (one != two) ? getTrueNode() : getFalseNode();
}
else if (name == "<=" && is_not_body)
{
checkMacroArgCount(node, 2, "<=", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return one < two || one == two ? getTrueNode() : getFalseNode();
}
else if (name == ">=" && is_not_body)
{
checkMacroArgCount(node, 2, ">=", "condition");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return !(one < two) ? getTrueNode() : getFalseNode();
}
else if (name == "+" && is_not_body)
{
checkMacroArgCount(node, 2, "+", "operator");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one.nodeType() == two.nodeType() && two.nodeType() == NodeType::Number) ? Node(one.number() + two.number()) : node;
}
else if (name == "-" && is_not_body)
{
checkMacroArgCount(node, 2, "-", "operator");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one.nodeType() == two.nodeType() && two.nodeType() == NodeType::Number) ? Node(one.number() - two.number()) : node;
}
else if (name == "*" && is_not_body)
{
checkMacroArgCount(node, 2, "*", "operator");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one.nodeType() == two.nodeType() && two.nodeType() == NodeType::Number) ? Node(one.number() * two.number()) : node;
}
else if (name == "/" && is_not_body)
{
checkMacroArgCount(node, 2, "/", "operator");
const Node one = evaluate(node.list()[1], depth + 1, is_not_body);
const Node two = evaluate(node.list()[2], depth + 1, is_not_body);
return (one.nodeType() == two.nodeType() && two.nodeType() == NodeType::Number) ? Node(one.number() / two.number()) : node;
}
else if (name == "not" && is_not_body)
{
if (node.list().size() != 2)
throwMacroProcessingError(fmt::format("Interpreting a `not' condition with {} arguments, expected 1.", argcount), node);

checkMacroArgCount(node, 1, "not", "condition");
return (!isTruthy(evaluate(node.list()[1], depth + 1, is_not_body))) ? getTrueNode() : getFalseNode();
}
else if (name == "and" && is_not_body)
Expand Down Expand Up @@ -351,8 +408,7 @@ namespace Ark::internal
}
else if (name == "@")
{
if (node.list().size() != 3)
throwMacroProcessingError(fmt::format("Interpreting a `@' with {} arguments, expected 2.", argcount), node);
checkMacroArgCount(node, 2, "@");

Node sublist = evaluate(node.list()[1], depth + 1, is_not_body);
const Node idx = evaluate(node.list()[2], depth + 1, is_not_body);
Expand Down
Loading