mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
First working assembly from nodes (cli), youpi
This commit is contained in:
parent
3c1224e937
commit
a42fdc81ea
12 changed files with 229 additions and 302 deletions
|
|
@ -83,9 +83,9 @@ typedef enum
|
|||
OP_SKIPNZ = 27, ///< skip next instruction if not zero, e.g.: skipnz r2
|
||||
|
||||
// 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_GT = 29, ///< compare if first register is greater than the second, result in first e.g.: cmp_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_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.: gt 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
|
||||
} chip32_instruction_t;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,25 @@ public:
|
|||
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
|
||||
|
||||
|
|
@ -93,6 +112,10 @@ public:
|
|||
return m_valueType;
|
||||
}
|
||||
|
||||
std::string GetLabel() const {
|
||||
return m_label;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T GetValue() const {
|
||||
try {
|
||||
|
|
@ -108,22 +131,51 @@ public:
|
|||
return m_uuid;
|
||||
}
|
||||
|
||||
Variable() {
|
||||
m_uuid = Uuid().String();
|
||||
static std::string GenerateRandomString(size_t length, uint32_t flags)
|
||||
{
|
||||
std::string charset = "";
|
||||
|
||||
if (flags & CHARSET_ALPHABET_LOWER)
|
||||
{
|
||||
charset += "abcdefghijklmnopqrstuvwxyz";
|
||||
}
|
||||
|
||||
Variable (const std::string &name)
|
||||
: Variable()
|
||||
if (flags & CHARSET_ALPHABET_UPPER)
|
||||
{
|
||||
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:
|
||||
std::string m_variableName;
|
||||
std::string m_variableName; // nom humain
|
||||
ValueType m_valueType;
|
||||
VariableValue m_value;
|
||||
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
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,30 +56,8 @@ public:
|
|||
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)
|
||||
{
|
||||
// m_roots = roots;
|
||||
Reset();
|
||||
|
||||
// Generate header comments
|
||||
|
|
@ -109,6 +87,8 @@ protected:
|
|||
|
||||
virtual void GenerateExit() = 0;
|
||||
|
||||
virtual void GenerateVariable(const std::shared_ptr<Variable> v) = 0;
|
||||
|
||||
|
||||
std::string AddStringLiteral(const std::string& text)
|
||||
{
|
||||
|
|
@ -131,7 +111,7 @@ protected:
|
|||
std::vector<std::string> m_stringLiterals;
|
||||
int m_depth{0};
|
||||
Section m_currentSection;
|
||||
std::vector<PathTree> m_roots;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -160,30 +140,18 @@ private:
|
|||
|
||||
void GenerateDataSection(const std::vector<std::shared_ptr<BaseNode>> &nodes, const std::vector<std::shared_ptr<Variable>> &variables)
|
||||
{
|
||||
|
||||
// Generate all constants
|
||||
for (const auto& n : nodes) {
|
||||
n->Accept(*this);
|
||||
}
|
||||
|
||||
// generate all variables in RAM
|
||||
for (auto & v : variables)
|
||||
{
|
||||
GenerateVariable(v);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
@ -194,28 +162,12 @@ private:
|
|||
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
|
||||
GenerateExit();
|
||||
}
|
||||
|
||||
void CollectVariables(std::shared_ptr<ASTNode> node) {
|
||||
void CollectVariables(std::shared_ptr<ASTNode> node)
|
||||
{
|
||||
if (!node) return;
|
||||
|
||||
if (node->IsType<VariableNode>()) {
|
||||
|
|
|
|||
|
|
@ -21,19 +21,9 @@ public:
|
|||
if (m_context.debugOutput) {
|
||||
AddComment("Node: " + node->node->GetTypeName() + " (ID: " + node->node->GetId() + ")");
|
||||
}
|
||||
/*
|
||||
if (isDataPath)
|
||||
{
|
||||
// Node label
|
||||
m_assembly << node->node->GetMyEntryLabel() << ":\n";
|
||||
|
||||
|
||||
// else if (node->IsType<VariableNode>()) {
|
||||
// GenerateVariableNode(node);
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
*/
|
||||
if (node->IsType<OperatorNode>()) {
|
||||
GenerateOperatorNode(node);
|
||||
}
|
||||
|
|
@ -46,16 +36,15 @@ public:
|
|||
else if (node->IsType<PrintNode>()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // 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);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -63,8 +52,6 @@ public:
|
|||
m_assembly << std::string(m_depth * 4, ' ') << "; " << comment << "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void GenerateExit() {
|
||||
AddComment("Program exit");
|
||||
m_assembly << " halt\n";
|
||||
|
|
@ -74,55 +61,22 @@ private:
|
|||
|
||||
void GenerateFunctionEntry(std::shared_ptr<ASTNode> node) {
|
||||
AddComment("Function Entry");
|
||||
m_depth++;
|
||||
|
||||
// for (auto& child : node->children) {
|
||||
// GenerateNodeCode(child);
|
||||
// }
|
||||
|
||||
m_depth--;
|
||||
}
|
||||
|
||||
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");
|
||||
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() + ")");
|
||||
*/
|
||||
auto trueBranch = node->GetChild(0);
|
||||
auto falseBranch = node->GetChild(1);
|
||||
|
||||
// Compare result and jump
|
||||
m_assembly << " pop eax\n"
|
||||
<< " cmp eax, 0\n"
|
||||
<< " je " << labelFalse << "\n";
|
||||
m_assembly << " pop r0\n"
|
||||
<< " skipz r0\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--;
|
||||
}
|
||||
|
||||
|
|
@ -152,8 +106,27 @@ private:
|
|||
AddComment("Operator: " + std::to_string(static_cast<int>(opNode->GetOperationType())));
|
||||
m_depth++;
|
||||
|
||||
// Generate code for variables
|
||||
for (const auto& [port, inputNode] : node->dataInputs) {
|
||||
// Generate code for variables usage
|
||||
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";
|
||||
}
|
||||
|
||||
|
|
@ -161,87 +134,45 @@ private:
|
|||
// 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";
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " add r0, r1\n"
|
||||
<< " push r0\n";
|
||||
break;
|
||||
case OperatorNode::OperationType::SUBTRACT:
|
||||
m_assembly << " pop ebx\n"
|
||||
<< " pop eax\n"
|
||||
<< " sub eax, ebx\n"
|
||||
<< " push eax\n";
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " sub r0, r1\n"
|
||||
<< " push r0\n";
|
||||
break;
|
||||
case OperatorNode::OperationType::MULTIPLY:
|
||||
m_assembly << " pop ebx\n"
|
||||
<< " pop eax\n"
|
||||
<< " imul eax, ebx\n"
|
||||
<< " push eax\n";
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " mul r0, r1\n"
|
||||
<< " push r0\n";
|
||||
break;
|
||||
case OperatorNode::OperationType::DIVIDE:
|
||||
m_assembly << " pop ebx\n"
|
||||
<< " pop eax\n"
|
||||
<< " cdq\n"
|
||||
<< " idiv ebx\n"
|
||||
<< " push eax\n";
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " div r0, r1\n"
|
||||
<< " push r0\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";
|
||||
case OperatorNode::OperationType::AND:
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " and r0, r1\n"
|
||||
<< " push r0\n";
|
||||
break;
|
||||
case OperationType::SUBTRACT:
|
||||
ss << " pop ebx\n"
|
||||
<< " pop eax\n"
|
||||
<< " sub eax, ebx\n"
|
||||
<< " push eax\n";
|
||||
case OperatorNode::OperationType::GREATER_THAN:
|
||||
m_assembly << " pop r0\n"
|
||||
<< " pop r1\n"
|
||||
<< " gt r0, r0, r1\n"
|
||||
<< " push r0\n";
|
||||
break;
|
||||
case OperationType::MULTIPLY:
|
||||
ss << " pop ebx\n"
|
||||
<< " pop eax\n"
|
||||
<< " imul eax, ebx\n"
|
||||
<< " push eax\n";
|
||||
default:
|
||||
// Make voluntary bad assembly
|
||||
m_assembly << "------>>>> OPERATOR NOT IMPLEMENTED: " << opNode->GetOperatorSymbol() << "\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--;
|
||||
|
|
@ -253,23 +184,44 @@ private:
|
|||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
auto* varNode = node->GetAs<VariableNode>();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
public:
|
||||
|
|
@ -194,6 +188,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Build execution paths
|
||||
BuildExecutionPath(topologicalOrder, nodeMap);
|
||||
|
||||
return topologicalOrder;
|
||||
|
||||
}
|
||||
|
|
@ -202,7 +199,32 @@ private:
|
|||
const std::vector<std::shared_ptr<BaseNode>>& m_nodes;
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ protected:
|
|||
|
||||
}
|
||||
|
||||
virtual void GenerateVariable(const std::shared_ptr<Variable> v) {
|
||||
|
||||
}
|
||||
|
||||
virtual void GenerateExit() {
|
||||
|
||||
|
|
|
|||
|
|
@ -19,44 +19,6 @@ BaseNode::~BaseNode()
|
|||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,14 +44,6 @@ public:
|
|||
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
|
||||
{
|
||||
|
|
@ -123,8 +115,6 @@ public:
|
|||
void SetInternalData(const nlohmann::json &j);
|
||||
nlohmann::json GetInternalData() const;
|
||||
|
||||
static std::string GenerateRandomString(size_t length, uint32_t flags = RandomFlags::ALL_CHARSETS);
|
||||
|
||||
void ClearPorts() {
|
||||
m_inputPorts.clear();
|
||||
m_outputPorts.clear();
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ public:
|
|||
virtual void Initialize() override;
|
||||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||
|
||||
virtual std::string GenerateAssembly() const { return ""; }
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,15 @@
|
|||
#include "story_project.h"
|
||||
#include "connection.h"
|
||||
#include "sys_lib.h"
|
||||
|
||||
#include "variable.h"
|
||||
|
||||
PrintNode::PrintNode(const std::string &type)
|
||||
: 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<Variable>(m_label);
|
||||
v->SetTextValue("");
|
||||
m_label = v->GetLabel();
|
||||
m_variables[m_label] = v;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,20 +17,18 @@ public:
|
|||
virtual void Initialize() override;
|
||||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||
|
||||
virtual std::string GenerateAssembly() const { return ""; }
|
||||
|
||||
void StoreInternalData();
|
||||
|
||||
void SetVariableUuid(const std::string &uuid) {
|
||||
m_variableUuid = uuid;
|
||||
void SetVariable(const std::shared_ptr<Variable> v) {
|
||||
m_variable = v;
|
||||
}
|
||||
|
||||
std::string GetVariableUuid() const {
|
||||
return m_variableUuid;
|
||||
std::shared_ptr<Variable> GetVariable() const {
|
||||
return m_variable;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_variableUuid;
|
||||
std::shared_ptr<Variable> m_variable;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -84,16 +84,16 @@ TEST_CASE( "Check various indentations and typos" ) {
|
|||
variables.push_back(var4);
|
||||
|
||||
auto variableNodeX = std::make_shared<VariableNode>("variable-node");
|
||||
variableNodeX->SetVariableUuid(var1->GetUuid());
|
||||
variableNodeX->SetVariable(var1);
|
||||
|
||||
auto variableNodeY = std::make_shared<VariableNode>("variable-node");
|
||||
variableNodeY->SetVariableUuid(var2->GetUuid());
|
||||
variableNodeY->SetVariable(var2);
|
||||
|
||||
auto variableNodeA = std::make_shared<VariableNode>("variable-node");
|
||||
variableNodeA->SetVariableUuid(var3->GetUuid());
|
||||
variableNodeA->SetVariable(var3);
|
||||
|
||||
auto variableNodeB = std::make_shared<VariableNode>("variable-node");
|
||||
variableNodeB->SetVariableUuid(var4->GetUuid());
|
||||
variableNodeB->SetVariable(var4);
|
||||
|
||||
auto testNode = std::make_shared<OperatorNode>();
|
||||
testNode->SetOperationType(OperatorNode::OperationType::GREATER_THAN);
|
||||
|
|
@ -227,25 +227,24 @@ TEST_CASE( "Check various indentations and typos" ) {
|
|||
|
||||
|
||||
ASTBuilder builder(nodes, connections);
|
||||
auto pathTrees = builder.BuildAST();
|
||||
auto pathTree = builder.BuildAST();
|
||||
|
||||
// Generate flow in the console
|
||||
VisualFlowGenerator flowGenerator(context);
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Chip32::Machine machine;
|
||||
Chip32::Machine machine;
|
||||
|
||||
// machine.QuickExecute(compiler.GetCode());
|
||||
machine.QuickExecute(assembly);
|
||||
|
||||
// REQUIRE( parseResult == true );
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue