diff --git a/core/story-manager/src/compiler/assembly_generator.h b/core/story-manager/src/compiler/assembly_generator.h index 9d89425..d50437f 100644 --- a/core/story-manager/src/compiler/assembly_generator.h +++ b/core/story-manager/src/compiler/assembly_generator.h @@ -16,6 +16,10 @@ #include "branch_node.h" #include "operator_node.h" + + + + class AssemblyGenerator { public: struct GeneratorContext { @@ -26,7 +30,7 @@ public: int stackSize; GeneratorContext(const std::string& ts = "2025-04-08 12:09:01", - const std::string& user = "arabine", + const std::string& user = "anonymous", bool debug = true, bool optimize = true, int stack = 1024) @@ -54,7 +58,9 @@ public: m_currentSection = Section::NONE; } - std::string GenerateAssembly(const std::vector& roots) { + std::string GenerateAssembly(std::vector> &nodes, const std::vector& roots) + { + m_roots = roots; Reset(); // Generate header comments @@ -62,11 +68,7 @@ public: // Generate data section StartSection(Section::DATA); - GenerateDataSection(roots); - - // Generate bss section for uninitialized data - StartSection(Section::BSS); - GenerateBssSection(); + GenerateDataSection(nodes, roots); // Generate text section StartSection(Section::TEXT); @@ -79,59 +81,46 @@ protected: enum class Section { NONE, DATA, - BSS, TEXT }; - virtual void GenerateNodeCode(std::shared_ptr node, bool isDataPath = false) { - if (!node) return; + virtual void GenerateNodeCode(std::shared_ptr node, bool isDataPath = false) = 0; - if (m_context.debugOutput) { - AddComment("Node: " + node->node->GetTypeName() + " (ID: " + node->node->GetId() + ")"); - } + virtual void AddComment(const std::string& comment) = 0; - if (node->IsType()) { - GenerateFunctionEntry(node); - } - else if (node->IsType()) { - GenerateBranchNode(node); - } - else if (node->IsType()) { - GeneratePrintNode(node); - } - else if (node->IsType()) { - GenerateOperatorNode(node); - } - else if (node->IsType()) { - GenerateVariableNode(node); - } + virtual void GenerateExit() = 0; - // If we're processing a data path, traverse data outputs - if (isDataPath) { - for (const auto& [port, outputs] : node->dataOutputs) { - for (const auto& target : outputs) { - GenerateNodeCode(target.node, true); - } - } - } + + std::string AddStringLiteral(const std::string& text) + { + std::string label = "str_" + std::to_string(m_stringLiterals.size()); + m_stringLiterals.push_back(text); + return label; } -private: + std::string GenerateUniqueLabel(const std::string& prefix) + { + return prefix + "_" + std::to_string(m_labelCounter++); + } + +protected: GeneratorContext m_context; std::stringstream m_assembly; int m_labelCounter; std::unordered_map m_variableAddresses; int m_currentStackOffset; std::vector m_stringLiterals; - int m_depth; + int m_depth{0}; Section m_currentSection; + std::vector m_roots; + +private: void GenerateHeader() { - m_assembly << "; Assembly generated by Visual Node Editor\n" - << "; Generation time: " << m_context.timestamp << "\n" - << "; Generated by: " << m_context.username << "\n" - << "; Optimization: " << (m_context.optimizeCode ? "enabled" : "disabled") << "\n" - << "\n"; + AddComment("Assembly generated by Visual Node Editor"); + AddComment("Generation time: " + m_context.timestamp); + AddComment("Generated by: " + m_context.username); + AddComment("Optimization: " + m_context.optimizeCode ? "enabled" : "disabled"); } void StartSection(Section section) { @@ -140,21 +129,24 @@ private: m_currentSection = section; switch (section) { case Section::DATA: - m_assembly << "section .data\n"; - break; - case Section::BSS: - m_assembly << "section .bss\n"; + AddComment("======================= DATA ======================="); break; case Section::TEXT: - m_assembly << "section .text\n" - << "global _start\n\n"; + AddComment("======================= CODE ======================="); break; default: break; } } - void GenerateDataSection(const std::vector& trees) { + void GenerateDataSection(const std::vector> &nodes, const std::vector& trees) { + + + // Generate all constants + for (const auto& n : nodes) { + m_assembly << n->GenerateConstants(); + } + // Generate string literals for (const auto& literal : m_stringLiterals) { std::string label = "str_" + std::to_string(m_labelCounter++); @@ -168,18 +160,10 @@ private: } } - void GenerateBssSection() { - m_assembly << " stack_space resb " << m_context.stackSize << "\n"; - } - void GenerateTextSection(const std::vector& trees) { // Program entry point - m_assembly << "_start:\n"; + m_assembly << ".main:\n"; - // Setup stack frame - m_assembly << " mov ebp, esp\n" - << " sub esp, " << m_context.stackSize << "\n\n"; - // Process execution paths first for (const auto& tree : trees) { if (tree.isExecutionPath) { @@ -198,130 +182,6 @@ private: GenerateExit(); } - void GenerateFunctionEntry(std::shared_ptr node) { - AddComment("Function Entry"); - m_depth++; - - for (auto& child : node->children) { - GenerateNodeCode(child); - } - - m_depth--; - } - - void GenerateBranchNode(std::shared_ptr node) { - std::string labelTrue = GenerateUniqueLabel("true"); - std::string labelFalse = GenerateUniqueLabel("false"); - std::string labelEnd = GenerateUniqueLabel("end"); - - AddComment("Branch condition evaluation"); - m_depth++; - - // Generate condition code - if (auto conditionNode = node->GetDataInput(0)) { - GenerateNodeCode(conditionNode); - } - - // Compare result and jump - m_assembly << " pop eax\n" - << " cmp eax, 0\n" - << " je " << labelFalse << "\n"; - - // True branch - m_assembly << labelTrue << ":\n"; - if (node->GetChildCount() > 0) { - GenerateNodeCode(node->GetChild(0)); - } - m_assembly << " jmp " << labelEnd << "\n"; - - // False branch - m_assembly << labelFalse << ":\n"; - if (node->GetChildCount() > 1) { - GenerateNodeCode(node->GetChild(1)); - } - - m_assembly << labelEnd << ":\n"; - m_depth--; - } - - void GeneratePrintNode(std::shared_ptr node) { - auto* printNode = node->GetAs(); - if (!printNode) return; - - std::string text = printNode->GetText(); - std::string label = AddStringLiteral(text); - - // 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) { - auto* opNode = node->GetAs(); - if (!opNode) return; - - AddComment("Operator: " + std::to_string(static_cast(opNode->GetOperationType()))); - m_depth++; - - // Generate code for operands - for (const auto& [port, inputNode] : node->dataInputs) { - GenerateNodeCode(inputNode); - } - - // Generate operator code - switch (opNode->GetOperationType()) { - case OperatorNode::OperationType::ADD: - m_assembly << " pop ebx\n" - << " pop eax\n" - << " add eax, ebx\n" - << " push eax\n"; - break; - case OperatorNode::OperationType::SUBTRACT: - m_assembly << " pop ebx\n" - << " pop eax\n" - << " sub eax, ebx\n" - << " push eax\n"; - break; - case OperatorNode::OperationType::MULTIPLY: - m_assembly << " pop ebx\n" - << " pop eax\n" - << " imul eax, ebx\n" - << " push eax\n"; - break; - case OperatorNode::OperationType::DIVIDE: - m_assembly << " pop ebx\n" - << " pop eax\n" - << " cdq\n" - << " idiv ebx\n" - << " push eax\n"; - break; - // Add other operators... - } - - m_depth--; - } - - void GenerateVariableNode(std::shared_ptr node) { - auto* varNode = node->GetAs(); - if (!varNode) return; - - std::string varName = varNode->GetVariableName(); - - AddComment("Load variable: " + varName); - m_assembly << " mov eax, [" << m_variableAddresses[varName] << "]\n" - << " push eax\n"; - } - - void GenerateExit() { - AddComment("Program exit"); - m_assembly << " mov eax, 1\n" // sys_exit - << " mov ebx, 0\n" // return 0 - << " int 0x80\n"; - } - void CollectVariables(std::shared_ptr node) { if (!node) return; @@ -345,19 +205,6 @@ private: } } - std::string AddStringLiteral(const std::string& text) { - std::string label = "str_" + std::to_string(m_stringLiterals.size()); - m_stringLiterals.push_back(text); - return label; - } - std::string GenerateUniqueLabel(const std::string& prefix) { - return prefix + "_" + std::to_string(m_labelCounter++); - } - void AddComment(const std::string& comment) { - if (m_context.debugOutput) { - m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n"; - } - } }; \ No newline at end of file diff --git a/core/story-manager/src/compiler/assembly_generator_chip32.h b/core/story-manager/src/compiler/assembly_generator_chip32.h new file mode 100644 index 0000000..fc0b003 --- /dev/null +++ b/core/story-manager/src/compiler/assembly_generator_chip32.h @@ -0,0 +1,199 @@ +#pragma once + +#include "ast_builder.h" +#include "assembly_generator.h" + +class AssemblyGeneratorChip32 : public AssemblyGenerator +{ +public: + AssemblyGeneratorChip32(const GeneratorContext& context = GeneratorContext()) + : AssemblyGenerator(context) + { + + } + virtual ~AssemblyGeneratorChip32() = default; + + + void GenerateNodeCode(std::shared_ptr node, bool isDataPath = false) override + { + if (!node) return; + + 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()) { + GenerateFunctionEntry(node); + } + else if (node->IsType()) { + GenerateBranchNode(node); + } + else if (node->IsType()) { + GeneratePrintNode(node); + } + } + + // If we're processing a data path, traverse data outputs + if (isDataPath) { + for (const auto& [port, outputs] : node->dataOutputs) { + for (const auto& target : outputs) { + GenerateNodeCode(target.node, true); + } + } + } + + } + + virtual void AddComment(const std::string& comment) { + m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n"; + } + + + + virtual void GenerateExit() { + AddComment("Program exit"); + m_assembly << " halt\n"; + } + +private: + + void GenerateFunctionEntry(std::shared_ptr node) { + AddComment("Function Entry"); + m_depth++; + + for (auto& child : node->children) { + GenerateNodeCode(child); + } + + m_depth--; + } + + void GenerateBranchNode(std::shared_ptr node) + { + std::string labelTrue = GenerateUniqueLabel("true"); + std::string labelFalse = GenerateUniqueLabel("false"); + std::string labelEnd = GenerateUniqueLabel("end"); + + AddComment("Branch condition evaluation"); + m_depth++; + + // 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" + << " cmp eax, 0\n" + << " je " << labelFalse << "\n"; + + // True branch + m_assembly << labelTrue << ":\n"; + if (node->GetChildCount() > 0) { + GenerateNodeCode(node->GetChild(0)); + } + m_assembly << " jmp " << labelEnd << "\n"; + + // False branch + m_assembly << labelFalse << ":\n"; + if (node->GetChildCount() > 1) { + GenerateNodeCode(node->GetChild(1)); + } + + m_assembly << labelEnd << ":\n"; + m_depth--; + } + + void GeneratePrintNode(std::shared_ptr node) { + auto* printNode = node->GetAs(); + if (!printNode) return; + + std::string text = printNode->GetText(); + std::string label = AddStringLiteral(text); + + // 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) { + auto* opNode = node->GetAs(); + if (!opNode) return; + + AddComment("Operator: " + std::to_string(static_cast(opNode->GetOperationType()))); + m_depth++; + + // Generate code for operands + for (const auto& [port, inputNode] : node->dataInputs) { + GenerateNodeCode(inputNode); + } + + // Generate operator code + switch (opNode->GetOperationType()) { + case OperatorNode::OperationType::ADD: + m_assembly << " pop ebx\n" + << " pop eax\n" + << " add eax, ebx\n" + << " push eax\n"; + break; + case OperatorNode::OperationType::SUBTRACT: + m_assembly << " pop ebx\n" + << " pop eax\n" + << " sub eax, ebx\n" + << " push eax\n"; + break; + case OperatorNode::OperationType::MULTIPLY: + m_assembly << " pop ebx\n" + << " pop eax\n" + << " imul eax, ebx\n" + << " push eax\n"; + break; + case OperatorNode::OperationType::DIVIDE: + m_assembly << " pop ebx\n" + << " pop eax\n" + << " cdq\n" + << " idiv ebx\n" + << " push eax\n"; + break; + // Add other operators... + } + + m_depth--; + } + + void GenerateVariableNode(std::shared_ptr node) { + auto* varNode = node->GetAs(); + if (!varNode) return; + + std::string varName = varNode->GetVariableName(); + + AddComment("Load variable: " + varName); + 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 ad79c29..a9ffd54 100644 --- a/core/story-manager/src/compiler/ast_builder.h +++ b/core/story-manager/src/compiler/ast_builder.h @@ -32,6 +32,14 @@ public: // Data outputs: output_port_index -> vector of (target node, target port) std::unordered_map> dataOutputs; + bool IsExecutionNode() const { + return node->GetBehavior() == BaseNode::Behavior::BEHAVIOR_EXECUTION; + } + + bool IsDataNode() const { + return node->GetBehavior() == BaseNode::Behavior::BEHAVIOR_DATA; + } + // Helper methods bool HasDataInput(unsigned int portIndex) const { return dataInputs.find(portIndex) != dataInputs.end(); @@ -130,6 +138,7 @@ public: struct PathTree { std::shared_ptr root; + std::shared_ptr lastNode; // Dernier nœud du PathTree std::vector> connections; bool isExecutionPath; // true for main flow, false for input paths }; @@ -171,19 +180,28 @@ public: } } // Nodes that have data outputs but no data inputs are data path roots - if (hasIncomingData.find(node->GetId()) == hasIncomingData.end()) { + if ((hasIncomingData.find(node->GetId()) == hasIncomingData.end()) || + AreAllInputsVariables(node, nodeMap)) + { // Check if the node has any outgoing data connections bool hasDataOutput = false; - for (const auto& conn : m_connections) { + for (const auto& conn : m_connections) + { if (conn->type == Connection::DATA_LINK && conn->outNodeId == node->GetId()) { hasDataOutput = true; break; } } - if (hasDataOutput) { + + if (hasDataOutput && !(dynamic_cast(node.get()))) + { dataRoots.push_back(node); } + + // if (hasDataOutput) { + // dataRoots.push_back(node); + // } } } @@ -214,6 +232,23 @@ private: const std::vector>& m_nodes; const std::vector>& m_connections; + + bool AreAllInputsVariables(const std::shared_ptr& node, const std::unordered_map>& nodeMap) const + { + for (const auto& conn : m_connections) + { + if (conn->type == Connection::DATA_LINK && conn->inNodeId == node->GetId()) + { + auto sourceNode = nodeMap.find(conn->outNodeId); + if (sourceNode != nodeMap.end() && !dynamic_cast(sourceNode->second.get())) + { + return false; + } + } + } + return true; + } + void BuildExecutionPath(PathTree& tree, const std::unordered_map>& nodeMap) { @@ -250,6 +285,8 @@ private: queue.push(tree.root); std::unordered_set visited; + std::shared_ptr currentLastNode = nullptr; + while (!queue.empty()) { auto current = queue.front(); queue.pop(); @@ -257,6 +294,8 @@ private: 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 @@ -266,14 +305,24 @@ private: auto targetNode = nodeMap.find(conn->inNodeId); if (targetNode != nodeMap.end()) { auto childNode = std::make_shared(targetNode->second); - current->dataOutputs[conn->outPortIndex].push_back( - {childNode, conn->inPortIndex}); + + // 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, diff --git a/core/story-manager/src/compiler/flow_generator.h b/core/story-manager/src/compiler/flow_generator.h index 3313be7..2c6cfad 100644 --- a/core/story-manager/src/compiler/flow_generator.h +++ b/core/story-manager/src/compiler/flow_generator.h @@ -13,7 +13,7 @@ public: std::cout << "AST Flow Visualization\n"; std::cout << "User: " << user << "\n"; std::cout << "Time: " << timestamp << "\n"; - std::cout << "==========================================================\n\n"; + std::cout << "==========================================================\n\n" << std::endl; } static void PrintNodeExecution(const std::string& nodeName, int depth = 0) { @@ -55,81 +55,117 @@ public: } - protected: - void GenerateNodeCode(std::shared_ptr node, bool isDataPath = false) override { - if (!node) return; +protected: - FlowVisualizer::PrintNodeExecution(node->node->GetTypeName(), m_depth); + virtual void AddComment(const std::string& comment) { + + } - if (node->IsType()) { - m_depth++; - for (auto& child : node->children) { - GenerateNodeCode(child); - } - m_depth--; - } - else if (node->IsType()) { - m_depth++; - // Get condition value - auto conditionNode = node->GetDataInput(0); - int conditionValue = EvaluateCondition(conditionNode); - - FlowVisualizer::PrintBranchDecision(conditionValue > 7, - std::to_string(conditionValue), m_depth); - // Execute appropriate path - if (conditionValue > 7) { - GenerateNodeCode(node->GetChild(0)); // True path - } else { - GenerateNodeCode(node->GetChild(1)); // False path - } - m_depth--; - } - else if (node->IsType()) { - auto* printNode = node->GetAs(); - FlowVisualizer::PrintNodeExecution("Print: " + printNode->GetText(), m_depth); - } - else if (node->IsType()) { - 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); - - int result = value1 + value2; - FlowVisualizer::PrintDataFlow("ADD", "Result", - std::to_string(result), m_depth); - m_depth--; + + virtual void GenerateExit() { + + } + + void GenerateNodeCode(std::shared_ptr node, bool isDataPath = false) override + { + if (!node) return; + + FlowVisualizer::PrintNodeExecution(node->node->GetTypeName(), m_depth); + + if (node->IsType()) { + m_depth++; + for (auto& child : node->children) { + GenerateNodeCode(child); } + m_depth--; } - - private: - int m_depth = 0; - - int EvaluateOperand(std::shared_ptr node) { - if (!node) return 0; + else if (node->IsType()) { + m_depth++; + // Get condition value + auto conditionNode = node->GetDataInput(0); + int conditionValue = EvaluateCondition(conditionNode); - if (node->IsType()) { - auto* varNode = node->GetAs(); - return varNode->GetValue(); + FlowVisualizer::PrintBranchDecision(conditionValue > 7, + std::to_string(conditionValue), m_depth); + + // Execute appropriate path + if (conditionValue > 7) { + GenerateNodeCode(node->GetChild(0)); // True path + } else { + GenerateNodeCode(node->GetChild(1)); // False path } - return 0; + m_depth--; + } + else if (node->IsType()) { + auto* printNode = node->GetAs(); + FlowVisualizer::PrintNodeExecution("Print: " + printNode->GetText(), m_depth); + } + else if (node->IsType()) { + 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); + + int result = value1 + value2; + FlowVisualizer::PrintDataFlow("ADD", "Result", + std::to_string(result), m_depth); + + for (const auto& [port, outputs] : node->dataOutputs) { + for (const auto& target : outputs) { + GenerateNodeCode(target.node, true); + } + } + + m_depth--; + } + else if (node->IsType()) { + m_depth++; + auto* varNode = node->GetAs(); + // FlowVisualizer::PrintNodeExecution("Variable: " + varNode->GetVariableName(), m_depth); + + // If we're processing a data path, traverse data outputs + if (isDataPath) { + for (const auto& [port, outputs] : node->dataOutputs) { + for (const auto& target : outputs) { + GenerateNodeCode(target.node, true); + } + } + } + m_depth--; } - 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; + + } + +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/nodes/base_node.cpp b/core/story-manager/src/nodes/base_node.cpp index 5359978..a8bcc1e 100644 --- a/core/story-manager/src/nodes/base_node.cpp +++ b/core/story-manager/src/nodes/base_node.cpp @@ -2,16 +2,18 @@ #include "uuid.h" #include -BaseNode::BaseNode(const std::string &type, const std::string &typeName) +BaseNode::BaseNode(const std::string &type, const std::string &typeName, Behavior behavior) + : m_behavior(behavior) { m_type = type; - m_typeName = typeName; + m_typeName = typeName; m_uuid = Uuid().String(); nlohmann::json obj{}; m_internal_data = obj; } + BaseNode::~BaseNode() { std::cout << "Deleted base node" << std::endl; diff --git a/core/story-manager/src/nodes/base_node.h b/core/story-manager/src/nodes/base_node.h index d1b3970..df202cf 100644 --- a/core/story-manager/src/nodes/base_node.h +++ b/core/story-manager/src/nodes/base_node.h @@ -13,6 +13,12 @@ class BaseNode { public: + enum Behavior + { + BEHAVIOR_EXECUTION, + BEHAVIOR_DATA, + }; + struct Port { enum Type { @@ -57,7 +63,7 @@ public: std::vector values; }; - BaseNode(const std::string &type, const std::string &typeName); + BaseNode(const std::string &type, const std::string &typeName, Behavior behavior = BEHAVIOR_EXECUTION); virtual ~BaseNode(); static std::string GetEntryLabel(const std::string &id); @@ -121,12 +127,20 @@ public: } + void SetBehavior(Behavior behavior) { + m_behavior = behavior; + } + Behavior GetBehavior() const { + return m_behavior; + } + private: std::string m_title{"Default title"}; std::string m_type; std::string m_typeName; std::string m_uuid; NodePosition m_pos; + Behavior m_behavior{BEHAVIOR_EXECUTION}; std::vector m_inputPorts; std::vector m_outputPorts; diff --git a/core/story-manager/src/nodes/operator_node.h b/core/story-manager/src/nodes/operator_node.h index b1a7b80..965523f 100644 --- a/core/story-manager/src/nodes/operator_node.h +++ b/core/story-manager/src/nodes/operator_node.h @@ -38,7 +38,7 @@ public: OperatorNode(const std::string& type = "operator-node", const std::string& typeName = "Operator") - : BaseNode(type, typeName) + : BaseNode(type, typeName, BaseNode::Behavior::BEHAVIOR_DATA) , m_operationType(OperationType::ADD) { Initialize(); diff --git a/core/story-manager/tests/test_ast.cpp b/core/story-manager/tests/test_ast.cpp index 25b5794..a9703aa 100644 --- a/core/story-manager/tests/test_ast.cpp +++ b/core/story-manager/tests/test_ast.cpp @@ -33,6 +33,7 @@ THE SOFTWARE. #include "print_node.h" #include "variable_node.h" #include "function_entry_node.h" +#include "operator_node.h" #include "chip32_machine.h" #include @@ -41,7 +42,7 @@ THE SOFTWARE. #include "ast_builder.h" #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; @@ -97,7 +98,19 @@ TEST_CASE( "Check various indentations and typos" ) { auto functionEntryNode = std::make_shared("function-entry-node"); - auto variableNode = std::make_shared("variable-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"); + + + auto testNode = std::make_shared(); + testNode->SetOperationType(OperatorNode::OperationType::GREATER_THAN); std::vector> nodes; @@ -106,12 +119,16 @@ TEST_CASE( "Check various indentations and typos" ) { nodes.push_back(printNodeTrue); nodes.push_back(printNodeFalse); nodes.push_back(branchNode); - nodes.push_back(variableNode); + nodes.push_back(variableNode1); + nodes.push_back(variableNode2); + nodes.push_back(testNode); auto cn1 = std::make_shared(); auto cn2 = std::make_shared(); auto cn3 = std::make_shared(); auto cn4 = std::make_shared(); + auto cn5 = std::make_shared(); + auto cn6 = std::make_shared(); std::vector> connections; @@ -119,6 +136,8 @@ TEST_CASE( "Check various indentations and typos" ) { connections.push_back(cn2); connections.push_back(cn3); connections.push_back(cn4); + connections.push_back(cn5); + connections.push_back(cn6); // Branch True -> print Ok @@ -142,13 +161,27 @@ TEST_CASE( "Check various indentations and typos" ) { cn3->outNodeId = functionEntryNode->GetId(); cn3->outPortIndex = 0; - // Variable branch -> Branch node (condition input) + // Compare test output -> Branch node (condition input) cn4->inNodeId = branchNode->GetId(); cn4->inPortIndex = 1; - cn4->outNodeId = variableNode->GetId(); + cn4->outNodeId = testNode->GetId(); cn4->outPortIndex = 0; cn4->type = Connection::DATA_LINK; + // Variable 1 -> Compare test node input 1 + cn5->inNodeId = testNode->GetId(); + cn5->inPortIndex = 0; + cn5->outNodeId = variableNode1->GetId(); + cn5->outPortIndex = 0; + cn5->type = Connection::DATA_LINK; + + // Variable 1 -> Compare test node input 1 + cn6->inNodeId = testNode->GetId(); + cn6->inPortIndex = 1; + cn6->outNodeId = variableNode2->GetId(); + cn6->outPortIndex = 0; + cn6->type = Connection::DATA_LINK; + // // Création des nœuds // std::vector nodes = { @@ -188,7 +221,7 @@ TEST_CASE( "Check various indentations and typos" ) { ); // Create generator - AssemblyGenerator generator(context); + AssemblyGeneratorChip32 generator(context); ASTBuilder builder(nodes, connections); @@ -206,20 +239,16 @@ TEST_CASE( "Check various indentations and typos" ) { // Generate flow in the console VisualFlowGenerator flowGenerator(context); - std::string flow = flowGenerator.GenerateAssembly(pathTrees); - FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01"); + std::string flow = flowGenerator.GenerateAssembly(nodes, pathTrees); + + std::cout << "\nGenerated flow:\n" << flow << std::endl; // Generate assembly - std::string assembly = generator.GenerateAssembly(pathTrees); - - - - - - + std::string assembly = generator.GenerateAssembly(nodes, pathTrees); + std::cout << "\nGenerated assembly:\n" << assembly << std::endl; // compiler.generateAssembly();