Modified TAC for all new syscall widgets
Some checks are pending
Build-StoryEditor / build_win32 (push) Waiting to run
Build-StoryEditor / build_linux (push) Waiting to run

This commit is contained in:
Anthony Rabine 2025-10-20 19:44:53 +02:00
parent 765f78fbc6
commit c29d099ec9
5 changed files with 359 additions and 94 deletions

View file

@ -130,6 +130,10 @@ public:
return m_assembly.str(); return m_assembly.str();
} }
GeneratorContext& Context() {
return m_context;
}
protected: protected:
virtual void GenerateNodeCode(std::shared_ptr<ASTNode> node, bool isDataPath = false) = 0; virtual void GenerateNodeCode(std::shared_ptr<ASTNode> node, bool isDataPath = false) = 0;

View file

@ -49,7 +49,7 @@ public:
// === ÉTAPE 3 : GÉNÉRATION TAC === // === ÉTAPE 3 : GÉNÉRATION TAC ===
m_tacGenerator = std::make_unique<TACGenerator>(); m_tacGenerator = std::make_unique<TACGenerator>();
m_tacProgram = m_tacGenerator->Generate(astNodes); m_tacProgram = m_tacGenerator->Generate(astNodes, Context().variables);
// DEBUG : Afficher le TAC généré // DEBUG : Afficher le TAC généré
if (m_context.debugOutput) { if (m_context.debugOutput) {

View file

@ -23,6 +23,10 @@ class PrintNode;
class BranchNode; class BranchNode;
class FunctionEntryNode; class FunctionEntryNode;
class CallFunctionNode; class CallFunctionNode;
class WaitEventNode;
class WaitDelayNode;
class PlayMediaNode;
class SendSignalNode;
// =================================================================== // ===================================================================
// TAC Operand - Représente une opérande (variable, temporaire, constante) // TAC Operand - Représente une opérande (variable, temporaire, constante)
@ -305,6 +309,10 @@ private:
// Note: Nécessite les includes des types de nœuds concrets // Note: Nécessite les includes des types de nœuds concrets
// =================================================================== // ===================================================================
// ===================================================================
// SECTION 1: INCLUDES (à ajouter après les includes existants)
// ===================================================================
#include "ast_builder.h" #include "ast_builder.h"
#include "variable_node.h" #include "variable_node.h"
#include "operator_node.h" #include "operator_node.h"
@ -312,15 +320,30 @@ private:
#include "branch_node.h" #include "branch_node.h"
#include "function_entry_node.h" #include "function_entry_node.h"
#include "call_function_node.h" #include "call_function_node.h"
#include "wait_event_node.h"
#include "wait_delay_node.h"
#include "play_media_node.h"
#include "send_signal_node.h"
// ===================================================================
// SECTION 2: CLASSE TACGenerator - MODIFICATIONS
// ===================================================================
class TACGenerator { class TACGenerator {
public: public:
TACGenerator() : m_tempCounter(0), m_labelCounter(0) {} TACGenerator() : m_tempCounter(0), m_labelCounter(0) {}
// Génère le TAC à partir de l'AST // ===================================================================
TACProgram Generate(const std::vector<std::shared_ptr<ASTNode>>& astNodes) { // NOUVELLE SIGNATURE: Génère le TAC à partir de l'AST + Variables
// ===================================================================
TACProgram Generate(const std::vector<std::shared_ptr<ASTNode>>& astNodes,
const std::vector<std::shared_ptr<Variable>>& variables) {
std::cout << "\n=== TACGenerator::Generate() START ===\n"; std::cout << "\n=== TACGenerator::Generate() START ===\n";
std::cout << "Number of AST nodes received: " << astNodes.size() << "\n"; std::cout << "Number of AST nodes received: " << astNodes.size() << "\n";
std::cout << "Number of variables: " << variables.size() << "\n";
// Stocker les variables pour résolution ultérieure
m_variables = variables;
m_program.Clear(); m_program.Clear();
m_tempCounter = 0; m_tempCounter = 0;
@ -328,8 +351,7 @@ public:
m_nodeResults.clear(); m_nodeResults.clear();
m_visitedNodes.clear(); m_visitedNodes.clear();
// Simplement appeler GenerateNode pour chaque nœud // Générer le code pour chaque nœud
// La gestion des doublons se fait dans GenerateNode()
for (size_t i = 0; i < astNodes.size(); i++) { for (size_t i = 0; i < astNodes.size(); i++) {
const auto& node = astNodes[i]; const auto& node = astNodes[i];
std::cout << "Processing AST node [" << i << "]: " std::cout << "Processing AST node [" << i << "]: "
@ -360,6 +382,9 @@ private:
// Set pour éviter de visiter deux fois le même nœud // Set pour éviter de visiter deux fois le même nœud
std::set<std::string> m_visitedNodes; std::set<std::string> m_visitedNodes;
// NOUVEAU: Variables disponibles pour résolution
std::vector<std::shared_ptr<Variable>> m_variables;
// =================================================================== // ===================================================================
// HELPERS // HELPERS
@ -382,17 +407,43 @@ private:
} }
// =================================================================== // ===================================================================
// GÉNÉRATION RÉCURSIVE // NOUVEAU: HELPERS POUR RÉSOLUTION DE VARIABLES
// ===================================================================
std::shared_ptr<Variable> ResolveVariableByUuid(const std::string& uuid) const {
if (uuid.empty()) {
return nullptr;
}
for (const auto& var : m_variables) {
if (var->GetUuid() == uuid) {
return var;
}
}
std::cerr << "WARNING: Variable with UUID " << uuid << " not found!\n";
return nullptr;
}
std::string GetVariableLabel(const std::string& uuid) const {
auto var = ResolveVariableByUuid(uuid);
if (var) {
return var->GetLabel();
}
return "unknown_var";
}
// ===================================================================
// GÉNÉRATION RÉCURSIVE - DISPATCHER
// =================================================================== // ===================================================================
// Génère le code pour un nœud et retourne où est stocké son résultat
std::shared_ptr<TACOperand> GenerateNode(std::shared_ptr<ASTNode> node) { std::shared_ptr<TACOperand> GenerateNode(std::shared_ptr<ASTNode> node) {
if (!node) return nullptr; if (!node) return nullptr;
std::cout << " GenerateNode(" << node->node->GetTypeName() std::cout << " GenerateNode(" << node->node->GetTypeName()
<< ", ID: " << node->GetId() << ")\n"; << ", ID: " << node->GetId() << ")\n";
// NOUVEAU : Vérifier si ce nœud a déjà été complètement traité // Vérifier si ce nœud a déjà été complètement traité
if (m_visitedNodes.find(node->GetId()) != m_visitedNodes.end()) { if (m_visitedNodes.find(node->GetId()) != m_visitedNodes.end()) {
std::cout << " -> Node already fully processed, SKIPPING\n"; std::cout << " -> Node already fully processed, SKIPPING\n";
// Retourner le résultat en cache s'il existe // Retourner le résultat en cache s'il existe
@ -416,6 +467,10 @@ private:
std::shared_ptr<TACOperand> result = nullptr; std::shared_ptr<TACOperand> result = nullptr;
// ===================================================================
// DISPATCHER PAR TYPE DE NŒUD
// ===================================================================
if (node->IsType<VariableNode>()) { if (node->IsType<VariableNode>()) {
std::cout << " -> Type: VariableNode\n"; std::cout << " -> Type: VariableNode\n";
result = GenerateVariableNode(node); result = GenerateVariableNode(node);
@ -436,6 +491,25 @@ private:
std::cout << " -> Type: CallFunctionNode\n"; std::cout << " -> Type: CallFunctionNode\n";
GenerateCallFunctionNode(node); GenerateCallFunctionNode(node);
} }
// ===================================================================
// NŒUDS SYSCALL
// ===================================================================
else if (node->IsType<WaitEventNode>()) {
std::cout << " -> Type: WaitEventNode\n";
GenerateWaitEventNode(node);
}
else if (node->IsType<WaitDelayNode>()) {
std::cout << " -> Type: WaitDelayNode\n";
GenerateWaitDelayNode(node);
}
else if (node->IsType<PlayMediaNode>()) {
std::cout << " -> Type: PlayMediaNode\n";
GeneratePlayMediaNode(node);
}
else if (node->IsType<SendSignalNode>()) {
std::cout << " -> Type: SendSignalNode\n";
GenerateSendSignalNode(node);
}
else if (node->IsType<FunctionEntryNode>()) { else if (node->IsType<FunctionEntryNode>()) {
std::cout << " -> Type: FunctionEntryNode (generating children)\n"; std::cout << " -> Type: FunctionEntryNode (generating children)\n";
// Entry point, générer les enfants // Entry point, générer les enfants
@ -455,7 +529,7 @@ private:
} }
// =================================================================== // ===================================================================
// GÉNÉRATION PAR TYPE DE NŒUD // GÉNÉRATION PAR TYPE DE NŒUD - EXISTANTS (pas de changement)
// =================================================================== // ===================================================================
std::shared_ptr<TACOperand> GenerateVariableNode(std::shared_ptr<ASTNode> node) { std::shared_ptr<TACOperand> GenerateVariableNode(std::shared_ptr<ASTNode> node) {
@ -564,94 +638,27 @@ private:
// RÉCUPÉRER ET CONVERTIR LE FORMAT STRING // RÉCUPÉRER ET CONVERTIR LE FORMAT STRING
std::string formatString = printNode->GetText(); std::string formatString = printNode->GetText();
// Évaluer tous les arguments et déterminer leurs types // Évaluer tous les arguments
std::vector<std::shared_ptr<TACOperand>> args; std::vector<std::shared_ptr<TACOperand>> args;
std::vector<Variable::ValueType> argTypes;
// Collecter et trier les inputs par port index // Collecter et trier les inputs par port index
std::vector<std::pair<unsigned int, std::shared_ptr<ASTNode>>> sortedInputs; std::vector<std::pair<unsigned int, std::shared_ptr<ASTNode>>> sortedInputs;
for (const auto& [port, inputNode] : node->dataInputs) { for (const auto& [port, inputNode] : node->dataInputs) {
std::cout << " Found input at port " << port
<< " -> " << inputNode->node->GetTypeName() << "\n";
sortedInputs.push_back({port, inputNode}); sortedInputs.push_back({port, inputNode});
} }
std::sort(sortedInputs.begin(), sortedInputs.end(), std::sort(sortedInputs.begin(), sortedInputs.end(),
[](const auto& a, const auto& b) { return a.first < b.first; }); [](const auto& a, const auto& b) { return a.first < b.first; });
// Générer le code pour chaque argument ET récupérer son type // Générer le code pour chaque argument
for (const auto& [port, inputNode] : sortedInputs) { for (const auto& [port, inputNode] : sortedInputs) {
std::cout << " Processing input port " << port << "\n";
auto argOperand = GenerateNode(inputNode); auto argOperand = GenerateNode(inputNode);
if (argOperand) { if (argOperand) {
std::cout << " -> Got operand: " << argOperand->ToString() << "\n";
args.push_back(argOperand); args.push_back(argOperand);
// DÉTERMINER LE TYPE DE L'ARGUMENT
Variable::ValueType argType = Variable::ValueType::INTEGER; // défaut
if (inputNode->IsType<VariableNode>()) {
auto* varNode = inputNode->GetAs<VariableNode>();
auto var = varNode->GetVariable();
if (var) {
argType = var->GetValueType();
std::cout << " -> Variable type: "
<< Variable::ValueTypeToString(argType) << "\n";
}
}
// Pour les OperatorNode, le résultat est toujours un INTEGER
else if (inputNode->IsType<OperatorNode>()) {
argType = Variable::ValueType::INTEGER;
}
argTypes.push_back(argType);
} }
} }
std::cout << " Total args collected: " << args.size() << "\n";
// CONVERTIR LES PLACEHOLDERS EN FONCTION DU TYPE
for (size_t i = 0; i < argTypes.size() && i < 4; i++) {
std::string placeholder = "{" + std::to_string(i) + "}";
std::string formatSpec;
switch (argTypes[i]) {
case Variable::ValueType::STRING:
formatSpec = "{" + std::to_string(i) + ":s}";
break;
case Variable::ValueType::INTEGER:
formatSpec = "{" + std::to_string(i) + ":d}";
break;
case Variable::ValueType::FLOAT:
formatSpec = "{" + std::to_string(i) + ":f}";
break;
default:
formatSpec = "{" + std::to_string(i) + ":d}";
}
// Remplacer {0} par {0:d} ou {0:s}
size_t pos = formatString.find(placeholder);
if (pos != std::string::npos) {
formatString.replace(pos, placeholder.length(), formatSpec);
}
}
// METTRE À JOUR LE FORMAT STRING DANS LA VARIABLE
auto formatVar = printNode->GetVariable(printNode->GetLabel());
if (formatVar) {
formatVar->SetTextValue(formatString);
std::cout << " Updated format string to: " << formatString << "\n";
}
// Créer l'opérande pour la chaîne de format (avec le format mis à jour)
auto formatOperand = std::make_shared<TACOperand>(
TACOperand::Type::VARIABLE,
printNode->GetLabel()
);
// Générer les instructions PARAM pour chaque argument // Générer les instructions PARAM pour chaque argument
for (size_t i = 0; i < args.size(); i++) { for (size_t i = 0; i < args.size(); i++) {
std::cout << " Generating PARAM instruction [" << i << "] for "
<< args[i]->ToString() << "\n";
auto paramInstr = std::make_shared<TACInstruction>( auto paramInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM, TACInstruction::OpCode::PARAM,
args[i] args[i]
@ -659,8 +666,13 @@ private:
m_program.AddInstruction(paramInstr); m_program.AddInstruction(paramInstr);
} }
// Créer l'opérande pour la chaîne de format
auto formatOperand = std::make_shared<TACOperand>(
TACOperand::Type::VARIABLE,
printNode->GetLabel()
);
// Générer l'instruction PRINT // Générer l'instruction PRINT
std::cout << " Generating PRINT instruction\n";
auto printInstr = std::make_shared<TACInstruction>( auto printInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PRINT, TACInstruction::OpCode::PRINT,
formatOperand formatOperand
@ -702,7 +714,6 @@ private:
} }
// Évaluer la condition (le BranchNode reçoit la condition sur le port 1) // Évaluer la condition (le BranchNode reçoit la condition sur le port 1)
// La condition provient généralement d'un OperatorNode (comparaison)
auto conditionInput = node->GetDataInput(1); auto conditionInput = node->GetDataInput(1);
if (!conditionInput) { if (!conditionInput) {
throw std::runtime_error("BranchNode missing condition input on port 1"); throw std::runtime_error("BranchNode missing condition input on port 1");
@ -765,11 +776,262 @@ private:
); );
m_program.AddInstruction(labelEnd); m_program.AddInstruction(labelEnd);
} }
// ===================================================================
// NOUVEAUX GÉNÉRATEURS POUR LES NŒUDS SYSCALL
// ===================================================================
void GenerateWaitDelayNode(std::shared_ptr<ASTNode> node) {
auto* waitDelayNode = node->GetAs<WaitDelayNode>();
if (!waitDelayNode) return;
std::cout << " GenerateWaitDelayNode: duration="
<< waitDelayNode->GetDuration() << "ms\n";
// Vérifier s'il y a un override depuis un port data (IN 1)
auto durationInput = node->GetDataInput(1);
std::shared_ptr<TACOperand> durationOperand;
if (durationInput) {
// Évaluer l'expression connectée
durationOperand = GenerateNode(durationInput);
std::cout << " Duration from port 1: " << durationOperand->ToString() << "\n";
} else {
// Utiliser la valeur par défaut
durationOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT,
std::to_string(waitDelayNode->GetDuration())
);
std::cout << " Duration from property: " << waitDelayNode->GetDuration() << "\n";
}
// PARAM pour la durée (R0)
auto paramInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM,
durationOperand
);
m_program.AddInstruction(paramInstr);
// SYSCALL 5
auto syscallNumOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "5"
);
auto syscallInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::SYSCALL,
syscallNumOperand
);
m_program.AddInstruction(syscallInstr);
}
void GenerateSendSignalNode(std::shared_ptr<ASTNode> node) {
auto* sendSignalNode = node->GetAs<SendSignalNode>();
if (!sendSignalNode) return;
std::cout << " GenerateSendSignalNode: signal_id="
<< sendSignalNode->GetSignalId() << "\n";
// Vérifier s'il y a un override depuis un port data (IN 1)
auto signalInput = node->GetDataInput(1);
std::shared_ptr<TACOperand> signalOperand;
if (signalInput) {
signalOperand = GenerateNode(signalInput);
std::cout << " Signal ID from port 1: " << signalOperand->ToString() << "\n";
} else {
signalOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT,
std::to_string(sendSignalNode->GetSignalId())
);
std::cout << " Signal ID from property: " << sendSignalNode->GetSignalId() << "\n";
}
// PARAM pour le signal ID (R0)
auto paramInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM,
signalOperand
);
m_program.AddInstruction(paramInstr);
// SYSCALL 3
auto syscallNumOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "3"
);
auto syscallInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::SYSCALL,
syscallNumOperand
);
m_program.AddInstruction(syscallInstr);
}
void GeneratePlayMediaNode(std::shared_ptr<ASTNode> node) {
auto* playMediaNode = node->GetAs<PlayMediaNode>();
if (!playMediaNode) return;
std::cout << " GeneratePlayMediaNode (data-driven)\n";
// Image name (R0) - depuis le port data IN 1
auto imageInput = node->GetDataInput(1);
std::shared_ptr<TACOperand> imageOperand;
if (imageInput) {
imageOperand = GenerateNode(imageInput);
std::cout << " Image from port 1: " << imageOperand->ToString() << "\n";
} else {
// Pas de connexion = null pointer (0)
imageOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "0"
);
std::cout << " No image connected (null)\n";
}
// Sound name (R1) - depuis le port data IN 2
auto soundInput = node->GetDataInput(2);
std::shared_ptr<TACOperand> soundOperand;
if (soundInput) {
soundOperand = GenerateNode(soundInput);
std::cout << " Sound from port 2: " << soundOperand->ToString() << "\n";
} else {
// Pas de connexion = null pointer (0)
soundOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "0"
);
std::cout << " No sound connected (null)\n";
}
// PARAMs
auto paramImage = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM, imageOperand
);
m_program.AddInstruction(paramImage);
auto paramSound = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM, soundOperand
);
m_program.AddInstruction(paramSound);
// SYSCALL 1
auto syscallNumOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "1"
);
auto syscallInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::SYSCALL,
syscallNumOperand
);
m_program.AddInstruction(syscallInstr);
// Optionnel: stocker le status de retour
std::string statusVarUuid = playMediaNode->GetStatusVariableUuid();
if (!statusVarUuid.empty()) {
std::string varLabel = GetVariableLabel(statusVarUuid);
std::cout << " Storing status in variable: " << varLabel << "\n";
auto resultOperand = std::make_shared<TACOperand>(
TACOperand::Type::VARIABLE,
varLabel
);
auto r0Operand = std::make_shared<TACOperand>(
TACOperand::Type::REGISTER, "r0"
);
auto storeInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::STORE,
resultOperand,
r0Operand
);
m_program.AddInstruction(storeInstr);
}
}
void GenerateWaitEventNode(std::shared_ptr<ASTNode> node) {
auto* waitEventNode = node->GetAs<WaitEventNode>();
if (!waitEventNode) return;
std::cout << " GenerateWaitEventNode: mask=0x"
<< std::hex << waitEventNode->GetEventMask() << std::dec
<< ", timeout=" << waitEventNode->GetTimeout() << "ms\n";
// Event mask (R0)
auto maskInput = node->GetDataInput(1);
std::shared_ptr<TACOperand> maskOperand;
if (maskInput) {
maskOperand = GenerateNode(maskInput);
std::cout << " Event mask from port 1: " << maskOperand->ToString() << "\n";
} else {
maskOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT,
std::to_string(waitEventNode->GetEventMask())
);
std::cout << " Event mask from property: 0x" << std::hex
<< waitEventNode->GetEventMask() << std::dec << "\n";
}
// Timeout (R1)
auto timeoutInput = node->GetDataInput(2);
std::shared_ptr<TACOperand> timeoutOperand;
if (timeoutInput) {
timeoutOperand = GenerateNode(timeoutInput);
std::cout << " Timeout from port 2: " << timeoutOperand->ToString() << "\n";
} else {
timeoutOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT,
std::to_string(waitEventNode->GetTimeout())
);
std::cout << " Timeout from property: " << waitEventNode->GetTimeout() << "ms\n";
}
// PARAMs
auto paramMask = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM, maskOperand
);
m_program.AddInstruction(paramMask);
auto paramTimeout = std::make_shared<TACInstruction>(
TACInstruction::OpCode::PARAM, timeoutOperand
);
m_program.AddInstruction(paramTimeout);
// SYSCALL 2
auto syscallNumOperand = std::make_shared<TACOperand>(
TACOperand::Type::CONSTANT, "2"
);
auto syscallInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::SYSCALL,
syscallNumOperand
);
m_program.AddInstruction(syscallInstr);
// IMPORTANT: Stocker le résultat dans la variable configurée
std::string resultVarUuid = waitEventNode->GetResultVariableUuid();
if (!resultVarUuid.empty()) {
std::string varLabel = GetVariableLabel(resultVarUuid);
std::cout << " Storing result in variable: " << varLabel << "\n";
auto resultOperand = std::make_shared<TACOperand>(
TACOperand::Type::VARIABLE,
varLabel
);
auto r0Operand = std::make_shared<TACOperand>(
TACOperand::Type::REGISTER, "r0"
);
auto storeInstr = std::make_shared<TACInstruction>(
TACInstruction::OpCode::STORE,
resultOperand,
r0Operand
);
m_program.AddInstruction(storeInstr);
} else {
std::cout << " No result variable, R0 will contain event code\n";
}
}
}; };
// =================================================================== // ===================================================================
// FIN DU FICHIER // FIN DES ADDITIONS
// =================================================================== // ===================================================================
// Note: La conversion TAC → Assembleur est dans AssemblyGeneratorChip32TAC
// Ce fichier ne contient QUE la représentation TAC pure
// ===================================================================

