From 3c1224e937e8f4cff59f13478ee23aeaa2a53d13 Mon Sep 17 00:00:00 2001 From: "anthony@rabine.fr" Date: Tue, 22 Apr 2025 16:35:50 +0200 Subject: [PATCH] Better custom AST builder using kahn algorithm --- .vscode/settings.json | 3 +- core/chip32/tests/test_parser.cpp | 7 +- core/story-manager/lib/variable.h | 133 ++++++++- .../src/compiler/assembly_generator.h | 57 +++- .../src/compiler/assembly_generator_chip32.h | 138 +++++++-- core/story-manager/src/compiler/ast_builder.h | 265 ++++++++---------- core/story-manager/src/compiler/compiler.h | 8 +- .../src/compiler/flow_generator.h | 44 +-- core/story-manager/src/media_node.cpp | 1 - core/story-manager/src/nodes/base_node.cpp | 10 + core/story-manager/src/nodes/base_node.h | 30 +- core/story-manager/src/nodes/branch_node.cpp | 8 - core/story-manager/src/nodes/branch_node.h | 1 - core/story-manager/src/nodes/compare_node.cpp | 8 - core/story-manager/src/nodes/compare_node.h | 1 - core/story-manager/src/nodes/execution_node.h | 36 --- .../src/nodes/function_entry_node.h | 14 +- .../src/nodes/function_exit_node.h | 5 - .../story-manager/src/nodes/function_node.cpp | 9 - core/story-manager/src/nodes/function_node.h | 1 - core/story-manager/src/nodes/operator_node.h | 50 ---- core/story-manager/src/nodes/print_node.cpp | 40 +-- core/story-manager/src/nodes/print_node.h | 21 +- .../story-manager/src/nodes/variable_node.cpp | 9 - core/story-manager/src/nodes/variable_node.h | 79 +----- core/story-manager/src/story_page.h | 10 +- core/story-manager/tests/test_ast.cpp | 179 ++++++------ 27 files changed, 568 insertions(+), 599 deletions(-) delete mode 100644 core/story-manager/src/nodes/execution_node.h diff --git a/.vscode/settings.json b/.vscode/settings.json index d1b56c6..cf08623 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -109,7 +109,8 @@ "text_encoding": "cpp", "serializers.h": "c", "ni_parser.h": "c", - "*.m": "cpp" + "*.m": "cpp", + "*.inc": "cpp" } } \ No newline at end of file diff --git a/core/chip32/tests/test_parser.cpp b/core/chip32/tests/test_parser.cpp index f0ea324..befa605 100644 --- a/core/chip32/tests/test_parser.cpp +++ b/core/chip32/tests/test_parser.cpp @@ -36,7 +36,6 @@ Purpose: grammar, ram usage and macros, rom code generation void hexdump(void *ptr, int buflen); static const std::string test1 = R"(; jump over the data, to our entry label - jump .entry $imageBird DC8 "example.bmp", 8 ; data $someConstant DC32 12456789 @@ -46,7 +45,7 @@ $RamData1 DV32 1 ; one 32-bit integer $MyArray DV8 10 ; array of 10 bytes ; label definition -.entry: ;; comment here should work +.main: ;; comment here should work ; We create a stupid loop just for RAM variable testing lcons r0, 4 ; prepare loop: 4 iterations @@ -183,14 +182,12 @@ static const std::string testPrintf = R"( ; ======================================================== ; We test the printf system call ; ======================================================== -jump .entry - $printHello DC8 "La réponse est %d" $answer DC32 42 $counter DV32 10 -.entry: +.main: ; prepapre loop diff --git a/core/story-manager/lib/variable.h b/core/story-manager/lib/variable.h index a286204..8bc80eb 100644 --- a/core/story-manager/lib/variable.h +++ b/core/story-manager/lib/variable.h @@ -2,19 +2,128 @@ #include #include +#include -struct Variable { - static const uint32_t NameMaxSize = 50; - std::string name; // Nom de la variable - std::string type; // Type de la variable (par exemple int32_t, int64_t) - int64_t value; // Valeur stockée en tant qu'entier en virgule fixe - std::string valueText; - int scalePower; // Nombre de bits pour la partie fractionnaire +#include "uuid.h" - Variable(const std::string &n, const std::string &t, int64_t v, int s) { - name = n; - type = t; - value = v; - scalePower = s; +class Variable +{ + +public: + enum class ValueType { + INTEGER, + FLOAT, + BOOL, + STRING + }; + + + // Setters + + void SetUuid(const std::string& uuid) { + m_uuid = uuid; } + + void SetVariableName(const std::string& name) { + m_variableName = name; + } + + void SetConstant(bool isConstant) { + m_isConstant = isConstant; + } + + void SetValueType(ValueType type) { + m_valueType = type; + // Reset value to default for new type + switch (type) { + case ValueType::INTEGER: + m_value = 0; + break; + case ValueType::FLOAT: + m_value = 0.0f; + break; + case ValueType::BOOL: + m_value = false; + break; + case ValueType::STRING: + m_value = ""; + break; + } + } + + template + void SetValue(const T& value) { + try { + m_value = value; + } catch (const std::bad_variant_access&) { + throw std::runtime_error("[variable.h] SetValue(): Invalid value type for variable"); + } + } + + void SetTextValue(const std::string& value) { + SetValue(value); + m_valueType = ValueType::STRING; + } + + void SetIntegerValue(int value) { + SetValue(value); + m_valueType = ValueType::INTEGER; + } + + void SetFloatValue(float value) { + SetValue(value); + m_valueType = ValueType::FLOAT; + } + + void SetBoolValue(bool value) { + SetValue(value); + m_valueType = ValueType::BOOL; + } + + // Getters + std::string GetVariableName() const { + return m_variableName; + } + + bool IsConstant() const { + return m_isConstant; + } + + ValueType GetValueType() const { + return m_valueType; + } + + template + T GetValue() const { + try { + return std::get(m_value); + } catch (const std::bad_variant_access&) { + throw std::runtime_error("[variable.h] GetValue(): Invalid value type requested"); + } + } + + using VariableValue = std::variant; + + std::string GetUuid() const { + return m_uuid; + } + + Variable() { + m_uuid = Uuid().String(); + } + + Variable (const std::string &name) + : Variable() + { + m_variableName = name; + } + +private: + std::string m_variableName; + ValueType m_valueType; + VariableValue m_value; + bool m_isConstant; + std::string m_uuid; + int m_scalePower; // Nombre de bits pour la partie fractionnaire + }; diff --git a/core/story-manager/src/compiler/assembly_generator.h b/core/story-manager/src/compiler/assembly_generator.h index d50437f..1c9eacc 100644 --- a/core/story-manager/src/compiler/assembly_generator.h +++ b/core/story-manager/src/compiler/assembly_generator.h @@ -15,12 +15,10 @@ #include "variable_node.h" #include "branch_node.h" #include "operator_node.h" +#include "base_node.h" - - - -class AssemblyGenerator { +class AssemblyGenerator : public IVariableVisitor { public: struct GeneratorContext { std::string timestamp; @@ -58,9 +56,10 @@ public: m_currentSection = Section::NONE; } - std::string GenerateAssembly(std::vector> &nodes, const std::vector& roots) + std::string GenerateAssembly(std::vector> &nodes, const std::vector& roots, const std::vector> &variables) { m_roots = roots; + /* Reset(); // Generate header comments @@ -68,11 +67,31 @@ public: // Generate data section StartSection(Section::DATA); - GenerateDataSection(nodes, roots); + GenerateDataSection(nodes, roots, variables); // Generate text section StartSection(Section::TEXT); GenerateTextSection(roots); +*/ + return m_assembly.str(); + } + + + std::string GenerateAssembly(std::vector> &nodes, const std::vector>& order, const std::vector> &variables) + { + // m_roots = roots; + Reset(); + + // Generate header comments + GenerateHeader(); + + // Generate data section + StartSection(Section::DATA); + GenerateDataSection(nodes, variables); + + // Generate text section + StartSection(Section::TEXT); + GenerateTextSection(order); return m_assembly.str(); } @@ -139,14 +158,19 @@ private: } } - void GenerateDataSection(const std::vector> &nodes, const std::vector& trees) { - + void GenerateDataSection(const std::vector> &nodes, const std::vector> &variables) + { // Generate all constants for (const auto& n : nodes) { - m_assembly << n->GenerateConstants(); + n->Accept(*this); } + + m_assembly << "\n\n"; + // Generate all + +/* // Generate string literals for (const auto& literal : m_stringLiterals) { std::string label = "str_" + std::to_string(m_labelCounter++); @@ -158,11 +182,19 @@ private: for (const auto& t : trees) { CollectVariables(t.root); } + + */ } - void GenerateTextSection(const std::vector& trees) { + void GenerateTextSection(const std::vector>& orderedNodes) { // Program entry point m_assembly << ".main:\n"; + + for (const auto& node : orderedNodes) { + GenerateNodeCode(node); + } + + /* // Process execution paths first for (const auto& tree : trees) { @@ -177,6 +209,7 @@ private: GenerateNodeCode(tree.root, true); } } + */ // Program exit GenerateExit(); @@ -187,11 +220,13 @@ private: if (node->IsType()) { auto* varNode = node->GetAs(); - std::string varName = varNode->GetVariableName(); + /* + std::string varName = varNode->GetN(); if (m_variableAddresses.find(varName) == m_variableAddresses.end()) { m_variableAddresses[varName] = varName; m_assembly << varName << ":\n" << varNode->GenerateAssembly(); } + */ } // Traverse children diff --git a/core/story-manager/src/compiler/assembly_generator_chip32.h b/core/story-manager/src/compiler/assembly_generator_chip32.h index fc0b003..a1ed336 100644 --- a/core/story-manager/src/compiler/assembly_generator_chip32.h +++ b/core/story-manager/src/compiler/assembly_generator_chip32.h @@ -21,20 +21,23 @@ public: if (m_context.debugOutput) { AddComment("Node: " + node->node->GetTypeName() + " (ID: " + node->node->GetId() + ")"); } - +/* if (isDataPath) { - if (node->IsType()) { - GenerateOperatorNode(node); - } - else if (node->IsType()) { - GenerateVariableNode(node); - } + + // else if (node->IsType()) { + // GenerateVariableNode(node); + // } } else { - if (node->IsType()) { + + */ + if (node->IsType()) { + GenerateOperatorNode(node); + } + else if (node->IsType()) { GenerateFunctionEntry(node); } else if (node->IsType()) { @@ -43,7 +46,7 @@ public: else if (node->IsType()) { GeneratePrintNode(node); } - } + // } // If we're processing a data path, traverse data outputs if (isDataPath) { @@ -73,9 +76,9 @@ private: AddComment("Function Entry"); m_depth++; - for (auto& child : node->children) { - GenerateNodeCode(child); - } + // for (auto& child : node->children) { + // GenerateNodeCode(child); + // } m_depth--; } @@ -92,14 +95,14 @@ private: // Generate condition code // We search a path tree that have a last node equivalent to our node // (this is the input of the condition) - +/* auto lastNode = std::find_if(m_roots.begin(), m_roots.end(), [&node](const PathTree& tree) { return tree.lastNode && tree.lastNode->node->GetId() == node->node->GetId(); }); AddComment("Last node: " + lastNode->lastNode->node->GetTypeName() + " (ID: " + lastNode->lastNode->node->GetId() + ")"); - + */ // Compare result and jump m_assembly << " pop eax\n" @@ -127,15 +130,19 @@ private: auto* printNode = node->GetAs(); if (!printNode) return; - std::string text = printNode->GetText(); - std::string label = AddStringLiteral(text); + std::string label = printNode->GetLabel(); + + + m_assembly << " push r0\n" + << " push r1\n" + << " lcons r0, $" << label << "\n" + << " lcons r1, 0 ; number of arguments\n" // FIXME: handle arguments + << " syscall 4\n" + << " pop r1\n" + << " pop r0\n"; + +// << ""mov r2, %2 // arguments are in r2, r3, r4 etc. - // System call to write - m_assembly << " mov edx, " << label << "_len\n" - << " mov ecx, " << label << "\n" - << " mov ebx, 1\n" // stdout - << " mov eax, 4\n" // sys_write - << " int 0x80\n"; } void GenerateOperatorNode(std::shared_ptr node) { @@ -145,10 +152,11 @@ private: AddComment("Operator: " + std::to_string(static_cast(opNode->GetOperationType()))); m_depth++; - // Generate code for operands + // Generate code for variables for (const auto& [port, inputNode] : node->dataInputs) { - GenerateNodeCode(inputNode); + // m_assembly << " load r0, " << inputNode.node->GetId() << "\n"; } + // Generate operator code switch (opNode->GetOperationType()) { @@ -178,11 +186,91 @@ private: << " push eax\n"; break; // Add other operators... + +/* + + + std::string GenerateAssembly() const override { + std::stringstream ss; + + switch (m_operationType) { + case OperationType::ADD: + ss << " pop ebx\n" + << " pop eax\n" + << " add eax, ebx\n" + << " push eax\n"; + break; + case OperationType::SUBTRACT: + ss << " pop ebx\n" + << " pop eax\n" + << " sub eax, ebx\n" + << " push eax\n"; + break; + case OperationType::MULTIPLY: + ss << " pop ebx\n" + << " pop eax\n" + << " imul eax, ebx\n" + << " push eax\n"; + break; + case OperationType::DIVIDE: + ss << " pop ebx\n" + << " pop eax\n" + << " cdq\n" // Sign extend eax into edx + << " idiv ebx\n" + << " push eax\n"; // Push quotient + break; + case OperationType::AND: + ss << " pop ebx\n" + << " pop eax\n" + << " and eax, ebx\n" + << " push eax\n"; + break; + case OperationType::OR: + ss << " pop ebx\n" + << " pop eax\n" + << " or eax, ebx\n" + << " push eax\n"; + break; + // Add other operators... + } + + return ss.str(); + } + + +*/ + + + } m_depth--; } + virtual void Visit(const std::shared_ptr v) override + { + if (v->IsConstant()) + { + if (v->GetValueType() == Variable::ValueType::STRING) + { + m_assembly << "$" << v->GetVariableName() << " DC8, \"" << v->GetValue() << "\"\n"; + } + else if (v->GetValueType() == Variable::ValueType::INTEGER) + { + m_assembly << "$" << v->GetVariableName() << " DC32, " << v->GetValue() << "\n"; + } + else if (v->GetValueType() == Variable::ValueType::FLOAT) + { + m_assembly << "$" << v->GetVariableName() << " DC32, " << v->GetValue() << "\n"; + } + else if (v->GetValueType() == Variable::ValueType::BOOL) + { + m_assembly << "$" << v->GetVariableName() << " DCB, " << (v->GetValue() ? "1" : "0") << "\n"; + } + + } + } +/* void GenerateVariableNode(std::shared_ptr node) { auto* varNode = node->GetAs(); if (!varNode) return; @@ -193,7 +281,7 @@ private: m_assembly << " mov eax, [" << m_variableAddresses[varName] << "]\n" << " push eax\n"; } - +*/ }; diff --git a/core/story-manager/src/compiler/ast_builder.h b/core/story-manager/src/compiler/ast_builder.h index a9ffd54..c0209c6 100644 --- a/core/story-manager/src/compiler/ast_builder.h +++ b/core/story-manager/src/compiler/ast_builder.h @@ -107,6 +107,14 @@ public: return dynamic_cast(node.get()); } + std::string GetId() const { + return node->GetId(); + } + + int GetWeight() const { + return node->GetWeight(); + } + // Debug information std::string GetDebugString() const { std::string result = "Node: " + node->GetTypeName() + " (ID: " + node->GetId() + ")\n"; @@ -150,82 +158,44 @@ public: const std::vector>& connections) : m_nodes(nodes), m_connections(connections) {} - std::vector BuildAST() { + std::vector> BuildAST() + { // Create node map for quick lookups - std::unordered_map> nodeMap; + std::unordered_map> nodeMap; for (const auto& node : m_nodes) { - nodeMap[node->GetId()] = node; + nodeMap[node->GetId()] = std::make_shared(node); } - // Find all root nodes (nodes without incoming execution connections) - std::unordered_set hasIncomingExec; - std::unordered_set hasIncomingData; + // Build adjacency list for the nodes from the connections for (const auto& conn : m_connections) { - if (conn->type == Connection::EXECUTION_LINKJ) { - hasIncomingExec.insert(conn->inNodeId); - } else { - hasIncomingData.insert(conn->inNodeId); + + // Don't add the variables nodes, as they are input data nodes. + auto rawNode = nodeMap[conn->outNodeId].get()->node; + + if (dynamic_cast(rawNode.get())) { + continue; } + m_adjList[conn->outNodeId].push_back(conn->inNodeId); } - // Collect root nodes - std::vector> execRoots; - std::vector> dataRoots; + std::vector> topologicalOrder = ApplyKahnAlgorithm(nodeMap); - for (const auto& node : m_nodes) { - if (hasIncomingExec.find(node->GetId()) == hasIncomingExec.end()) { - if (dynamic_cast(node.get())) { - execRoots.push_back(node); - } - } - // Nodes that have data outputs but no data inputs are data path roots - if ((hasIncomingData.find(node->GetId()) == hasIncomingData.end()) || - AreAllInputsVariables(node, nodeMap)) + // Maintenant, on va ajouter les connexions de données + for (const auto& conn : m_connections) + { + auto outNode = nodeMap[conn->outNodeId]; + auto inNode = nodeMap[conn->inNodeId]; + + // Keep variables nodes as data inputs + if (dynamic_cast(outNode->node.get())) { - // Check if the node has any outgoing data connections - bool hasDataOutput = false; - for (const auto& conn : m_connections) - { - if (conn->type == Connection::DATA_LINK && - conn->outNodeId == node->GetId()) { - hasDataOutput = true; - break; - } - } - - if (hasDataOutput && !(dynamic_cast(node.get()))) - { - dataRoots.push_back(node); - } - - // if (hasDataOutput) { - // dataRoots.push_back(node); - // } + inNode->AddDataInput(conn->inPortIndex, outNode); } } - std::vector pathTrees; + return topologicalOrder; - // Build execution path trees - for (const auto& root : execRoots) { - PathTree tree; - tree.root = std::make_shared(root); - tree.isExecutionPath = true; - BuildExecutionPath(tree, nodeMap); - pathTrees.push_back(tree); - } - - // Build data path trees - for (const auto& root : dataRoots) { - PathTree tree; - tree.root = std::make_shared(root); - tree.isExecutionPath = false; - BuildDataPath(tree, nodeMap); - pathTrees.push_back(tree); - } - - return pathTrees; } private: @@ -233,6 +203,89 @@ private: const std::vector>& m_connections; + + std::vector> ApplyKahnAlgorithm(const std::unordered_map> &nodeMap) + { + + // Pour le container de la queue, on utilise un comparateur pour trier les noeuds par poids + // Cela permet de prioriser les noeuds avec un poids plus faible + auto compare = [](const std::shared_ptr& a, const std::shared_ptr& b) { + return a->GetWeight() < b->GetWeight(); + }; + std::priority_queue, std::vector>, decltype(compare)> queue(compare); + + // std::queue q; + std::unordered_map inDegree; + + std::vector> res; + int visitedCount = 0; + + // Calculate indegree + for (auto p: m_adjList) + { + std::string u = p.first; + + // On initialise à zéro si le node n'est pas dans la liste + if (inDegree.find(u) == inDegree.end()) + { + inDegree[u] = 0; + } + + for (auto v: p.second) + { + inDegree[v]++; + } + } + + // insert vertices with 0 indegree in queue + for (auto i: inDegree) + { + if (i.second == 0) + { + queue.push(nodeMap.at(i.first)); + } + } + + // Process the queue + while(!queue.empty()) + { + auto x = queue.top(); + queue.pop(); + visitedCount++; + + res.push_back(x); + + // Reduce indegree of neighbours + for (auto dest: m_adjList[x->GetId()]) + { + inDegree[dest]--; + if (inDegree[dest] == 0) + { + queue.push(nodeMap.at(dest)); + } + } + } + + if (visitedCount != nodeMap.size()) { + // cout << "There exists a cycle in the graph"; + // throw std::runtime_error("Graph has a cycle"); + } + + // Debug: print in the console all the nodes in topological order + std::cout << "Topological order: \n\n"; + for (const auto& a : res) + { + std::cout << a->node->GetTypeName() << " (" << a->GetId() << ") \n"; + } + + return res; + } + + + // Ids (UUID strings) of nodes + std::unordered_map> m_adjList; + + bool AreAllInputsVariables(const std::shared_ptr& node, const std::unordered_map>& nodeMap) const { for (const auto& conn : m_connections) @@ -246,97 +299,9 @@ private: } } } - return true; + return true; } - void BuildExecutionPath(PathTree& tree, - const std::unordered_map>& nodeMap) { - std::queue> queue; - queue.push(tree.root); - while (!queue.empty()) { - auto current = queue.front(); - queue.pop(); - // Find execution connections from this node - for (const auto& conn : m_connections) { - if (conn->type == Connection::EXECUTION_LINKJ && - conn->outNodeId == current->node->GetId()) { - auto targetNode = nodeMap.find(conn->inNodeId); - if (targetNode != nodeMap.end()) { - auto childNode = std::make_shared(targetNode->second); - current->children.push_back(childNode); - queue.push(childNode); - tree.connections.push_back(conn); - - // For each execution node, find its data inputs - BuildDataInputs(childNode, nodeMap); - } - } - } - } - } - - void BuildDataPath(PathTree& tree, - const std::unordered_map>& nodeMap) { - std::queue> queue; - queue.push(tree.root); - std::unordered_set visited; - - std::shared_ptr currentLastNode = nullptr; - - while (!queue.empty()) { - auto current = queue.front(); - queue.pop(); - - if (visited.find(current->node->GetId()) != visited.end()) { - continue; - } - - currentLastNode = current; // Met à jour le dernier nœud visité - visited.insert(current->node->GetId()); - - // Find data connections from this node - for (const auto& conn : m_connections) { - if (conn->type == Connection::DATA_LINK && - conn->outNodeId == current->node->GetId()) { - auto targetNode = nodeMap.find(conn->inNodeId); - if (targetNode != nodeMap.end()) { - auto childNode = std::make_shared(targetNode->second); - - // Add childNode as a children only if it is not an execution node - // Otherwise, the assembly code will be generated twice - if (childNode->IsDataNode()) - { - current->dataOutputs[conn->outPortIndex].push_back({childNode, conn->inPortIndex}); - } - queue.push(childNode); - tree.connections.push_back(conn); - } - } - } - } - - // On garde la trace du dernier nœud visité - // De cette façon on va pouvoir savoir à quel nœud on doit se connecter - // pour la génération de code - tree.lastNode = currentLastNode; - } - - void BuildDataInputs(std::shared_ptr node, - const std::unordered_map>& nodeMap) { - for (const auto& conn : m_connections) { - if (conn->type == Connection::DATA_LINK && - conn->inNodeId == node->node->GetId()) { - auto sourceNode = nodeMap.find(conn->outNodeId); - if (sourceNode != nodeMap.end()) { - auto inputNode = std::make_shared(sourceNode->second); - node->dataInputs[conn->inPortIndex] = inputNode; - } - } - } - } }; diff --git a/core/story-manager/src/compiler/compiler.h b/core/story-manager/src/compiler/compiler.h index d751d2a..6c5e03c 100644 --- a/core/story-manager/src/compiler/compiler.h +++ b/core/story-manager/src/compiler/compiler.h @@ -188,10 +188,10 @@ public: } }; - // Generate all constants - for (const auto& astNode : m_ast.nodeMap) { - assemblyCode << astNode.second->node->GenerateConstants(); - } + // // Generate all constants + // for (const auto& astNode : m_ast.nodeMap) { + // assemblyCode << astNode.second->node->GenerateConstants(); + // } // After the constants, the main entry point: assemblyCode << ".main:\n"; diff --git a/core/story-manager/src/compiler/flow_generator.h b/core/story-manager/src/compiler/flow_generator.h index 2c6cfad..4615382 100644 --- a/core/story-manager/src/compiler/flow_generator.h +++ b/core/story-manager/src/compiler/flow_generator.h @@ -62,6 +62,10 @@ protected: } + virtual void Visit(const std::shared_ptr v) { + + } + virtual void GenerateExit() { @@ -84,7 +88,7 @@ protected: m_depth++; // Get condition value auto conditionNode = node->GetDataInput(0); - int conditionValue = EvaluateCondition(conditionNode); + int conditionValue = 0; FlowVisualizer::PrintBranchDecision(conditionValue > 7, std::to_string(conditionValue), m_depth); @@ -105,18 +109,16 @@ protected: m_depth++; auto* opNode = node->GetAs(); - // Evaluate operands - int value1 = EvaluateOperand(node->GetDataInput(0)); - int value2 = EvaluateOperand(node->GetDataInput(1)); + - FlowVisualizer::PrintDataFlow("Operand 1", "ADD", - std::to_string(value1), m_depth); - FlowVisualizer::PrintDataFlow("Operand 2", "ADD", - std::to_string(value2), m_depth); + FlowVisualizer::PrintDataFlow("Operand 1", opNode->GetOperatorSymbol(), + std::to_string(0), m_depth); + FlowVisualizer::PrintDataFlow("Operand 2", opNode->GetOperatorSymbol(), + std::to_string(0), m_depth); - int result = value1 + value2; - FlowVisualizer::PrintDataFlow("ADD", "Result", - std::to_string(result), m_depth); + + FlowVisualizer::PrintDataFlow(opNode->GetOperatorSymbol(), "Result", + std::to_string(0), m_depth); for (const auto& [port, outputs] : node->dataOutputs) { for (const auto& target : outputs) { @@ -148,24 +150,4 @@ protected: private: int m_depth = 0; - int EvaluateOperand(std::shared_ptr node) { - if (!node) return 0; - - if (node->IsType()) { - auto* varNode = node->GetAs(); - return varNode->GetValue(); - } - return 0; - } - - int EvaluateCondition(std::shared_ptr node) { - if (!node) return 0; - - if (node->IsType()) { - auto input0 = node->GetDataInput(0); - auto input1 = node->GetDataInput(1); - return EvaluateOperand(input0) + EvaluateOperand(input1); - } - return 0; - } }; diff --git a/core/story-manager/src/media_node.cpp b/core/story-manager/src/media_node.cpp index 7691cde..e139b39 100644 --- a/core/story-manager/src/media_node.cpp +++ b/core/story-manager/src/media_node.cpp @@ -2,7 +2,6 @@ #include "story_project.h" #include "connection.h" #include "sys_lib.h" -#include "compiler.h" static std::string ChoiceLabel(const std::string &id) { diff --git a/core/story-manager/src/nodes/base_node.cpp b/core/story-manager/src/nodes/base_node.cpp index a8bcc1e..56c6d63 100644 --- a/core/story-manager/src/nodes/base_node.cpp +++ b/core/story-manager/src/nodes/base_node.cpp @@ -128,3 +128,13 @@ float BaseNode::GetY() const { return m_pos.y; } + +void BaseNode::Accept(IVariableVisitor &visitor) +{ + + for (auto &v : m_variables) + { + visitor.Visit(v.second); + } + +} diff --git a/core/story-manager/src/nodes/base_node.h b/core/story-manager/src/nodes/base_node.h index df202cf..5964a69 100644 --- a/core/story-manager/src/nodes/base_node.h +++ b/core/story-manager/src/nodes/base_node.h @@ -9,6 +9,14 @@ #include "i_story_page.h" #include "i_story_project.h" #include "story_options.h" +#include "variable.h" + +class IVariableVisitor { + +public: + virtual void Visit(const std::shared_ptr v) = 0; + +}; class BaseNode { @@ -70,10 +78,6 @@ public: virtual void Initialize() = 0; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) = 0; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) = 0; - - virtual std::string GenerateConstants() const { return ""; } - virtual std::string GenerateAssembly() const = 0; void SetPosition(float x, float y); @@ -97,6 +101,15 @@ public: return m_typeName; } + + void SetWeight(int w) { + m_weight = w; + } + + int GetWeight() const { + return m_weight; + } + void SetId(const std::string &id) { m_uuid = id; } std::string GetId() const { return m_uuid; } @@ -134,12 +147,21 @@ public: return m_behavior; } + void Accept(IVariableVisitor &visitor); + + +protected: + // Easy access the variables for children nodes + // Key is the variable name, or whatever the node use to identify the variable + std::map> m_variables; + private: std::string m_title{"Default title"}; std::string m_type; std::string m_typeName; std::string m_uuid; NodePosition m_pos; + int m_weight{0}; Behavior m_behavior{BEHAVIOR_EXECUTION}; std::vector m_inputPorts; diff --git a/core/story-manager/src/nodes/branch_node.cpp b/core/story-manager/src/nodes/branch_node.cpp index 53092d0..c2c84a5 100644 --- a/core/story-manager/src/nodes/branch_node.cpp +++ b/core/story-manager/src/nodes/branch_node.cpp @@ -2,7 +2,6 @@ #include "story_project.h" #include "connection.h" #include "sys_lib.h" -#include "compiler.h" BranchNode::BranchNode(const std::string &type) @@ -17,14 +16,7 @@ void BranchNode::Initialize() } -std::string BranchNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) -{ - std::string s; - - - return s; -} std::string BranchNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) { diff --git a/core/story-manager/src/nodes/branch_node.h b/core/story-manager/src/nodes/branch_node.h index d153d08..4ea1050 100644 --- a/core/story-manager/src/nodes/branch_node.h +++ b/core/story-manager/src/nodes/branch_node.h @@ -13,7 +13,6 @@ public: virtual void Initialize() override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override; virtual std::string GenerateAssembly() const { return ""; } diff --git a/core/story-manager/src/nodes/compare_node.cpp b/core/story-manager/src/nodes/compare_node.cpp index f539181..edf0cc8 100644 --- a/core/story-manager/src/nodes/compare_node.cpp +++ b/core/story-manager/src/nodes/compare_node.cpp @@ -2,7 +2,6 @@ #include "story_project.h" #include "connection.h" #include "sys_lib.h" -#include "compiler.h" CompareNode::CompareNode(const std::string &type) @@ -17,14 +16,7 @@ void CompareNode::Initialize() } -std::string CompareNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) -{ - std::string s; - - - return s; -} std::string CompareNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) { diff --git a/core/story-manager/src/nodes/compare_node.h b/core/story-manager/src/nodes/compare_node.h index 8704ed3..0fcee4b 100644 --- a/core/story-manager/src/nodes/compare_node.h +++ b/core/story-manager/src/nodes/compare_node.h @@ -13,7 +13,6 @@ public: virtual void Initialize() override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override; private: diff --git a/core/story-manager/src/nodes/execution_node.h b/core/story-manager/src/nodes/execution_node.h deleted file mode 100644 index 4d712a0..0000000 --- a/core/story-manager/src/nodes/execution_node.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "base_node.h" - -class ExecutionNode : public BaseNode -{ -public: - ExecutionNode(const std::string &type, const std::string &typeName) - : BaseNode(type, typeName) {} - - void Initialize() override { - // Initialisation spécifique pour ExecutionNode - } - - std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override { - return GetMyEntryLabel() + ":\n"; - } - - std::string GenerateAssembly() const override { - return GetMyEntryLabel() + ":\n"; - } - - std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override { - // Génération des constantes pour ExecutionNode - return "ExecutionNode Constants"; - } - - // Ajoutez des méthodes spécifiques pour gérer les entrées et sorties d'exécution - void AddExecutionInput() { - // Logique pour ajouter une entrée d'exécution - } - - void AddExecutionOutput() { - // Logique pour ajouter une sortie d'exécution - } -}; diff --git a/core/story-manager/src/nodes/function_entry_node.h b/core/story-manager/src/nodes/function_entry_node.h index 1ead68f..faf8e8e 100644 --- a/core/story-manager/src/nodes/function_entry_node.h +++ b/core/story-manager/src/nodes/function_entry_node.h @@ -1,13 +1,16 @@ #pragma once -#include "execution_node.h" +#include "base_node.h" -class FunctionEntryNode : public ExecutionNode +class FunctionEntryNode : public BaseNode { public: FunctionEntryNode(const std::string &type) - : ExecutionNode(type, "Function Entry Node") {} + : BaseNode(type, "Function Entry Node") + { + SetWeight(100); + } void Initialize() override { // Initialisation spécifique pour FunctionEntryNode @@ -19,11 +22,6 @@ public: return GetMyEntryLabel() + ":\n"; } - std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override { - // Génération des constantes pour FunctionEntryNode - return "FunctionEntryNode Constants"; - } - // Ajoutez des méthodes spécifiques pour gérer l'entrée de la fonction void PrepareFunctionEntry() { // Logique pour préparer l'entrée de la fonction diff --git a/core/story-manager/src/nodes/function_exit_node.h b/core/story-manager/src/nodes/function_exit_node.h index c18f9c1..4d50831 100644 --- a/core/story-manager/src/nodes/function_exit_node.h +++ b/core/story-manager/src/nodes/function_exit_node.h @@ -18,11 +18,6 @@ public: return "FunctionExitNode Build"; } - std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override { - // Génération des constantes pour FunctionExitNode - return "FunctionExitNode Constants"; - } - // Ajoutez des méthodes spécifiques pour gérer la sortie de la fonction void FinalizeFunctionExit() { // Logique pour finaliser la sortie de la fonction diff --git a/core/story-manager/src/nodes/function_node.cpp b/core/story-manager/src/nodes/function_node.cpp index 45a62c2..a3b0d78 100644 --- a/core/story-manager/src/nodes/function_node.cpp +++ b/core/story-manager/src/nodes/function_node.cpp @@ -32,12 +32,3 @@ std::string FunctionNode::Build(IStoryPage &page, const StoryOptions &options, i return std::string(); } -std::string FunctionNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) -{ - std::string s; - - - - return s; -} - diff --git a/core/story-manager/src/nodes/function_node.h b/core/story-manager/src/nodes/function_node.h index d8cb6b1..25991d6 100644 --- a/core/story-manager/src/nodes/function_node.h +++ b/core/story-manager/src/nodes/function_node.h @@ -13,7 +13,6 @@ public: virtual void Initialize() override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override; void StoreInternalData(); diff --git a/core/story-manager/src/nodes/operator_node.h b/core/story-manager/src/nodes/operator_node.h index 965523f..026f040 100644 --- a/core/story-manager/src/nodes/operator_node.h +++ b/core/story-manager/src/nodes/operator_node.h @@ -105,56 +105,6 @@ public: return ss.str(); } - std::string GenerateConstants(IStoryPage& page, IStoryProject& project, int nb_out_conns) override { - return ""; // Operators don't generate constants - } - - std::string GenerateAssembly() const override { - std::stringstream ss; - - switch (m_operationType) { - case OperationType::ADD: - ss << " pop ebx\n" - << " pop eax\n" - << " add eax, ebx\n" - << " push eax\n"; - break; - case OperationType::SUBTRACT: - ss << " pop ebx\n" - << " pop eax\n" - << " sub eax, ebx\n" - << " push eax\n"; - break; - case OperationType::MULTIPLY: - ss << " pop ebx\n" - << " pop eax\n" - << " imul eax, ebx\n" - << " push eax\n"; - break; - case OperationType::DIVIDE: - ss << " pop ebx\n" - << " pop eax\n" - << " cdq\n" // Sign extend eax into edx - << " idiv ebx\n" - << " push eax\n"; // Push quotient - break; - case OperationType::AND: - ss << " pop ebx\n" - << " pop eax\n" - << " and eax, ebx\n" - << " push eax\n"; - break; - case OperationType::OR: - ss << " pop ebx\n" - << " pop eax\n" - << " or eax, ebx\n" - << " push eax\n"; - break; - // Add other operators... - } - - return ss.str(); - } private: OperationType m_operationType; diff --git a/core/story-manager/src/nodes/print_node.cpp b/core/story-manager/src/nodes/print_node.cpp index 8c1ce21..2db8250 100644 --- a/core/story-manager/src/nodes/print_node.cpp +++ b/core/story-manager/src/nodes/print_node.cpp @@ -2,13 +2,17 @@ #include "story_project.h" #include "connection.h" #include "sys_lib.h" -#include "compiler.h" PrintNode::PrintNode(const std::string &type) - : ExecutionNode(type, "Print Node") + : BaseNode(type, "Print Node") { m_label = GenerateRandomString(10, BaseNode::CHARSET_ALPHABET_LOWER | BaseNode::CHARSET_ALPHABET_UPPER );// Should be enough to avoid collision? + + // Create empty variable in memory + auto v = std::make_shared(m_label); + v->SetTextValue(""); + m_variables[m_label] = v; } @@ -17,41 +21,9 @@ void PrintNode::Initialize() } -std::string PrintNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) -{ - std::stringstream ss; - ss << "$" << m_label << " DC8, " << m_text << "\n"; - return ss.str(); -} - std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) { return ""; } -std::string PrintNode::GenerateConstants() const -{ - std::stringstream ss; - ss << "$" << m_label << " DC8, \"" << m_text << "\"\n"; - return ss.str(); -} - -std::string PrintNode::GenerateAssembly() const -{ - - std::stringstream ss; - - ss << ExecutionNode::GenerateAssembly() - << " push r0\n" - << " push r1\n" - << " lcons r0, $" << m_label << "\n" - << " lcons r1, 0 ; number of arguments\n" // FIXME: handle arguments - << " syscall 4\n" - << " pop r1\n" - << " pop r0\n"; - -// << ""mov r2, %2 // arguments are in r2, r3, r4 etc. - - return ss.str(); -} diff --git a/core/story-manager/src/nodes/print_node.h b/core/story-manager/src/nodes/print_node.h index 4707eb5..ab486d5 100644 --- a/core/story-manager/src/nodes/print_node.h +++ b/core/story-manager/src/nodes/print_node.h @@ -2,34 +2,33 @@ #include #include "i_story_manager.h" -#include "execution_node.h" +#include "base_node.h" #include "i_script_node.h" #include "i_story_project.h" -class PrintNode : public ExecutionNode +class PrintNode : public BaseNode { public: PrintNode(const std::string &type); virtual void Initialize() override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override; - - virtual std::string GenerateConstants() const override; - - std::string GenerateAssembly() const override; void SetText(const std::string &text) { - m_text = text; + + m_variables.at(m_label)->SetValue(text); + } + + std::string GetLabel() const { + return m_label; } std::string GetText() const { - return m_text; + return m_variables.at(m_label)->GetValue(); } private: - std::string m_label; - std::string m_text; // Text to print + std::string m_label; // Label for the string literal uint32_t m_arguments{0}; // number of arguments }; diff --git a/core/story-manager/src/nodes/variable_node.cpp b/core/story-manager/src/nodes/variable_node.cpp index 05e5ecb..9e5dd5e 100644 --- a/core/story-manager/src/nodes/variable_node.cpp +++ b/core/story-manager/src/nodes/variable_node.cpp @@ -32,12 +32,3 @@ std::string VariableNode::Build(IStoryPage &page, const StoryOptions &options, i return std::string(); } -std::string VariableNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) -{ - std::string s; - - - - return s; -} - diff --git a/core/story-manager/src/nodes/variable_node.h b/core/story-manager/src/nodes/variable_node.h index 62f2f96..0b5b16f 100644 --- a/core/story-manager/src/nodes/variable_node.h +++ b/core/story-manager/src/nodes/variable_node.h @@ -1,8 +1,8 @@ #pragma once #include -#include +#include "variable.h" #include "i_story_manager.h" #include "base_node.h" #include "i_script_node.h" @@ -12,92 +12,25 @@ class VariableNode : public BaseNode { public: - enum class ValueType { - INTEGER, - FLOAT, - BOOL, - STRING - }; - - using VariableValue = std::variant; - VariableNode(const std::string &type = "variable-node"); virtual void Initialize() override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; - virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override; virtual std::string GenerateAssembly() const { return ""; } void StoreInternalData(); - - // Setters - void SetVariableName(const std::string& name) { - m_variableName = name; + void SetVariableUuid(const std::string &uuid) { + m_variableUuid = uuid; } - void SetConstant(bool isConstant) { - m_isConstant = isConstant; + std::string GetVariableUuid() const { + return m_variableUuid; } - void SetValueType(ValueType type) { - m_valueType = type; - // Reset value to default for new type - switch (type) { - case ValueType::INTEGER: - m_value = 0; - break; - case ValueType::FLOAT: - m_value = 0.0f; - break; - case ValueType::BOOL: - m_value = false; - break; - case ValueType::STRING: - m_value = ""; - break; - } - } - - template - void SetValue(const T& value) { - try { - m_value = value; - } catch (const std::bad_variant_access&) { - throw std::runtime_error("Invalid value type for variable"); - } - } - - // Getters - std::string GetVariableName() const { - return m_variableName; - } - - bool IsConstant() const { - return m_isConstant; - } - - ValueType GetValueType() const { - return m_valueType; - } - - template - T GetValue() const { - try { - return std::get(m_value); - } catch (const std::bad_variant_access&) { - throw std::runtime_error("Invalid value type requested"); - } - } - - - private: - std::string m_variableName; - ValueType m_valueType; - VariableValue m_value; - bool m_isConstant; + std::string m_variableUuid; }; diff --git a/core/story-manager/src/story_page.h b/core/story-manager/src/story_page.h index ab15c44..9307d43 100644 --- a/core/story-manager/src/story_page.h +++ b/core/story-manager/src/story_page.h @@ -52,11 +52,11 @@ public: void Build(std::stringstream &code, IStoryProject &project) { - // First generate all constants - for (const auto & n : m_nodes) - { - code << n->GenerateConstants(*this, project, OutputsCount(n->GetId())) << "\n"; - } + // // First generate all constants + // for (const auto & n : m_nodes) + // { + // code << n->GenerateConstants(*this, project, OutputsCount(n->GetId())) << "\n"; + // } for (const auto & n : m_nodes) { diff --git a/core/story-manager/tests/test_ast.cpp b/core/story-manager/tests/test_ast.cpp index a9703aa..490c6ae 100644 --- a/core/story-manager/tests/test_ast.cpp +++ b/core/story-manager/tests/test_ast.cpp @@ -35,6 +35,7 @@ THE SOFTWARE. #include "function_entry_node.h" #include "operator_node.h" #include "chip32_machine.h" +#include "variable.h" #include #include @@ -43,47 +44,7 @@ THE SOFTWARE. #include "assembly_generator.h" #include "flow_generator.h" #include "assembly_generator_chip32.h" -/* -void ProcessASTTree(const ASTBuilder::PathTree& tree, int depth = 0) { - std::queue, int>> queue; - queue.push({tree.root, depth}); - std::unordered_set visited; - while (!queue.empty()) { - auto [node, currentDepth] = queue.front(); - queue.pop(); - - if (visited.find(node->node->GetId()) != visited.end()) { - continue; - } - visited.insert(node->node->GetId()); - - std::string indent(currentDepth * 2, ' '); - std::cout << indent << "Node: " << node->node->GetTypeName() - << " (ID: " << node->node->GetId() << ")" << std::endl; - - // Print data inputs - for (const auto& [portIndex, inputNode] : node->dataInputs) { - std::cout << indent << " Input at port " << portIndex - << " from: " << inputNode->node->GetTypeName() << std::endl; - } - - // Print data outputs - for (const auto& [portIndex, outputs] : node->dataOutputs) { - for (const auto& [targetNode, targetPort] : outputs) { - std::cout << indent << " Output from port " << portIndex - << " to: " << targetNode->node->GetTypeName() - << " port " << targetPort << std::endl; - } - } - - // Add children to queue - for (const auto& child : node->children) { - queue.push({child, currentDepth + 1}); - } - } -} -*/ TEST_CASE( "Check various indentations and typos" ) { Compiler compiler; @@ -98,20 +59,50 @@ TEST_CASE( "Check various indentations and typos" ) { auto functionEntryNode = std::make_shared("function-entry-node"); - auto variableNode1 = std::make_shared("variable-node"); - variableNode1->SetValue(5); - variableNode1->SetValueType(VariableNode::ValueType::INTEGER); - variableNode1->SetVariableName("X"); - auto variableNode2 = std::make_shared("variable-node"); - variableNode2->SetValue(10); - variableNode2->SetValueType(VariableNode::ValueType::INTEGER); - variableNode2->SetVariableName("Y"); + std::vector> variables; + auto var1 = std::make_shared("X"); + var1->SetValue(5); + var1->SetValueType(Variable::ValueType::INTEGER); + auto var2 = std::make_shared("Y"); + var2->SetValue(10); + var2->SetValueType(Variable::ValueType::INTEGER); + + auto var3 = std::make_shared("A"); + var3->SetValue(7); + var3->SetValueType(Variable::ValueType::INTEGER); + + auto var4 = std::make_shared("B"); + var4->SetValue(2); + var4->SetValueType(Variable::ValueType::INTEGER); + + + variables.push_back(var1); + variables.push_back(var2); + variables.push_back(var3); + variables.push_back(var4); + + auto variableNodeX = std::make_shared("variable-node"); + variableNodeX->SetVariableUuid(var1->GetUuid()); + + auto variableNodeY = std::make_shared("variable-node"); + variableNodeY->SetVariableUuid(var2->GetUuid()); + + auto variableNodeA = std::make_shared("variable-node"); + variableNodeA->SetVariableUuid(var3->GetUuid()); + + auto variableNodeB = std::make_shared("variable-node"); + variableNodeB->SetVariableUuid(var4->GetUuid()); auto testNode = std::make_shared(); testNode->SetOperationType(OperatorNode::OperationType::GREATER_THAN); + auto addNode = std::make_shared(); + addNode->SetOperationType(OperatorNode::OperationType::ADD); + + auto subNode = std::make_shared(); + subNode->SetOperationType(OperatorNode::OperationType::SUBTRACT); std::vector> nodes; @@ -119,9 +110,13 @@ TEST_CASE( "Check various indentations and typos" ) { nodes.push_back(printNodeTrue); nodes.push_back(printNodeFalse); nodes.push_back(branchNode); - nodes.push_back(variableNode1); - nodes.push_back(variableNode2); + nodes.push_back(variableNodeX); + nodes.push_back(variableNodeY); + nodes.push_back(variableNodeA); + nodes.push_back(variableNodeB); nodes.push_back(testNode); + nodes.push_back(addNode); + nodes.push_back(subNode); auto cn1 = std::make_shared(); auto cn2 = std::make_shared(); @@ -129,6 +124,10 @@ TEST_CASE( "Check various indentations and typos" ) { auto cn4 = std::make_shared(); auto cn5 = std::make_shared(); auto cn6 = std::make_shared(); + auto cn7 = std::make_shared(); + auto cn8 = std::make_shared(); + auto cn9 = std::make_shared(); + auto cn10 = std::make_shared(); std::vector> connections; @@ -138,7 +137,10 @@ TEST_CASE( "Check various indentations and typos" ) { connections.push_back(cn4); connections.push_back(cn5); connections.push_back(cn6); - + connections.push_back(cn7); + connections.push_back(cn8); + connections.push_back(cn9); + connections.push_back(cn10); // Branch True -> print Ok // False -> print Ko @@ -168,47 +170,47 @@ TEST_CASE( "Check various indentations and typos" ) { cn4->outPortIndex = 0; cn4->type = Connection::DATA_LINK; - // Variable 1 -> Compare test node input 1 + // + output 1 -> Compare test node input 1 cn5->inNodeId = testNode->GetId(); cn5->inPortIndex = 0; - cn5->outNodeId = variableNode1->GetId(); + cn5->outNodeId = addNode->GetId(); cn5->outPortIndex = 0; cn5->type = Connection::DATA_LINK; - // Variable 1 -> Compare test node input 1 + // - output -> Compare test node input 1 cn6->inNodeId = testNode->GetId(); cn6->inPortIndex = 1; - cn6->outNodeId = variableNode2->GetId(); + cn6->outNodeId = subNode->GetId(); cn6->outPortIndex = 0; cn6->type = Connection::DATA_LINK; + // ADD NODE INPUTS - // // Création des nœuds - // std::vector nodes = { - // Node(Node::Type::VARIABLE, "i", "node_i"), - // Node(Node::Type::CONSTANT, 10, "node_10"), - // Node(Node::Type::SUBTRACT, "node_subtract"), - // Node(Node::Type::CONSTANT, 1, "node_1"), - // Node(Node::Type::ADD, "node_add"), - // Node(Node::Type::ASSIGN, "i", "node_assign"), - // Node(Node::Type::VARIABLE, "conditionVar", "node_condVar"), - // Node(Node::Type::CONSTANT, 2, "node_2"), - // Node(Node::Type::MULTIPLY, "node_multiply"), - // Node(Node::Type::ASSIGN, "i", "node_assign_multiply"), - // Node(Node::Type::BRANCH, "node_branch"), - // Node(Node::Type::LOOP, "node_loop") - // }; + cn7->inNodeId = addNode->GetId(); + cn7->inPortIndex = 0; + cn7->outNodeId = variableNodeX->GetId(); + cn7->outPortIndex = 0; + cn7->type = Connection::DATA_LINK; - // try - // { - // // Construction de l'AST - // compiler.buildAST(nodes, connections); - // compiler.printAST(); + cn8->inNodeId = addNode->GetId(); + cn8->inPortIndex = 1; + cn8->outNodeId = variableNodeY->GetId(); + cn8->outPortIndex = 0; + cn8->type = Connection::DATA_LINK; - // } catch(const std::exception &e) - // { - // std::cout << e.what() << std::endl; - // } + // SUBTRACT NODE INPUTS + + cn9->inNodeId = subNode->GetId(); + cn9->inPortIndex = 0; + cn9->outNodeId = variableNodeA->GetId(); + cn9->outPortIndex = 0; + cn9->type = Connection::DATA_LINK; + + cn10->inNodeId = subNode->GetId(); + cn10->inPortIndex = 1; + cn10->outNodeId = variableNodeB->GetId(); + cn10->outPortIndex = 0; + cn10->type = Connection::DATA_LINK; // Create generator context with current time and user @@ -227,34 +229,19 @@ TEST_CASE( "Check various indentations and typos" ) { ASTBuilder builder(nodes, connections); auto pathTrees = builder.BuildAST(); - /* - // Process each path tree - for (const auto& tree : pathTrees) { - std::cout << (tree.isExecutionPath ? "Execution" : "Data") - << " Path Tree:" << std::endl; - ProcessASTTree(tree); - std::cout << std::endl; - } - */ - // Generate flow in the console VisualFlowGenerator flowGenerator(context); FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01"); - std::string flow = flowGenerator.GenerateAssembly(nodes, pathTrees); + std::string flow = flowGenerator.GenerateAssembly(nodes, pathTrees, variables); std::cout << "\nGenerated flow:\n" << flow << std::endl; // Generate assembly - std::string assembly = generator.GenerateAssembly(nodes, pathTrees); + std::string assembly = generator.GenerateAssembly(nodes, pathTrees, variables); std::cout << "\nGenerated assembly:\n" << assembly << std::endl; - // compiler.generateAssembly(); - - // std::cout << compiler.GetCode() << std::endl; - - // Chip32::Machine machine; // machine.QuickExecute(compiler.GetCode());