First working assembly from nodes (cli), youpi

This commit is contained in:
anthony@rabine.fr 2025-04-22 23:20:44 +02:00
parent 3c1224e937
commit a42fdc81ea
12 changed files with 229 additions and 302 deletions

View file

@ -83,9 +83,9 @@ typedef enum
OP_SKIPNZ = 27, ///< skip next instruction if not zero, e.g.: skipnz r2 OP_SKIPNZ = 27, ///< skip next instruction if not zero, e.g.: skipnz r2
// Comparison // Comparison
OP_CMP_EQ = 28, ///< compare two registers for equality, result in first e.g.: cmp_eq r4, r0, r1 (r4 = (r0 == r1 ? 1 : 0) OP_CMP_EQ = 28, ///< compare two registers for equality, result in first e.g.: eq r4, r0, r1 (r4 = (r0 == r1 ? 1 : 0)
OP_CMP_GT = 29, ///< compare if first register is greater than the second, result in first e.g.: cmp_gt r4, r0, r1 OP_CMP_GT = 29, ///< compare if first register is greater than the second, result in first e.g.: gt r4, r0, r1
OP_CMP_LT = 30, ///< compare if first register is less than the second, result in first e.g.: cmp_lt r4, r0, r1 OP_CMP_LT = 30, ///< compare if first register is less than the second, result in first e.g.: lt r4, r0, r1
INSTRUCTION_COUNT INSTRUCTION_COUNT
} chip32_instruction_t; } chip32_instruction_t;

View file

@ -17,6 +17,25 @@ public:
STRING STRING
}; };
enum RandomFlags
{
CHARSET_ALPHABET_LOWER = 0x1, // "abcdefghijklmnopqrstuvwxyz"
CHARSET_ALPHABET_UPPER = 0x2, // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
CHARSET_NUMBERS = 0x4, // "0123456789"
CHARSET_SIGNS = 0x8, // "!@#$%^&*()_+-=[]{}|;:,.<>?";
ALL_CHARSETS = CHARSET_ALPHABET_LOWER | CHARSET_ALPHABET_UPPER |CHARSET_NUMBERS | CHARSET_SIGNS
};
Variable() {
m_uuid = Uuid().String();
m_label = Variable::GenerateRandomString(10, Variable::CHARSET_ALPHABET_LOWER | Variable::CHARSET_ALPHABET_UPPER );
}
Variable (const std::string &name)
: Variable()
{
m_variableName = name;
}
// Setters // Setters
@ -93,6 +112,10 @@ public:
return m_valueType; return m_valueType;
} }
std::string GetLabel() const {
return m_label;
}
template<typename T> template<typename T>
T GetValue() const { T GetValue() const {
try { try {
@ -108,22 +131,51 @@ public:
return m_uuid; return m_uuid;
} }
Variable() { static std::string GenerateRandomString(size_t length, uint32_t flags)
m_uuid = Uuid().String(); {
std::string charset = "";
if (flags & CHARSET_ALPHABET_LOWER)
{
charset += "abcdefghijklmnopqrstuvwxyz";
} }
Variable (const std::string &name) if (flags & CHARSET_ALPHABET_UPPER)
: Variable()
{ {
m_variableName = name; charset += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (flags & CHARSET_NUMBERS)
{
charset += "0123456789";
}
if (flags & CHARSET_SIGNS)
{
charset += "!@#$%^&*()_+-=[]{}|;:,.<>?";
}
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_int_distribution<> distribution(0, charset.size() - 1);
std::string result;
result.reserve(length);
for (size_t i = 0; i < length; ++i) {
result += charset[distribution(generator)];
}
return result;
} }
private: private:
std::string m_variableName; std::string m_variableName; // nom humain
ValueType m_valueType; ValueType m_valueType;
VariableValue m_value; VariableValue m_value;
bool m_isConstant; bool m_isConstant;
std::string m_uuid; std::string m_uuid; // pour identifier le variable dans le JSON du projet
std::string m_label; // pour la génération assembleur
int m_scalePower; // Nombre de bits pour la partie fractionnaire int m_scalePower; // Nombre de bits pour la partie fractionnaire
}; };

View file

@ -56,30 +56,8 @@ public:
m_currentSection = Section::NONE; m_currentSection = Section::NONE;
} }
std::string GenerateAssembly(std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<PathTree>& roots, const std::vector<std::shared_ptr<Variable>> &variables)
{
m_roots = roots;
/*
Reset();
// Generate header comments
GenerateHeader();
// Generate data section
StartSection(Section::DATA);
GenerateDataSection(nodes, roots, variables);
// Generate text section
StartSection(Section::TEXT);
GenerateTextSection(roots);
*/
return m_assembly.str();
}
std::string GenerateAssembly(std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<ASTNode>>& order, const std::vector<std::shared_ptr<Variable>> &variables) std::string GenerateAssembly(std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<ASTNode>>& order, const std::vector<std::shared_ptr<Variable>> &variables)
{ {
// m_roots = roots;
Reset(); Reset();
// Generate header comments // Generate header comments
@ -109,6 +87,8 @@ protected:
virtual void GenerateExit() = 0; virtual void GenerateExit() = 0;
virtual void GenerateVariable(const std::shared_ptr<Variable> v) = 0;
std::string AddStringLiteral(const std::string& text) std::string AddStringLiteral(const std::string& text)
{ {
@ -131,7 +111,7 @@ protected:
std::vector<std::string> m_stringLiterals; std::vector<std::string> m_stringLiterals;
int m_depth{0}; int m_depth{0};
Section m_currentSection; Section m_currentSection;
std::vector<PathTree> m_roots;
private: private:
@ -160,30 +140,18 @@ private:
void GenerateDataSection(const std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<Variable>> &variables) void GenerateDataSection(const std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<Variable>> &variables)
{ {
// Generate all constants // Generate all constants
for (const auto& n : nodes) { for (const auto& n : nodes) {
n->Accept(*this); n->Accept(*this);
} }
// generate all variables in RAM
for (auto & v : variables)
{
GenerateVariable(v);
}
m_assembly << "\n\n"; m_assembly << "\n\n";
// Generate all
/*
// Generate string literals
for (const auto& literal : m_stringLiterals) {
std::string label = "str_" + std::to_string(m_labelCounter++);
m_assembly << label << " db '" << literal << "',0\n"
<< label << "_len equ $ - " << label << "\n";
}
// Generate variables
for (const auto& t : trees) {
CollectVariables(t.root);
}
*/
} }
void GenerateTextSection(const std::vector<std::shared_ptr<ASTNode>>& orderedNodes) { void GenerateTextSection(const std::vector<std::shared_ptr<ASTNode>>& orderedNodes) {
@ -194,28 +162,12 @@ private:
GenerateNodeCode(node); GenerateNodeCode(node);
} }
/*
// Process execution paths first
for (const auto& tree : trees) {
if (tree.isExecutionPath) {
GenerateNodeCode(tree.root);
}
}
// Process data paths
for (const auto& tree : trees) {
if (!tree.isExecutionPath) {
GenerateNodeCode(tree.root, true);
}
}
*/
// Program exit // Program exit
GenerateExit(); GenerateExit();
} }
void CollectVariables(std::shared_ptr<ASTNode> node) { void CollectVariables(std::shared_ptr<ASTNode> node)
{
if (!node) return; if (!node) return;
if (node->IsType<VariableNode>()) { if (node->IsType<VariableNode>()) {

View file

@ -21,19 +21,9 @@ public:
if (m_context.debugOutput) { if (m_context.debugOutput) {
AddComment("Node: " + node->node->GetTypeName() + " (ID: " + node->node->GetId() + ")"); AddComment("Node: " + node->node->GetTypeName() + " (ID: " + node->node->GetId() + ")");
} }
/* // Node label
if (isDataPath) m_assembly << node->node->GetMyEntryLabel() << ":\n";
{
// else if (node->IsType<VariableNode>()) {
// GenerateVariableNode(node);
// }
}
else
{
*/
if (node->IsType<OperatorNode>()) { if (node->IsType<OperatorNode>()) {
GenerateOperatorNode(node); GenerateOperatorNode(node);
} }
@ -46,16 +36,15 @@ public:
else if (node->IsType<PrintNode>()) { else if (node->IsType<PrintNode>()) {
GeneratePrintNode(node); GeneratePrintNode(node);
} }
// }
// If we're processing a data path, traverse data outputs // // If we're processing a data path, traverse data outputs
if (isDataPath) { // if (isDataPath) {
for (const auto& [port, outputs] : node->dataOutputs) { // for (const auto& [port, outputs] : node->dataOutputs) {
for (const auto& target : outputs) { // for (const auto& target : outputs) {
GenerateNodeCode(target.node, true); // GenerateNodeCode(target.node, true);
} // }
} // }
} // }
} }
@ -63,8 +52,6 @@ public:
m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n"; m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n";
} }
virtual void GenerateExit() { virtual void GenerateExit() {
AddComment("Program exit"); AddComment("Program exit");
m_assembly << " halt\n"; m_assembly << " halt\n";
@ -74,55 +61,22 @@ private:
void GenerateFunctionEntry(std::shared_ptr<ASTNode> node) { void GenerateFunctionEntry(std::shared_ptr<ASTNode> node) {
AddComment("Function Entry"); AddComment("Function Entry");
m_depth++;
// for (auto& child : node->children) {
// GenerateNodeCode(child);
// }
m_depth--;
} }
void GenerateBranchNode(std::shared_ptr<ASTNode> node) void GenerateBranchNode(std::shared_ptr<ASTNode> node)
{ {
std::string labelTrue = GenerateUniqueLabel("true");
std::string labelFalse = GenerateUniqueLabel("false");
std::string labelEnd = GenerateUniqueLabel("end");
AddComment("Branch condition evaluation"); AddComment("Branch condition evaluation");
m_depth++; m_depth++;
// Generate condition code auto trueBranch = node->GetChild(0);
// We search a path tree that have a last node equivalent to our node auto falseBranch = node->GetChild(1);
// (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 // Compare result and jump
m_assembly << " pop eax\n" m_assembly << " pop r0\n"
<< " cmp eax, 0\n" << " skipz r0\n"
<< " je " << labelFalse << "\n"; << " jump " << trueBranch->node->GetMyEntryLabel() << "\n"
<< " jump " << falseBranch->node->GetMyEntryLabel() << "\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--; m_depth--;
} }
@ -152,8 +106,27 @@ private:
AddComment("Operator: " + std::to_string(static_cast<int>(opNode->GetOperationType()))); AddComment("Operator: " + std::to_string(static_cast<int>(opNode->GetOperationType())));
m_depth++; m_depth++;
// Generate code for variables // Generate code for variables usage
for (const auto& [port, inputNode] : node->dataInputs) { int reg = 0;
for (const auto& [port, inputNode] : node->dataInputs)
{
// Check if the input node is a variable
if (inputNode->IsType<VariableNode>())
{
auto* varNode = inputNode->GetAs<VariableNode>();
if (varNode) {
auto var = varNode->GetVariable();
// Generate code to load the variable value
// FIXME: hardcoded 4 bytes, replace by actual real variable size
m_assembly << " load r" << reg << ", $" << var->GetLabel() << ", 4" << "; Load variable " << var->GetVariableName() << "\n";
m_assembly << " push r" << reg << "\n";
// Assuming we have a function to load the variable value
// m_assembly << " load r0, " << varNode->GetVariableName() << "\n";
}
reg++;
}
// m_assembly << " load r0, " << inputNode.node->GetId() << "\n"; // m_assembly << " load r0, " << inputNode.node->GetId() << "\n";
} }
@ -161,87 +134,45 @@ private:
// Generate operator code // Generate operator code
switch (opNode->GetOperationType()) { switch (opNode->GetOperationType()) {
case OperatorNode::OperationType::ADD: case OperatorNode::OperationType::ADD:
m_assembly << " pop ebx\n" m_assembly << " pop r0\n"
<< " pop eax\n" << " pop r1\n"
<< " add eax, ebx\n" << " add r0, r1\n"
<< " push eax\n"; << " push r0\n";
break; break;
case OperatorNode::OperationType::SUBTRACT: case OperatorNode::OperationType::SUBTRACT:
m_assembly << " pop ebx\n" m_assembly << " pop r0\n"
<< " pop eax\n" << " pop r1\n"
<< " sub eax, ebx\n" << " sub r0, r1\n"
<< " push eax\n"; << " push r0\n";
break; break;
case OperatorNode::OperationType::MULTIPLY: case OperatorNode::OperationType::MULTIPLY:
m_assembly << " pop ebx\n" m_assembly << " pop r0\n"
<< " pop eax\n" << " pop r1\n"
<< " imul eax, ebx\n" << " mul r0, r1\n"
<< " push eax\n"; << " push r0\n";
break; break;
case OperatorNode::OperationType::DIVIDE: case OperatorNode::OperationType::DIVIDE:
m_assembly << " pop ebx\n" m_assembly << " pop r0\n"
<< " pop eax\n" << " pop r1\n"
<< " cdq\n" << " div r0, r1\n"
<< " idiv ebx\n" << " push r0\n";
<< " push eax\n";
break; break;
// Add other operators... case OperatorNode::OperationType::AND:
m_assembly << " pop r0\n"
/* << " pop r1\n"
<< " and r0, r1\n"
<< " push r0\n";
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; break;
case OperationType::SUBTRACT: case OperatorNode::OperationType::GREATER_THAN:
ss << " pop ebx\n" m_assembly << " pop r0\n"
<< " pop eax\n" << " pop r1\n"
<< " sub eax, ebx\n" << " gt r0, r0, r1\n"
<< " push eax\n"; << " push r0\n";
break; break;
case OperationType::MULTIPLY: default:
ss << " pop ebx\n" // Make voluntary bad assembly
<< " pop eax\n" m_assembly << "------>>>> OPERATOR NOT IMPLEMENTED: " << opNode->GetOperatorSymbol() << "\n";
<< " imul eax, ebx\n"
<< " push eax\n";
break; 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--; m_depth--;
@ -253,23 +184,44 @@ private:
{ {
if (v->GetValueType() == Variable::ValueType::STRING) if (v->GetValueType() == Variable::ValueType::STRING)
{ {
m_assembly << "$" << v->GetVariableName() << " DC8, \"" << v->GetValue<std::string>() << "\"\n"; m_assembly << "$" << v->GetLabel() << " DC8, \"" << v->GetValue<std::string>() << "\" ; " << v->GetVariableName() << "\n";
} }
else if (v->GetValueType() == Variable::ValueType::INTEGER) else if (v->GetValueType() == Variable::ValueType::INTEGER)
{ {
m_assembly << "$" << v->GetVariableName() << " DC32, " << v->GetValue<int>() << "\n"; m_assembly << "$" << v->GetLabel() << " DC32, " << v->GetValue<int>() << " ; " << v->GetVariableName() << "\n";
} }
else if (v->GetValueType() == Variable::ValueType::FLOAT) else if (v->GetValueType() == Variable::ValueType::FLOAT)
{ {
m_assembly << "$" << v->GetVariableName() << " DC32, " << v->GetValue<float>() << "\n"; m_assembly << "$" << v->GetLabel() << " DC32, " << v->GetValue<float>() << " ; " << v->GetVariableName() << "\n";
} }
else if (v->GetValueType() == Variable::ValueType::BOOL) else if (v->GetValueType() == Variable::ValueType::BOOL)
{ {
m_assembly << "$" << v->GetVariableName() << " DCB, " << (v->GetValue<bool>() ? "1" : "0") << "\n"; m_assembly << "$" << v->GetLabel() << " DCB, " << (v->GetValue<bool>() ? "1" : "0") << " ; " << v->GetVariableName() << "\n";
} }
} }
} }
virtual void GenerateVariable(const std::shared_ptr<Variable> v)
{
if (v->GetValueType() == Variable::ValueType::STRING)
{
m_assembly << "$" << v->GetLabel() << " DV8, \"" << v->GetValue<std::string>() << "\" ; " << v->GetVariableName() << "\n";
}
else if (v->GetValueType() == Variable::ValueType::INTEGER)
{
m_assembly << "$" << v->GetLabel() << " DV32, " << v->GetValue<int>() << " ; " << v->GetVariableName() << "\n";
}
else if (v->GetValueType() == Variable::ValueType::FLOAT)
{
m_assembly << "$" << v->GetLabel() << " DV32, " << v->GetValue<float>() << " ; " << v->GetVariableName() << "\n";
}
else if (v->GetValueType() == Variable::ValueType::BOOL)
{
m_assembly << "$" << v->GetLabel() << " DVB, " << (v->GetValue<bool>() ? "1" : "0") << " ; " << v->GetVariableName() << "\n";
}
}
/* /*
void GenerateVariableNode(std::shared_ptr<ASTNode> node) { void GenerateVariableNode(std::shared_ptr<ASTNode> node) {
auto* varNode = node->GetAs<VariableNode>(); auto* varNode = node->GetAs<VariableNode>();

View file

@ -144,12 +144,6 @@ public:
} }
}; };
struct PathTree {
std::shared_ptr<ASTNode> root;
std::shared_ptr<ASTNode> lastNode; // Dernier nœud du PathTree
std::vector<std::shared_ptr<Connection>> connections;
bool isExecutionPath; // true for main flow, false for input paths
};
class ASTBuilder { class ASTBuilder {
public: public:
@ -194,6 +188,9 @@ public:
} }
} }
// Build execution paths
BuildExecutionPath(topologicalOrder, nodeMap);
return topologicalOrder; return topologicalOrder;
} }
@ -202,7 +199,32 @@ private:
const std::vector<std::shared_ptr<BaseNode>>& m_nodes; const std::vector<std::shared_ptr<BaseNode>>& m_nodes;
const std::vector<std::shared_ptr<Connection>>& m_connections; const std::vector<std::shared_ptr<Connection>>& m_connections;
void BuildExecutionPath(std::vector<std::shared_ptr<ASTNode>>& tree,
const std::unordered_map<std::string, std::shared_ptr<ASTNode>>& nodeMap)
{
std::queue<std::shared_ptr<ASTNode>> queue;
queue.push(tree.front());
while (!queue.empty()) {
auto current = queue.front();
queue.pop();
// Find execution connections from this node
for (const auto& conn : m_connections)
{
if (conn->outNodeId == current->node->GetId())
{
auto targetNode = nodeMap.find(conn->inNodeId);
if (targetNode != nodeMap.end())
{
auto childNode = targetNode->second;
current->children.push_back(childNode);
queue.push(childNode);
}
}
}
}
}
std::vector<std::shared_ptr<ASTNode>> ApplyKahnAlgorithm(const std::unordered_map<std::string, std::shared_ptr<ASTNode>> &nodeMap) std::vector<std::shared_ptr<ASTNode>> ApplyKahnAlgorithm(const std::unordered_map<std::string, std::shared_ptr<ASTNode>> &nodeMap)
{ {

View file

@ -66,6 +66,9 @@ protected:
} }
virtual void GenerateVariable(const std::shared_ptr<Variable> v) {
}
virtual void GenerateExit() { virtual void GenerateExit() {

View file

@ -19,44 +19,6 @@ BaseNode::~BaseNode()
std::cout << "Deleted base node" << std::endl; std::cout << "Deleted base node" << std::endl;
} }
std::string BaseNode::GenerateRandomString(size_t length, uint32_t flags)
{
std::string charset = "";
if (flags & CHARSET_ALPHABET_LOWER)
{
charset += "abcdefghijklmnopqrstuvwxyz";
}
if (flags & CHARSET_ALPHABET_UPPER)
{
charset += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (flags & CHARSET_NUMBERS)
{
charset += "0123456789";
}
if (flags & CHARSET_SIGNS)
{
charset += "!@#$%^&*()_+-=[]{}|;:,.<>?";
}
std::random_device rd;
std::mt19937 generator(rd());
std::uniform_int_distribution<> distribution(0, charset.size() - 1);
std::string result;
result.reserve(length);
for (size_t i = 0; i < length; ++i) {
result += charset[distribution(generator)];
}
return result;
}
std::string BaseNode::GetEntryLabel(const std::string &id) std::string BaseNode::GetEntryLabel(const std::string &id)
{ {

View file

@ -44,14 +44,6 @@ public:
float y; float y;
}; };
enum RandomFlags
{
CHARSET_ALPHABET_LOWER = 0x1, // "abcdefghijklmnopqrstuvwxyz"
CHARSET_ALPHABET_UPPER = 0x2, // "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
CHARSET_NUMBERS = 0x4, // "0123456789"
CHARSET_SIGNS = 0x8, // "!@#$%^&*()_+-=[]{}|;:,.<>?";
ALL_CHARSETS = CHARSET_ALPHABET_LOWER | CHARSET_ALPHABET_UPPER |CHARSET_NUMBERS | CHARSET_SIGNS
};
struct ConstantValue struct ConstantValue
{ {
@ -123,8 +115,6 @@ public:
void SetInternalData(const nlohmann::json &j); void SetInternalData(const nlohmann::json &j);
nlohmann::json GetInternalData() const; nlohmann::json GetInternalData() const;
static std::string GenerateRandomString(size_t length, uint32_t flags = RandomFlags::ALL_CHARSETS);
void ClearPorts() { void ClearPorts() {
m_inputPorts.clear(); m_inputPorts.clear();
m_outputPorts.clear(); m_outputPorts.clear();

View file

@ -14,8 +14,6 @@ public:
virtual void Initialize() override; virtual void Initialize() override;
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
virtual std::string GenerateAssembly() const { return ""; }
private: private:
}; };

View file

@ -2,16 +2,15 @@
#include "story_project.h" #include "story_project.h"
#include "connection.h" #include "connection.h"
#include "sys_lib.h" #include "sys_lib.h"
#include "variable.h"
PrintNode::PrintNode(const std::string &type) PrintNode::PrintNode(const std::string &type)
: BaseNode(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 // Create empty variable in memory
auto v = std::make_shared<Variable>(m_label); auto v = std::make_shared<Variable>(m_label);
v->SetTextValue(""); v->SetTextValue("");
m_label = v->GetLabel();
m_variables[m_label] = v; m_variables[m_label] = v;
} }

View file

@ -17,20 +17,18 @@ public:
virtual void Initialize() override; virtual void Initialize() override;
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override; virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
virtual std::string GenerateAssembly() const { return ""; }
void StoreInternalData(); void StoreInternalData();
void SetVariableUuid(const std::string &uuid) { void SetVariable(const std::shared_ptr<Variable> v) {
m_variableUuid = uuid; m_variable = v;
} }
std::string GetVariableUuid() const { std::shared_ptr<Variable> GetVariable() const {
return m_variableUuid; return m_variable;
} }
private: private:
std::string m_variableUuid; std::shared_ptr<Variable> m_variable;
}; };

View file

@ -84,16 +84,16 @@ TEST_CASE( "Check various indentations and typos" ) {
variables.push_back(var4); variables.push_back(var4);
auto variableNodeX = std::make_shared<VariableNode>("variable-node"); auto variableNodeX = std::make_shared<VariableNode>("variable-node");
variableNodeX->SetVariableUuid(var1->GetUuid()); variableNodeX->SetVariable(var1);
auto variableNodeY = std::make_shared<VariableNode>("variable-node"); auto variableNodeY = std::make_shared<VariableNode>("variable-node");
variableNodeY->SetVariableUuid(var2->GetUuid()); variableNodeY->SetVariable(var2);
auto variableNodeA = std::make_shared<VariableNode>("variable-node"); auto variableNodeA = std::make_shared<VariableNode>("variable-node");
variableNodeA->SetVariableUuid(var3->GetUuid()); variableNodeA->SetVariable(var3);
auto variableNodeB = std::make_shared<VariableNode>("variable-node"); auto variableNodeB = std::make_shared<VariableNode>("variable-node");
variableNodeB->SetVariableUuid(var4->GetUuid()); variableNodeB->SetVariable(var4);
auto testNode = std::make_shared<OperatorNode>(); auto testNode = std::make_shared<OperatorNode>();
testNode->SetOperationType(OperatorNode::OperationType::GREATER_THAN); testNode->SetOperationType(OperatorNode::OperationType::GREATER_THAN);
@ -227,25 +227,24 @@ TEST_CASE( "Check various indentations and typos" ) {
ASTBuilder builder(nodes, connections); ASTBuilder builder(nodes, connections);
auto pathTrees = builder.BuildAST(); auto pathTree = builder.BuildAST();
// Generate flow in the console // Generate flow in the console
VisualFlowGenerator flowGenerator(context); VisualFlowGenerator flowGenerator(context);
FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01"); FlowVisualizer::PrintHeader("arabine", "2025-04-08 12:03:01");
std::string flow = flowGenerator.GenerateAssembly(nodes, pathTrees, variables); std::string flow = flowGenerator.GenerateAssembly(nodes, pathTree, variables);
std::cout << "\nGenerated flow:\n" << flow << std::endl; std::cout << "\nGenerated flow:\n" << flow << std::endl;
// Generate assembly // Generate assembly
std::string assembly = generator.GenerateAssembly(nodes, pathTrees, variables); std::string assembly = generator.GenerateAssembly(nodes, pathTree, variables);
std::cout << "\nGenerated assembly:\n" << assembly << std::endl; std::cout << "\nGenerated assembly:\n" << assembly << std::endl;
// Chip32::Machine machine; Chip32::Machine machine;
// machine.QuickExecute(compiler.GetCode()); machine.QuickExecute(assembly);
// REQUIRE( parseResult == true );
} }