View file

@ -422,7 +422,7 @@ bool StoryProject::GenerateCompleteProgram(std::string &assembly)
// Générer le TAC pour cette page // Générer le TAC pour cette page
TACGenerator tacGen; TACGenerator tacGen;
TACProgram pageTAC = tacGen.Generate(astNodes); TACProgram pageTAC = tacGen.Generate(astNodes, m_variables);
// Stocker le TAC // Stocker le TAC
pageTACPrograms[pageUuid] = pageTAC; pageTACPrograms[pageUuid] = pageTAC;

View file

@ -256,12 +256,15 @@ TEST_CASE( "Check AST with basic nodes" ) {
TEST_CASE("TAC Generation - Print with 2 variables", "[tac][print]") { TEST_CASE("TAC Generation - Print with 2 variables", "[tac][print]") {
// === SETUP === // === SETUP ===
std::vector<std::shared_ptr<Variable>> variables;
// Créer les variables // Créer les variables
auto var_a = std::make_shared<Variable>("a"); auto var_a = std::make_shared<Variable>("a");
var_a->SetIntegerValue(10); var_a->SetIntegerValue(10);
variables.push_back(var_a);
auto var_b = std::make_shared<Variable>("b"); auto var_b = std::make_shared<Variable>("b");
var_b->SetIntegerValue(20); var_b->SetIntegerValue(20);
variables.push_back(var_b);
// Créer les nœuds // Créer les nœuds
auto functionEntry = std::make_shared<FunctionEntryNode>("function-entry-node"); auto functionEntry = std::make_shared<FunctionEntryNode>("function-entry-node");
@ -320,7 +323,8 @@ TEST_CASE("TAC Generation - Print with 2 variables", "[tac][print]") {
// === GENERATE TAC === // === GENERATE TAC ===
TACGenerator tacGen; TACGenerator tacGen;
TACProgram tac = tacGen.Generate(astNodes);
TACProgram tac = tacGen.Generate(astNodes, variables);
// === DISPLAY TAC (for debugging) === // === DISPLAY TAC (for debugging) ===
std::cout << "\n" << tac.ToString() << std::endl; std::cout << "\n" << tac.ToString() << std::endl;
@ -688,7 +692,7 @@ TEST_CASE("Complex AST with TAC - Intermediate results and reuse", "[tac][comple
// === GENERATE TAC === // === GENERATE TAC ===
std::cout << "\n--- Generating TAC ---\n"; std::cout << "\n--- Generating TAC ---\n";
TACGenerator tacGen; TACGenerator tacGen;
TACProgram tac = tacGen.Generate(pathTree); TACProgram tac = tacGen.Generate(pathTree, variables);
std::cout << "\n" << tac.ToString() << std::endl; std::cout << "\n" << tac.ToString() << std::endl;
@ -760,11 +764,6 @@ TEST_CASE("Complex AST with TAC - Intermediate results and reuse", "[tac][comple
REQUIRE(assembly.find(".main:") != std::string::npos); REQUIRE(assembly.find(".main:") != std::string::npos);
REQUIRE(assembly.find("halt") != std::string::npos); REQUIRE(assembly.find("halt") != std::string::npos);
// Vérifier la conversion {0} → %d dans les format strings
REQUIRE(assembly.find("{0}") == std::string::npos);
REQUIRE(assembly.find("{1}") == std::string::npos);
REQUIRE(assembly.find("{2}") == std::string::npos);
// Vérifier présence de syscall 4 (print) // Vérifier présence de syscall 4 (print)
REQUIRE(assembly.find("syscall 4") != std::string::npos); REQUIRE(assembly.find("syscall 4") != std::string::npos);
@ -1094,7 +1093,7 @@ TestResult RunComplexTACTest(int valueA, int valueB, int valueC, int threshold)
// Generate TAC // Generate TAC
TACGenerator tacGen; TACGenerator tacGen;
TACProgram tac = tacGen.Generate(pathTree); TACProgram tac = tacGen.Generate(pathTree, variables);
result.tacOutput = tac.ToString(); result.tacOutput = tac.ToString();
// Verify TAC structure // Verify TAC structure
@ -1150,7 +1149,7 @@ TEST_CASE("Complex AST with TAC - Multiple test cases", "[tac][complex][ast2]")
auto [nodes, conns] = BuildComplexDiagram(vars, 10, 5, 3, 40); auto [nodes, conns] = BuildComplexDiagram(vars, 10, 5, 3, 40);
ASTBuilder builder(nodes, conns); ASTBuilder builder(nodes, conns);
auto tree = builder.BuildAST(); auto tree = builder.BuildAST();
TACProgram tac = tacGen.Generate(tree); TACProgram tac = tacGen.Generate(tree, vars);
int addCount = 0, subCount = 0, mulCount = 0, gtCount = 0; int addCount = 0, subCount = 0, mulCount = 0, gtCount = 0;
for (const auto& instr : tac.GetInstructions()) { for (const auto& instr : tac.GetInstructions()) {