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",
|
"name": "Black Magic Probe",
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,19 @@ public:
|
||||||
|
|
||||||
Error GetLastError() { return m_lastError; }
|
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:
|
private:
|
||||||
bool CompileMnemonicArguments(Instr &instr);
|
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.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,45 @@ 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)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,24 @@ public:
|
||||||
float y;
|
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);
|
BaseNode(const std::string &type, const std::string &typeName);
|
||||||
virtual ~BaseNode();
|
virtual ~BaseNode();
|
||||||
|
|
||||||
|
|
@ -28,12 +46,19 @@ public:
|
||||||
virtual std::string Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns) = 0;
|
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(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);
|
void SetPosition(float x, float y);
|
||||||
|
|
||||||
// make this virtual so that graphical node override the behavior
|
// make this virtual so that graphical node override the behavior
|
||||||
virtual float GetX() const;
|
virtual float GetX() const;
|
||||||
virtual float GetY() const;
|
virtual float GetY() const;
|
||||||
|
|
||||||
|
std::string GetMyEntryLabel() const {
|
||||||
|
return GetEntryLabel(m_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
// Coded type, internal use
|
// Coded type, internal use
|
||||||
std::string GetType() const
|
std::string GetType() const
|
||||||
{
|
{
|
||||||
|
|
@ -59,6 +84,7 @@ 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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_title{"Default title"};
|
std::string m_title{"Default title"};
|
||||||
|
|
|
||||||
|
|
@ -56,11 +56,11 @@ public:
|
||||||
for (auto& node : nodes) {
|
for (auto& node : nodes) {
|
||||||
auto astNode = std::make_shared<AstNode>();
|
auto astNode = std::make_shared<AstNode>();
|
||||||
|
|
||||||
astNode->position = {0, 0};
|
astNode->position = {x, y};
|
||||||
x += 10; // Espacement horizontal
|
x += 1; // Espacement horizontal
|
||||||
if (x > 50) { // Nouvelle ligne
|
if (x > 20) { // Nouvelle ligne
|
||||||
x = 0;
|
x = 0;
|
||||||
y += 5; // Espacement vertical
|
y += 1; // Espacement vertical
|
||||||
}
|
}
|
||||||
|
|
||||||
astNode->node = node;
|
astNode->node = node;
|
||||||
|
|
@ -75,74 +75,173 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestion des conditions et des corps de boucles/branches
|
// Gestion des conditions et des corps de boucles/branches
|
||||||
/*
|
for (auto& node : nodes) {
|
||||||
for(auto& node : nodes) {
|
std::string nodeType = node->GetTypeName();
|
||||||
if (node.type == Node::Type::LOOP || node.type == Node::Type::BRANCH){
|
if (nodeType == "LOOP" || nodeType == "BRANCH") {
|
||||||
for (auto& connection : connections) {
|
for (auto& connection : connections) {
|
||||||
if (connection.inNodeId == node.id && connection.inPortIndex == 0) { // Condition
|
if (connection->inNodeId == node->GetId()) {
|
||||||
node.condition = nodeMap[connection.outNodeId];
|
if (connection->inPortIndex == 0) { // Condition
|
||||||
}
|
m_ast.nodeMap[node->GetId()]->condition = m_ast.nodeMap[connection->outNodeId];
|
||||||
if (connection.inNodeId == node.id && connection.inPortIndex == 1) { // Body
|
} else if (connection->inPortIndex == 1) { // Body
|
||||||
node.body.push_back(nodeMap[connection.outNodeId]);
|
m_ast.nodeMap[node->GetId()]->body.push_back(m_ast.nodeMap[connection->outNodeId]);
|
||||||
}
|
} else if (nodeType == "BRANCH" && connection->inPortIndex == 2) { // ElseBody
|
||||||
if (node.type == Node::Type::BRANCH && connection.inNodeId == node.id && connection.inPortIndex == 2) { // ElseBody
|
// if (m_ast.nodeMap[node->GetId()]->elseBody == nullptr) {
|
||||||
if(node.elseBody == nullptr) {
|
// auto dummyNode = std::make_shared<BaseNode>("DummyNode");
|
||||||
node.elseBody = new Node(Node::Type::VARIABLE, "dummy"); // Créer un noeud dummy juste pour l'elsebody.
|
// auto dummyAstNode = std::make_shared<AstNode>();
|
||||||
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
// dummyAstNode->node = dummyNode;
|
||||||
} else {
|
// m_ast.nodeMap[node->GetId()]->elseBody = dummyAstNode;
|
||||||
node.elseBody->body.push_back(nodeMap[connection.outNodeId]);
|
// }
|
||||||
|
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() {
|
void displayNodeSchema() {
|
||||||
|
// Définir une taille fixe pour la grille
|
||||||
// Afficher les nœuds
|
const int gridWidth = 20; // 20 cases de large
|
||||||
for (auto& astNode : m_ast.nodeMap) {
|
int gridHeight = 0;
|
||||||
auto pos = astNode.second->position;
|
|
||||||
std::cout << "\033[" << pos.second + 1 << ";" << pos.first + 1 << "H"; // Déplacer le curseur
|
// Calculer la hauteur nécessaire pour la grille
|
||||||
std::cout << "[" << astNode.second->node->GetTypeName() << "]";
|
for (const auto& astNode : m_ast.nodeMap) {
|
||||||
|
gridHeight = std::max(gridHeight, astNode.second->position.second + 1);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// Afficher les connexions
|
// Créer une grille pour la console
|
||||||
for (auto& connection : connections) {
|
std::vector<std::vector<std::string>> grid(gridHeight, std::vector<std::string>(gridWidth, " "));
|
||||||
auto outPos = nodePositions[connection.outNodeId];
|
|
||||||
auto inPos = nodePositions[connection.inNodeId];
|
// Placer les nœuds dans la grille
|
||||||
|
for (const auto& astNode : m_ast.nodeMap) {
|
||||||
// Dessiner une ligne entre les nœuds (simplifié)
|
auto pos = astNode.second->position;
|
||||||
int startX = outPos.first + 10;
|
std::string nodeName = astNode.second->node->GetTypeName();
|
||||||
int startY = outPos.second + 1;
|
|
||||||
int endX = inPos.first;
|
// Tronquer le nom du nœud à 3 caractères
|
||||||
int endY = inPos.second + 1;
|
if (nodeName.length() > 3) {
|
||||||
|
nodeName = nodeName.substr(0, 3);
|
||||||
if (startY == endY) { // Ligne horizontale
|
} else {
|
||||||
for (int i = startX; i < endX; ++i) {
|
// Ajouter des espaces pour centrer le nom dans la case
|
||||||
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
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;
|
||||||
|
|
||||||
|
// 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) {
|
// Ligne verticale
|
||||||
std::cout << "\033[" << startY << ";" << i + 1 << "H-";
|
for (int i = std::min(startY, endY); i <= std::max(startY, endY); ++i) {
|
||||||
}
|
if (i < gridHeight) {
|
||||||
for (int i = std::min(startY, endY); i < std::max(startY, endY); ++i) {
|
grid[i][endX][0] = '|'; // Dessiner la ligne dans la première position de la case
|
||||||
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>";
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\033[" << 100 << ";" << 1 << "H"; // Déplacer le curseur en bas
|
// 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:
|
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)
|
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 PrintNode::GenerateConstants(IStoryPage &page, IStoryProject &project, int nb_out_conns)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::stringstream ss;
|
||||||
|
ss << "$" << m_label << " DC8, " << m_text << "\n";
|
||||||
|
return ss.str();
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
std::string PrintNode::Build(IStoryPage &page, const StoryOptions &options, int nb_out_conns)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PrintNode::GenerateConstants() const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
ss << "$" << m_label << " DC8, \"" << m_text << "\"\n";
|
||||||
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);
|
|
||||||
}
|
|
||||||
return ss.str();
|
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 <string>
|
||||||
#include "i_story_manager.h"
|
#include "i_story_manager.h"
|
||||||
#include "base_node.h"
|
#include "execution_node.h"
|
||||||
#include "i_script_node.h"
|
#include "i_script_node.h"
|
||||||
#include "i_story_project.h"
|
#include "i_story_project.h"
|
||||||
|
|
||||||
class PrintNode : public BaseNode
|
class PrintNode : public ExecutionNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrintNode(const std::string &type);
|
PrintNode(const std::string &type);
|
||||||
|
|
||||||
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 GenerateConstants(IStoryPage &page, IStoryProject &project, 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:
|
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}
|
add_executable(${PROJECT_NAME}
|
||||||
main.cpp
|
main.cpp
|
||||||
test_ast.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_assembler.cpp
|
||||||
../../chip32/chip32_vm.c
|
../../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 "branch_node.h"
|
||||||
#include "print_node.h"
|
#include "print_node.h"
|
||||||
#include "variable_node.h"
|
#include "variable_node.h"
|
||||||
|
#include "chip32_machine.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -41,19 +42,22 @@ TEST_CASE( "Check various indentations and typos" ) {
|
||||||
|
|
||||||
Compiler compiler;
|
Compiler compiler;
|
||||||
|
|
||||||
auto printNode = std::make_shared<PrintNode>();
|
auto printNode = std::make_shared<PrintNode>("print-node");
|
||||||
auto branchNode = std::make_shared<BranchNode>();
|
|
||||||
|
printNode->SetText("Hello from OST");
|
||||||
|
|
||||||
|
// auto branchNode = std::make_shared<BranchNode>("branch-node");
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<BaseNode>> nodes;
|
std::vector<std::shared_ptr<BaseNode>> nodes;
|
||||||
|
|
||||||
nodes.push_back(printNode);
|
nodes.push_back(printNode);
|
||||||
nodes.push_back(branchNode);
|
// nodes.push_back(branchNode);
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Connection>> connections;
|
std::vector<std::shared_ptr<Connection>> connections;
|
||||||
|
|
||||||
auto cn1 = std::make_shared<Connection>();
|
auto cn1 = std::make_shared<Connection>();
|
||||||
cn1->
|
|
||||||
|
|
||||||
// // Création des nœuds
|
// // Création des nœuds
|
||||||
// std::vector<Node> nodes = {
|
// std::vector<Node> nodes = {
|
||||||
|
|
@ -74,10 +78,18 @@ TEST_CASE( "Check various indentations and typos" ) {
|
||||||
|
|
||||||
|
|
||||||
// Construction de l'AST
|
// 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