mirror of
https://github.com/arabine/open-story-teller.git
synced 2025-12-06 17:09:06 +01:00
Add main entry point, fix some bugs, continue AST compilation
This commit is contained in:
parent
af859d7085
commit
b9a946eab4
15 changed files with 598 additions and 90 deletions
28
.vscode/launch.json
vendored
28
.vscode/launch.json
vendored
|
|
@ -95,6 +95,34 @@
|
|||
}
|
||||
]
|
||||
|
||||
},
|
||||
{
|
||||
"name": "Debug Compiler AST Tests",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/core/story-manager/tests/build/compiler_test", // Remplacez par le chemin de votre exécutable
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/core/story-manager/tests/build",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"linux": {
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb"
|
||||
},
|
||||
"osx": {
|
||||
"MIMode": "lldb",
|
||||
"miDebuggerPath": "/Users/user936511/.vscode/extensions/ms-vscode.cpptools-1.18.5-darwin-arm64/debugAdapters/lldb-mi/bin/lldb-mi"
|
||||
},
|
||||
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
|
||||
},
|
||||
{
|
||||
"name": "Black Magic Probe",
|
||||
|
|
|
|||
|
|
@ -119,6 +119,19 @@ public:
|
|||
|
||||
Error GetLastError() { return m_lastError; }
|
||||
|
||||
bool GetMain(Instr &instr) const {
|
||||
|
||||
// Find the main label
|
||||
bool success = m_labels.count(".main") == 1;
|
||||
|
||||
if (success)
|
||||
{
|
||||
instr = m_labels.at(".main");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private:
|
||||
bool CompileMnemonicArguments(Instr &instr);
|
||||
|
||||
|
|
|
|||
137
core/chip32/chip32_machine.h
Normal file
137
core/chip32/chip32_machine.h
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "chip32_assembler.h"
|
||||
#include "chip32_macros.h"
|
||||
|
||||
namespace Chip32
|
||||
{
|
||||
|
||||
class Machine
|
||||
{
|
||||
public:
|
||||
bool parseResult{false};
|
||||
bool buildResult{false};
|
||||
chip32_result_t runResult{VM_OK};
|
||||
|
||||
static int get_from_memory(chip32_ctx_t *ctx, uint32_t addr, char *text)
|
||||
{
|
||||
int valid = 0;
|
||||
|
||||
// Test if address is valid
|
||||
|
||||
bool isRam = addr & 0x80000000;
|
||||
addr &= 0xFFFF; // mask the RAM/ROM bit, ensure 16-bit addressing
|
||||
if (isRam) {
|
||||
strcpy(&text[0], (const char *)&ctx->ram.mem[addr]);
|
||||
} else {
|
||||
strcpy(&text[0], (const char *)&ctx->rom.mem[addr]);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t story_player_syscall(chip32_ctx_t *ctx, uint8_t code)
|
||||
{
|
||||
uint8_t retCode = SYSCALL_RET_OK;
|
||||
char working_buf[100] = {0};
|
||||
|
||||
// Printf
|
||||
if (code == 4)
|
||||
{
|
||||
// In R0: string with escaped characters
|
||||
// R1: Number of arguments
|
||||
// R2, R3 ... arguments
|
||||
|
||||
// Integers: stored in registers by values
|
||||
// Strings: first character address in register
|
||||
|
||||
get_from_memory(ctx, ctx->registers[R0], working_buf);
|
||||
int arg_count = ctx->registers[R1];
|
||||
|
||||
switch(arg_count){
|
||||
case 0:
|
||||
puts(working_buf);
|
||||
break;
|
||||
case 1:
|
||||
printf(working_buf, ctx->registers[R2]);
|
||||
puts("");
|
||||
break;
|
||||
case 2:
|
||||
printf(working_buf, ctx->registers[R2], ctx->registers[R3]);
|
||||
puts("");
|
||||
break;
|
||||
case 3:
|
||||
printf(working_buf, ctx->registers[R2], ctx->registers[R3], ctx->registers[R4]);
|
||||
puts("");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
// WAIT (sleep)
|
||||
else if (code == 5)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ctx->registers[R0]));
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QuickExecute(const std::string &assemblyCode)
|
||||
{
|
||||
std::vector<uint8_t> program;
|
||||
Chip32::Assembler assembler;
|
||||
Chip32::Result result;
|
||||
uint8_t data[8*1024];
|
||||
|
||||
parseResult = assembler.Parse(assemblyCode);
|
||||
|
||||
std::cout << assembler.GetLastError().ToString() << std::endl;
|
||||
|
||||
|
||||
buildResult = assembler.BuildBinary(program, result);
|
||||
result.Print();
|
||||
|
||||
chip32_ctx_t chip32_ctx;
|
||||
|
||||
chip32_ctx.stack_size = 512;
|
||||
|
||||
chip32_ctx.rom.mem = program.data();
|
||||
chip32_ctx.rom.addr = 0;
|
||||
chip32_ctx.rom.size = program.size();
|
||||
|
||||
chip32_ctx.ram.mem = data;
|
||||
chip32_ctx.ram.addr = 40 *1024;
|
||||
chip32_ctx.ram.size = sizeof(data);
|
||||
|
||||
chip32_ctx.syscall = story_player_syscall;
|
||||
|
||||
chip32_initialize(&chip32_ctx);
|
||||
|
||||
Instr mainLine;
|
||||
if (assembler.GetMain(mainLine))
|
||||
{
|
||||
// set pointer counter to the main line
|
||||
chip32_ctx.registers[PC] = mainLine.addr;
|
||||
}
|
||||
|
||||
runResult = chip32_run(&chip32_ctx);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace Chip32
|
||||
|
|
@ -22,6 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,45 @@ 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)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,24 @@ public:
|
|||
float y;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789"
|
||||
"!@#$%^&*()_+-=[]{}|;:,.<>?";
|
||||
*/
|
||||
|
||||
enum RandomFlags
|
||||
{
|
||||
CHARSET_ALPHABET_LOWER = 0x1,
|
||||
CHARSET_ALPHABET_UPPER = 0x2,
|
||||
CHARSET_NUMBERS = 0x4,
|
||||
CHARSET_SIGNS = 0x8,
|
||||
ALL_CHARSETS = CHARSET_ALPHABET_LOWER | CHARSET_ALPHABET_UPPER |CHARSET_NUMBERS | CHARSET_SIGNS
|
||||
};
|
||||
|
||||
BaseNode(const std::string &type, const std::string &typeName);
|
||||
virtual ~BaseNode();
|
||||
|
||||
|
|
@ -28,12 +46,19 @@ public:
|
|||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) = 0;
|
||||
virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) = 0;
|
||||
|
||||
virtual std::string GenerateConstants() const { return ""; }
|
||||
virtual std::string GenerateAssembly() const = 0;
|
||||
|
||||
void SetPosition(float x, float y);
|
||||
|
||||
// make this virtual so that graphical node override the behavior
|
||||
virtual float GetX() const;
|
||||
virtual float GetY() const;
|
||||
|
||||
std::string GetMyEntryLabel() const {
|
||||
return GetEntryLabel(m_uuid);
|
||||
}
|
||||
|
||||
// Coded type, internal use
|
||||
std::string GetType() const
|
||||
{
|
||||
|
|
@ -59,6 +84,7 @@ public:
|
|||
void SetInternalData(const nlohmann::json &j);
|
||||
nlohmann::json GetInternalData() const;
|
||||
|
||||
static std::string GenerateRandomString(size_t length, uint32_t flags = RandomFlags::ALL_CHARSETS);
|
||||
|
||||
private:
|
||||
std::string m_title{"Default title"};
|
||||
|
|
|
|||
|
|
@ -56,11 +56,11 @@ public:
|
|||
for (auto& node : nodes) {
|
||||
auto astNode = std::make_shared<AstNode>();
|
||||
|
||||
astNode->position = {0, 0};
|
||||
x += 10; // Espacement horizontal
|
||||
if (x > 50) { // Nouvelle ligne
|
||||
astNode->position = {x, y};
|
||||
x += 1; // Espacement horizontal
|
||||
if (x > 20) { // Nouvelle ligne
|
||||
x = 0;
|
||||
y += 5; // Espacement vertical
|
||||
y += 1; // Espacement vertical
|
||||
}
|
||||
|
||||
astNode->node = node;
|
||||
|
|
@ -75,74 +75,173 @@ public:
|
|||
}
|
||||
|
||||
// Gestion des conditions et des corps de boucles/branches
|
||||
/*
|
||||
for(auto& node : nodes) {
|
||||
if (node.type == Node::Type::LOOP || node.type == Node::Type::BRANCH){
|
||||
for (auto& node : nodes) {
|
||||
std::string nodeType = node->GetTypeName();
|
||||
if (nodeType == "LOOP" || nodeType == "BRANCH") {
|
||||
for (auto& connection : connections) {
|
||||
if (connection.inNodeId == node.id && connection.inPortIndex == 0) { // Condition
|
||||
node.condition = nodeMap[connection.outNodeId];
|
||||
}
|
||||
if (connection.inNodeId == node.id && connection.inPortIndex == 1) { // Body
|
||||
node.body.push_back(nodeMap[connection.outNodeId]);
|
||||
}
|
||||
if (node.type == Node::Type::BRANCH && connection.inNodeId == node.id && connection.inPortIndex == 2) { // ElseBody
|
||||
if(node.elseBody == nullptr) {
|
||||
node.elseBody = new Node(Node::Type::VARIABLE, "dummy"); // Créer un noeud dummy juste pour l'elsebody.
|
||||
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
||||
} else {
|
||||
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
||||
if (connection->inNodeId == node->GetId()) {
|
||||
if (connection->inPortIndex == 0) { // Condition
|
||||
m_ast.nodeMap[node->GetId()]->condition = m_ast.nodeMap[connection->outNodeId];
|
||||
} else if (connection->inPortIndex == 1) { // Body
|
||||
m_ast.nodeMap[node->GetId()]->body.push_back(m_ast.nodeMap[connection->outNodeId]);
|
||||
} else if (nodeType == "BRANCH" && connection->inPortIndex == 2) { // ElseBody
|
||||
// if (m_ast.nodeMap[node->GetId()]->elseBody == nullptr) {
|
||||
// auto dummyNode = std::make_shared<BaseNode>("DummyNode");
|
||||
// auto dummyAstNode = std::make_shared<AstNode>();
|
||||
// dummyAstNode->node = dummyNode;
|
||||
// m_ast.nodeMap[node->GetId()]->elseBody = dummyAstNode;
|
||||
// }
|
||||
m_ast.nodeMap[node->GetId()]->elseBody->body.push_back(m_ast.nodeMap[connection->outNodeId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Fonction pour afficher le schéma des nœuds
|
||||
void displayNodeSchema() {
|
||||
// Définir une taille fixe pour la grille
|
||||
const int gridWidth = 20; // 20 cases de large
|
||||
int gridHeight = 0;
|
||||
|
||||
// Afficher les nœuds
|
||||
for (auto& astNode : m_ast.nodeMap) {
|
||||
// Calculer la hauteur nécessaire pour la grille
|
||||
for (const auto& astNode : m_ast.nodeMap) {
|
||||
gridHeight = std::max(gridHeight, astNode.second->position.second + 1);
|
||||
}
|
||||
|
||||
// Créer une grille pour la console
|
||||
std::vector<std::vector<std::string>> grid(gridHeight, std::vector<std::string>(gridWidth, " "));
|
||||
|
||||
// Placer les nœuds dans la grille
|
||||
for (const auto& astNode : m_ast.nodeMap) {
|
||||
auto pos = astNode.second->position;
|
||||
std::cout << "\033[" << pos.second + 1 << ";" << pos.first + 1 << "H"; // Déplacer le curseur
|
||||
std::cout << "[" << astNode.second->node->GetTypeName() << "]";
|
||||
}
|
||||
/*
|
||||
// Afficher les connexions
|
||||
for (auto& connection : connections) {
|
||||
auto outPos = nodePositions[connection.outNodeId];
|
||||
auto inPos = nodePositions[connection.inNodeId];
|
||||
std::string nodeName = astNode.second->node->GetTypeName();
|
||||
|
||||
// Dessiner une ligne entre les nœuds (simplifié)
|
||||
int startX = outPos.first + 10;
|
||||
int startY = outPos.second + 1;
|
||||
// Tronquer le nom du nœud à 3 caractères
|
||||
if (nodeName.length() > 3) {
|
||||
nodeName = nodeName.substr(0, 3);
|
||||
} else {
|
||||
// Ajouter des espaces pour centrer le nom dans la case
|
||||
nodeName.insert(nodeName.end(), 3 - nodeName.length(), ' ');
|
||||
}
|
||||
|
||||
// Placer le nom du nœud dans la grille
|
||||
grid[pos.second][pos.first] = nodeName;
|
||||
}
|
||||
|
||||
// Dessiner les connexions
|
||||
for (const auto& astNode : m_ast.nodeMap) {
|
||||
for (const auto& input : astNode.second->inputs) {
|
||||
auto outPos = input->position;
|
||||
auto inPos = astNode.second->position;
|
||||
|
||||
// Dessiner une ligne entre les nœuds
|
||||
int startX = outPos.first + 1; // Commencer après le nom du nœud
|
||||
int startY = outPos.second;
|
||||
int endX = inPos.first;
|
||||
int endY = inPos.second + 1;
|
||||
int endY = inPos.second;
|
||||
|
||||
if (startY == endY) { // Ligne horizontale
|
||||
for (int i = startX; i < endX; ++i) {
|
||||
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
||||
// Ligne horizontale
|
||||
for (int i = startX; i <= endX; ++i) {
|
||||
if (i < gridWidth) {
|
||||
grid[startY][i][0] = '-'; // Dessiner la ligne dans la première position de la case
|
||||
}
|
||||
} else { // Ligne verticale + horizontale
|
||||
for (int i = startX; i < startX + (endX - startX) / 2; ++i) {
|
||||
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
||||
}
|
||||
for (int i = std::min(startY, endY); i < std::max(startY, endY); ++i) {
|
||||
std::cout << "\033[" << i + 1 << ";" << startX + (endX - startX) / 2 + 1 << "H|";
|
||||
}
|
||||
for (int i = startX + (endX - startX) / 2 + 1; i < endX; ++i) {
|
||||
std::cout << "\033[" << endY << ";" << i + 1 << "H-";
|
||||
}
|
||||
}
|
||||
std::cout << "\033[" << endY << ";" << endX << "H>";
|
||||
}
|
||||
|
||||
std::cout << "\033[" << 100 << ";" << 1 << "H"; // Déplacer le curseur en bas
|
||||
// Ligne verticale
|
||||
for (int i = std::min(startY, endY); i <= std::max(startY, endY); ++i) {
|
||||
if (i < gridHeight) {
|
||||
grid[i][endX][0] = '|'; // Dessiner la ligne dans la première position de la case
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// Afficher la grille avec des séparateurs verticaux
|
||||
for (const auto& row : grid) {
|
||||
for (size_t i = 0; i < row.size(); ++i) {
|
||||
std::cout << row[i];
|
||||
if (i < row.size() - 1) {
|
||||
std::cout << "|"; // Séparateur vertical
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void generateAssembly() {
|
||||
std::string assemblyCode;
|
||||
std::map<std::string, std::string> labels;
|
||||
|
||||
// Generate all constants
|
||||
for (const auto& astNode : m_ast.nodeMap) {
|
||||
assemblyCode += astNode.second->node->GenerateConstants();
|
||||
}
|
||||
|
||||
// After the constants, the main entry point:
|
||||
assemblyCode += ".main:\n";
|
||||
|
||||
// Générer des labels uniques pour les nœuds
|
||||
for (const auto& nodePair : m_ast.nodeMap) {
|
||||
std::string label = m_ast.generateLabel(m_ast);
|
||||
labels[nodePair.first] = label;
|
||||
|
||||
// Générer du code pour chaque type de nœud
|
||||
std::string nodeType = nodePair.second->node->GetTypeName();
|
||||
if (nodeType == "LOOP") {
|
||||
// Générer du code pour une boucle
|
||||
assemblyCode += " ; Loop start\n";
|
||||
// Ajouter des instructions pour la condition de la boucle
|
||||
if (nodePair.second->condition) {
|
||||
assemblyCode += " cmp_eq r0, " + labels[nodePair.second->condition->node->GetId()] + ", 0\n";
|
||||
assemblyCode += " skipz r0\n";
|
||||
assemblyCode += " jump " + labels[nodePair.second->body.front()->node->GetId()] + "\n";
|
||||
}
|
||||
// Ajouter des instructions pour le corps de la boucle
|
||||
for (const auto& bodyNode : nodePair.second->body) {
|
||||
assemblyCode += " ; Loop body\n";
|
||||
// Ajouter des instructions pour chaque nœud du corps
|
||||
}
|
||||
assemblyCode += " jump " + label + "\n"; // Retour au début de la boucle
|
||||
} else if (nodeType == "BRANCH") {
|
||||
// Générer du code pour un branchement
|
||||
assemblyCode += " ; Branch start\n";
|
||||
// Ajouter des instructions pour la condition du branchement
|
||||
if (nodePair.second->condition) {
|
||||
assemblyCode += " cmp_eq r0, " + labels[nodePair.second->condition->node->GetId()] + ", 0\n";
|
||||
assemblyCode += " skipnz r0\n";
|
||||
assemblyCode += " jump " + labels[nodePair.second->body.front()->node->GetId()] + "\n";
|
||||
}
|
||||
// Ajouter des instructions pour le corps du branchement
|
||||
for (const auto& bodyNode : nodePair.second->body) {
|
||||
assemblyCode += " ; Branch body\n";
|
||||
// Ajouter des instructions pour chaque nœud du corps
|
||||
}
|
||||
// Ajouter des instructions pour le corps du else
|
||||
if (nodePair.second->elseBody) {
|
||||
assemblyCode += " ; Else body\n";
|
||||
// Ajouter des instructions pour chaque nœud du corps du else
|
||||
}
|
||||
} else {
|
||||
// Générer du code pour d'autres types de nœuds
|
||||
assemblyCode += " ; Other node type: " + nodeType + "\n";
|
||||
assemblyCode += nodePair.second->node->GenerateAssembly();
|
||||
|
||||
// Ajouter des instructions spécifiques au type de nœud
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter le code assembleur généré à l'AST
|
||||
m_ast.assemblyCode = assemblyCode;
|
||||
}
|
||||
|
||||
std::string GetCode() const {
|
||||
return m_ast.assemblyCode;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
36
core/story-manager/src/execution_node.h
Normal file
36
core/story-manager/src/execution_node.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "base_node.h"
|
||||
|
||||
class ExecutionNode : public BaseNode
|
||||
{
|
||||
public:
|
||||
ExecutionNode(const std::string &type, const std::string &typeName)
|
||||
: BaseNode(type, typeName) {}
|
||||
|
||||
void Initialize() override {
|
||||
// Initialisation spécifique pour ExecutionNode
|
||||
}
|
||||
|
||||
std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override {
|
||||
return GetMyEntryLabel() + ":\n";
|
||||
}
|
||||
|
||||
std::string GenerateAssembly() const override {
|
||||
return GetMyEntryLabel() + ":\n";
|
||||
}
|
||||
|
||||
std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override {
|
||||
// Génération des constantes pour ExecutionNode
|
||||
return "ExecutionNode Constants";
|
||||
}
|
||||
|
||||
// Ajoutez des méthodes spécifiques pour gérer les entrées et sorties d'exécution
|
||||
void AddExecutionInput() {
|
||||
// Logique pour ajouter une entrée d'exécution
|
||||
}
|
||||
|
||||
void AddExecutionOutput() {
|
||||
// Logique pour ajouter une sortie d'exécution
|
||||
}
|
||||
};
|
||||
31
core/story-manager/src/function_entry_node.h
Normal file
31
core/story-manager/src/function_entry_node.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "execution_node.h"
|
||||
|
||||
|
||||
class FunctionEntryNode : public ExecutionNode
|
||||
{
|
||||
public:
|
||||
FunctionEntryNode(const std::string &type, const std::string &typeName)
|
||||
: ExecutionNode(type, typeName) {}
|
||||
|
||||
void Initialize() override {
|
||||
// Initialisation spécifique pour FunctionEntryNode
|
||||
// Par exemple, préparer les entrées nécessaires pour la fonction
|
||||
}
|
||||
|
||||
std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override {
|
||||
// Logique de construction pour FunctionEntryNode
|
||||
return GetMyEntryLabel() + ":\n";
|
||||
}
|
||||
|
||||
std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override {
|
||||
// Génération des constantes pour FunctionEntryNode
|
||||
return "FunctionEntryNode Constants";
|
||||
}
|
||||
|
||||
// Ajoutez des méthodes spécifiques pour gérer l'entrée de la fonction
|
||||
void PrepareFunctionEntry() {
|
||||
// Logique pour préparer l'entrée de la fonction
|
||||
}
|
||||
};
|
||||
30
core/story-manager/src/function_exit_node.h
Normal file
30
core/story-manager/src/function_exit_node.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "execution_node.h"
|
||||
|
||||
class FunctionExitNode : public ExecutionNode
|
||||
{
|
||||
public:
|
||||
FunctionExitNode(const std::string &type, const std::string &typeName)
|
||||
: ExecutionNode(type, typeName) {}
|
||||
|
||||
void Initialize() override {
|
||||
// Initialisation spécifique pour FunctionExitNode
|
||||
// Par exemple, préparer les sorties nécessaires pour la fonction
|
||||
}
|
||||
|
||||
std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override {
|
||||
// Logique de construction pour FunctionExitNode
|
||||
return "FunctionExitNode Build";
|
||||
}
|
||||
|
||||
std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override {
|
||||
// Génération des constantes pour FunctionExitNode
|
||||
return "FunctionExitNode Constants";
|
||||
}
|
||||
|
||||
// Ajoutez des méthodes spécifiques pour gérer la sortie de la fonction
|
||||
void FinalizeFunctionExit() {
|
||||
// Logique pour finaliser la sortie de la fonction
|
||||
}
|
||||
};
|
||||
31
core/story-manager/src/operator_node.h
Normal file
31
core/story-manager/src/operator_node.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "base_node.h"
|
||||
|
||||
class OperatorNode : public BaseNode
|
||||
{
|
||||
public:
|
||||
OperatorNode(const std::string &type, const std::string &typeName)
|
||||
: BaseNode(type, typeName) {}
|
||||
|
||||
void Initialize() override {
|
||||
// Initialisation spécifique pour DataNode
|
||||
}
|
||||
|
||||
std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override {
|
||||
// Logique de construction pour DataNode
|
||||
return "DataNode Build";
|
||||
}
|
||||
|
||||
std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override {
|
||||
// Génération des constantes pour DataNode
|
||||
return "DataNode Constants";
|
||||
}
|
||||
|
||||
// Ajoutez des méthodes spécifiques pour gérer les données directement
|
||||
void ProcessData() {
|
||||
// Logique pour traiter les données directement
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
|
||||
PrintNode::PrintNode(const std::string &type)
|
||||
: BaseNode(type, "Print Node")
|
||||
: ExecutionNode(type, "Print Node")
|
||||
{
|
||||
|
||||
m_label = GenerateRandomString(10, BaseNode::CHARSET_ALPHABET_LOWER | BaseNode::CHARSET_ALPHABET_UPPER );// Should be enough to avoid collision?
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -19,35 +19,39 @@ void PrintNode::Initialize()
|
|||
|
||||
std::string PrintNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
|
||||
|
||||
return s;
|
||||
std::stringstream ss;
|
||||
ss << "$" << m_label << " DC8, " << m_text << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string PrintNode::GenerateConstants() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
std::list<std::shared_ptr<Connection>> conns;
|
||||
page.GetNodeConnections(conns, GetId());
|
||||
int i = 0;
|
||||
std::list<std::shared_ptr<Connection>>::iterator c = conns.begin();
|
||||
|
||||
if (conns.size() == 2)
|
||||
{
|
||||
ss << R"(; ---------------------------- )"
|
||||
<< GetTitle()
|
||||
<< " Type: Branch"
|
||||
<< "\n";
|
||||
|
||||
ss << "eq r0, r0, r1\n"
|
||||
<< "skipz r0\n"
|
||||
<< "jump " << BaseNode::GetEntryLabel((*c)->inNodeId);
|
||||
++c;
|
||||
ss << "jump " << BaseNode::GetEntryLabel((*c)->inNodeId);
|
||||
}
|
||||
ss << "$" << m_label << " DC8, \"" << m_text << "\"\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string PrintNode::GenerateAssembly() const
|
||||
{
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << ExecutionNode::GenerateAssembly()
|
||||
<< " push r0\n"
|
||||
<< " push r1\n"
|
||||
<< " lcons r0, $" << m_label << "\n"
|
||||
<< " lcons r1, 0 ; number of arguments\n" // FIXME: handle arguments
|
||||
<< " syscall 4\n"
|
||||
<< " pop r1\n"
|
||||
<< " pop r0\n";
|
||||
|
||||
// << ""mov r2, %2 // arguments are in r2, r3, r4 etc.
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,29 @@
|
|||
|
||||
#include <string>
|
||||
#include "i_story_manager.h"
|
||||
#include "base_node.h"
|
||||
#include "execution_node.h"
|
||||
#include "i_script_node.h"
|
||||
#include "i_story_project.h"
|
||||
|
||||
class PrintNode : public BaseNode
|
||||
class PrintNode : public ExecutionNode
|
||||
{
|
||||
public:
|
||||
PrintNode(const std::string &type);
|
||||
PrintNode(const std::string &type);
|
||||
|
||||
virtual void Initialize() override;
|
||||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) override;
|
||||
virtual std::string GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns) override;
|
||||
|
||||
virtual std::string GenerateConstants() const override;
|
||||
|
||||
std::string GenerateAssembly() const override;
|
||||
|
||||
void SetText(const std::string &text) {
|
||||
m_text = text;
|
||||
}
|
||||
private:
|
||||
std::string m_label;
|
||||
std::string m_text; // Text to print
|
||||
uint32_t m_arguments{0}; // number of arguments
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,20 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
test_ast.cpp
|
||||
../src/base_node.cpp
|
||||
../src/branch_node.cpp
|
||||
../src/print_node.cpp
|
||||
../src/variable_node.cpp
|
||||
../src/connection.cpp
|
||||
|
||||
../../chip32/chip32_assembler.cpp
|
||||
../../chip32/chip32_vm.c
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE ../../chip32)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
../../chip32
|
||||
../src
|
||||
../interfaces
|
||||
../lib
|
||||
../../../shared
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ THE SOFTWARE.
|
|||
#include "branch_node.h"
|
||||
#include "print_node.h"
|
||||
#include "variable_node.h"
|
||||
#include "chip32_machine.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
|
@ -41,19 +42,22 @@ TEST_CASE( "Check various indentations and typos" ) {
|
|||
|
||||
Compiler compiler;
|
||||
|
||||
auto printNode = std::make_shared<PrintNode>();
|
||||
auto branchNode = std::make_shared<BranchNode>();
|
||||
auto printNode = std::make_shared<PrintNode>("print-node");
|
||||
|
||||
printNode->SetText("Hello from OST");
|
||||
|
||||
// auto branchNode = std::make_shared<BranchNode>("branch-node");
|
||||
|
||||
|
||||
std::vector<std::shared_ptr<BaseNode>> nodes;
|
||||
|
||||
nodes.push_back(printNode);
|
||||
nodes.push_back(branchNode);
|
||||
// nodes.push_back(branchNode);
|
||||
|
||||
std::vector<std::shared_ptr<Connection>> connections;
|
||||
|
||||
auto cn1 = std::make_shared<Connection>();
|
||||
cn1->
|
||||
|
||||
|
||||
// // Création des nœuds
|
||||
// std::vector<Node> nodes = {
|
||||
|
|
@ -74,10 +78,18 @@ TEST_CASE( "Check various indentations and typos" ) {
|
|||
|
||||
|
||||
// Construction de l'AST
|
||||
AST ast = buildAST(nodes, connections);
|
||||
compiler.buildAST(nodes, connections);
|
||||
compiler.displayNodeSchema();
|
||||
|
||||
compiler.generateAssembly();
|
||||
|
||||
std::cout << compiler.GetCode() << std::endl;
|
||||
|
||||
|
||||
Chip32::Machine machine;
|
||||
|
||||
REQUIRE( parseResult == true );
|
||||
machine.QuickExecute(compiler.GetCode());
|
||||
|
||||
// REQUIRE( parseResult == true );
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue