12 |
13 | // STL
14 | // none
15 |
16 | // Qt
17 | //
18 |
19 | /** \file pconsole.h
20 | * \brief plik nagłówkowy klasy PConsole
21 | *
22 | * Plik nagłówkowy zawiera definicję klasy PConsole.
23 | */
24 |
25 | /** \brief Konsola wejścia/wyjścia
26 | *
27 | * Klasa realizująca wszystkie operacje wejścia wyjścia związane z instrukcjami Pieta.
28 | */
29 | class PConsole {
30 |
31 | private:
32 |
33 | /**
34 | * Pole logiczne definiujące tryb gadatliwy.
35 | */
36 | bool verbose;
37 |
38 | std::stringstream &stream;
39 |
40 | public:
41 |
42 | PConsole(std::stringstream &);
43 | ~PConsole();
44 |
45 | void setVerbosity(bool);
46 |
47 | void printChar(int);
48 | void printNumber(int);
49 | int readChar();
50 | int readNumber();
51 |
52 | };
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/gui/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Read more about configuring cmake with Qt at:
2 | # http://qt-project.org/quarterly/view/using_cmake_to_build_qt_projects
3 |
4 | INCLUDE(${QT_USE_FILE})
5 | ADD_DEFINITIONS(${QT_DEFINITIONS})
6 |
7 | INCLUDE_DIRECTORIES(
8 | ${CMAKE_SOURCE_DIR}/src/core
9 | ${CMAKE_CURRENT_BINARY_DIR}
10 | )
11 |
12 | SET(gui_SOURCES
13 | program_image_widget.cpp
14 | machine_widget.cpp
15 | child_window.cpp
16 | main_window.cpp
17 | main.cpp
18 | )
19 |
20 | SET(gui_HEADERS
21 | main_window.h
22 | child_window.h
23 | machine_widget.h
24 | program_image_widget.h
25 | )
26 |
27 | SET(gui_FORMS
28 | program_image_widget.ui
29 | machine_widget.ui
30 | main_window.ui
31 | )
32 |
33 | SET(gui_RESOURCES
34 | images.qrc
35 | )
36 |
37 | QT4_WRAP_CPP(gui_HEADERS_MOC ${gui_HEADERS})
38 | QT4_WRAP_UI(gui_FORMS_HEADERS ${gui_FORMS})
39 | QT4_ADD_RESOURCES(gui_RESOURCES_RCC ${gui_RESOURCES})
40 |
41 | ADD_EXECUTABLE(gui
42 | p_gui_virtual_machine.cpp # this is not a UI file (no moc generated)
43 | ${gui_SOURCES}
44 | ${gui_HEADERS_MOC}
45 | ${gui_FORMS_HEADERS}
46 | ${gui_RESOURCES_RCC}
47 | )
48 |
49 | TARGET_LINK_LIBRARIES(gui
50 | ${QT_LIBRARIES}
51 | PietCore
52 | )
53 |
--------------------------------------------------------------------------------
/src/gui/main_window.cpp:
--------------------------------------------------------------------------------
1 | #include "main_window.h"
2 | #include "ui_main_window.h"
3 |
4 | #include "child_window.h"
5 |
6 | MainWindow::MainWindow(QWidget *parent) :
7 | QMainWindow(parent),
8 | ui(new Ui::MainWindow)
9 | {
10 | ui->setupUi(this);
11 | }
12 |
13 | MainWindow::~MainWindow()
14 | {
15 | delete ui;
16 | }
17 |
18 | void MainWindow::displayAbout()
19 | {
20 | QMessageBox::about(this, tr("About Piet Esoteric Language Interpreter"),
21 | tr("Piet "
22 | "is a graphical programming language designed by "
23 | "David Morgan-Mar. "
24 | "Read more about Piet at "
25 | "author's page "
26 | "This non-commercial project is a Piet GUI interpreter designed by Tomasz Ducin. "
27 | "For more information visit "
28 | "github piet project.
"
29 | "© 2009-2013 Tomasz Ducin
"));
30 | }
31 |
32 | void MainWindow::openChildWindow()
33 | {
34 | ChildWindow *childWindow = new ChildWindow(ui->mdiArea);
35 | childWindow->setAttribute(Qt::WA_DeleteOnClose);
36 | childWindow->show();
37 | }
38 |
--------------------------------------------------------------------------------
/src/gui/machine_widget.h:
--------------------------------------------------------------------------------
1 | #ifndef MACHINE_WIDGET_H
2 | #define MACHINE_WIDGET_H
3 |
4 | #include
5 |
6 | #include
7 |
8 | #include "p_gui_virtual_machine.h"
9 | #include "program_image_widget.h"
10 |
11 | namespace Ui {
12 | class MachineWidget;
13 | }
14 |
15 | class MachineWidget : public QWidget
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit MachineWidget(QWidget *parent = 0);
21 | ~MachineWidget();
22 |
23 | void enableMachineInterface();
24 | void disableMachineInterface();
25 |
26 | signals:
27 | void fileChosen(QString);
28 |
29 | public slots:
30 | void chooseFile();
31 | void createMachine(QString);
32 |
33 | void toggleVerbosity(bool);
34 |
35 | void executeSingleInstruction();
36 | void executeAllInstructions();
37 |
38 | void startMachine();
39 | void restartMachine();
40 | void stopMachine();
41 |
42 | private:
43 | Ui::MachineWidget *ui;
44 | ProgramImageWidget *program_image;
45 |
46 | PGuiVirtualMachine *piet;
47 | std::stringstream *stream;
48 |
49 | bool machine_created;
50 |
51 | void clearCalcStack();
52 | void fillCalcStack();
53 | void updateState();
54 | void updateCodeCoordinates();
55 | void updateInformation();
56 | };
57 |
58 | #endif // MACHINE_WIDGET_H
59 |
--------------------------------------------------------------------------------
/src/gui/p_gui_virtual_machine.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_virtual_machine.h"
5 | #include "p_gui_virtual_machine.h"
6 |
7 | // piet core
8 | #include "../debug.h"
9 |
10 | // C++
11 | #include
12 |
13 | // STL
14 | // none
15 |
16 | // Qt
17 | #include
18 | #include
19 |
20 | /** \file pconsolevirtualmachine.cpp
21 | * \brief Plik z kodem źródłowym klasy PConsoleVirtualMachine
22 | *
23 | * Plik zawiera kod źródłowy klasy PConsoleVirtualMachine.
24 | */
25 |
26 | PGuiVirtualMachine::PGuiVirtualMachine(const char * filename, std::stringstream &str)
27 | : PVirtualMachine(filename, str)
28 | {
29 | std::cout << "GUI VM" << std::endl;
30 | }
31 |
32 | bool PGuiVirtualMachine::validateNumber(int value)
33 | {
34 | return true;
35 | }
36 |
37 | void PGuiVirtualMachine::readNumber()
38 | {
39 | std::cout << "GUI readNumber" << std::endl;
40 | int read;
41 | do {
42 | read = QInputDialog::getInteger(
43 | 0, "Piet input reading", "Enter a number:", 1);
44 | } while (!validateNumber(read));
45 | stack->instrPush(read);
46 | }
47 |
48 | bool PGuiVirtualMachine::validateChar(QString value)
49 | {
50 | return value.size() == 1;
51 | }
52 |
53 | void PGuiVirtualMachine::readChar()
54 | {
55 | std::cout << "GUI readNumber" << std::endl;
56 | QString read;
57 | do {
58 | read = QInputDialog::getText(
59 | 0, "Piet input reading", "Enter a character:");
60 | } while (!validateChar(read));
61 | stack->instrPush(read.toInt());
62 | }
63 |
--------------------------------------------------------------------------------
/src/gui/program_image_widget.cpp:
--------------------------------------------------------------------------------
1 | #include "program_image_widget.h"
2 | #include "ui_program_image_widget.h"
3 |
4 | #include "p_gui_virtual_machine.h"
5 |
6 | #include
7 | #include
8 |
9 | ProgramImageWidget::ProgramImageWidget(QWidget *parent) :
10 | QWidget(parent),
11 | ui(new Ui::ProgramImageWidget)
12 | {
13 | ui->setupUi(this);
14 | scene = new QGraphicsScene(this);
15 | ui->graphicsView->setScene(scene);
16 | zoom_scale = 0;
17 | image_created = false;
18 | }
19 |
20 | ProgramImageWidget::~ProgramImageWidget()
21 | {
22 | delete scene;
23 | delete ui;
24 | }
25 |
26 | void ProgramImageWidget::setPiet(PGuiVirtualMachine *piet)
27 | {
28 | this->piet = piet;
29 | image_created = true;
30 | render();
31 | }
32 |
33 | void ProgramImageWidget::render()
34 | {
35 | scene->clear();
36 | float zoom_size = getZoomSize();
37 | const QImage *original = piet->getImage();
38 | QImage scaled_image = original->scaled(QSize(original->width() * zoom_size, original->height() * zoom_size));
39 | QPixmap scaled_pixmap = QPixmap::fromImage(scaled_image);
40 | scene->addPixmap(scaled_pixmap);
41 | scene->setSceneRect(scene->itemsBoundingRect());
42 | }
43 |
44 | float ProgramImageWidget::getZoomSize()
45 | {
46 | return pow(2.0, zoom_scale);
47 | }
48 |
49 | void ProgramImageWidget::zoomIn()
50 | {
51 | if (image_created)
52 | {
53 | zoom_scale++;
54 | render();
55 | }
56 | }
57 |
58 | void ProgramImageWidget::zoomOut()
59 | {
60 | if (image_created)
61 | {
62 | zoom_scale--;
63 | render();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Piet
2 | ====
3 |
4 | [Piet](http://en.wikipedia.org/wiki/Piet_%28programming_language%29) is a graphical programming language designed by [David Morgan-Mar](http://en.wikipedia.org/wiki/David_Morgan-Mar). Read more about Piet at http://www.dangermouse.net/esoteric/piet.html.
5 |
6 | This project provides Piet interpreter lib which is additionally used inside a console and gui aplications.
7 |
8 | Compilation
9 | ===========
10 |
11 | The project uses [CMake](http://www.cmake.org/) for deployment process. You need to have installed version 2.8.2 or higher. Once cmake is installed, you may compile with following commands:
12 |
13 | mkdir build
14 | cd build
15 | cmake ..
16 | make
17 |
18 | and it will create all binary files (libs, console and gui application).
19 |
20 | Doxygen
21 | =======
22 |
23 | If you have doxygen documentation tool installed, cmake will additionally generate HTML documentation.
24 |
25 | Qt Creator
26 | ==========
27 |
28 | You may use the Qt Creator tool within the gui project (sources are located in src/gui). Open the project with the `gui.pro` file. But before you can compile the gui application in the Qt Creator, libpietcore.a library has to be compiled (which is done by cmake). Basically, compile entire project with cmake and after this you can use Qt Creator with no limits.
29 |
30 | Run
31 | ===
32 |
33 | Execute the `piet` binary file in command line with one parameter, specifying the program to execute:
34 |
35 | $ piet path_to_img_programs/2toN.png
36 |
37 | Travis continuous integration
38 | =============================
39 |
40 | Piet project code is integrated with travis, where it is compiled using Qt4 and cmake:
41 |
42 | [](https://travis-ci.org/ducin/piet)
43 |
--------------------------------------------------------------------------------
/src/core/p_color_manager.h:
--------------------------------------------------------------------------------
1 | #ifndef P_COLOR_MANAGER
2 | #define P_COLOR_MANAGER
3 |
4 | //// includes
5 |
6 | // piet core
7 | #include "p_enums.h"
8 | #include "p_structs.h"
9 |
10 | // C++
11 | // none
12 |
13 | // STL
14 | #include
15 |
16 | // Qt
17 | #include
18 |
19 | /** \file pcolormanager.h
20 | * \brief plik nagłówkowy klasy PColorManager
21 | *
22 | * Plik nagłówkowy zawiera definicję klasy PColorManager.
23 | */
24 |
25 | /** \brief Maszyna kodu
26 | *
27 | * Klasa odpowiedzialna za właściwe interpretowanie kolorów, determinowanie czy kolor jest standardowy, jeśli niestandardowy - przydziela go do odpowiedniego koloru standardowego wg odpowiedniego algorytmu.
28 | */
29 | class PColorManager {
30 |
31 | private:
32 |
33 | int lightnessCycleDifference(PStdColors, PStdColors);
34 | int saturationCycleDifference(PStdColors, PStdColors);
35 |
36 | /**
37 | * Pole logiczne definiujące tryb gadatliwy.
38 | */
39 | bool verbose;
40 |
41 | std::stringstream &stream;
42 |
43 | public:
44 |
45 | PColorManager(std::stringstream &);
46 | ~PColorManager();
47 |
48 | void setVerbosity(bool);
49 |
50 | int getInstructionIndex(QRgb, QRgb);
51 |
52 | QRgb /** kolor jasny czerwony */ LIGHT_RED, /** kolor czerwony */ NORMAL_RED, /** kolor ciemny czerwony */ DARK_RED;
53 | QRgb /** kolor jasny żółty */ LIGHT_YELLOW, /** kolor żółty */ NORMAL_YELLOW, /** kolor ciemny żółty */ DARK_YELLOW;
54 | QRgb /** kolor jasny zielony */ LIGHT_GREEN, /** kolor zielony */ NORMAL_GREEN, /** kolor ziemny zielony */ DARK_GREEN;
55 | QRgb /** kolor jasny błękitny */ LIGHT_CYAN, /** kolor błękitny */ NORMAL_CYAN, /** kolor ciemny błękitny */ DARK_CYAN;
56 | QRgb /** kolor jasny niebieski */ LIGHT_BLUE, /** kolor niebieski */ NORMAL_BLUE, /** kolor ciemny niebieski */ DARK_BLUE;
57 | QRgb /** kolor jasny magenta */ LIGHT_MAGENTA, /** kolor magenta */ NORMAL_MAGENTA, /** kolor ciemny magenta */ DARK_MAGENTA;
58 | QRgb /** kolor biały */ WHITE, /** kolor czarny */ BLACK;
59 |
60 | PStdColors getColorName(QRgb);
61 |
62 | void initColorValues();
63 |
64 | };
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/src/gui/program_image_widget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | ProgramImageWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 300
10 | 300
11 |
12 |
13 |
14 |
15 | 300
16 | 300
17 |
18 |
19 |
20 | Form
21 |
22 |
23 | -
24 |
25 |
26 | -
27 |
28 |
-
29 |
30 |
31 | Zoom In
32 |
33 |
34 |
35 | -
36 |
37 |
38 | Zoom Out
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | pushButtonZoomIn
50 | clicked()
51 | ProgramImageWidget
52 | zoomIn()
53 |
54 |
55 | 102
56 | 271
57 |
58 |
59 | 43
60 | 244
61 |
62 |
63 |
64 |
65 | pushButtonZoomOut
66 | clicked()
67 | ProgramImageWidget
68 | zoomOut()
69 |
70 |
71 | 179
72 | 271
73 |
74 |
75 | 241
76 | 244
77 |
78 |
79 |
80 |
81 |
82 | zoomIn()
83 | zoomOut()
84 |
85 |
86 |
--------------------------------------------------------------------------------
/src/core/p_console.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_console.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 |
11 | // C++
12 | #include
13 | #include
14 |
15 | // STL
16 | // none
17 |
18 | // Qt
19 | // none
20 |
21 | /** \file pconsole.cpp
22 | * \brief Plik z kodem źródłowym klasy PConsole
23 | *
24 | * Plik zawiera kod źródłowy klasy PConsole.
25 | */
26 |
27 | /**
28 | * Konstruktor konsoli wejścia/wyjścia. Nie robi nic szczególnego.
29 | */
30 | PConsole::PConsole(std::stringstream &str) : stream(str)
31 | {
32 | debug("CONSTRUCTOR ----- console START\n");
33 | verbose = false;
34 | debug("CONSTRUCTOR ----- console END\n");
35 | }
36 |
37 | /**
38 | * Destruktor konsoli wejścia/wyjścia. Nie robi nic szczególnego.
39 | */
40 | PConsole::~PConsole()
41 | {
42 | debug("DESTRUCTOR ----- console START\n");
43 |
44 | debug("DESTRUCTOR ----- console END\n");
45 | }
46 |
47 | /**
48 | * Ustala tryb gadatliwy.
49 | * @param verbosity tryb gadatliwy
50 | */
51 | void PConsole::setVerbosity(bool verbosity)
52 | {
53 | verbose = verbosity;
54 | }
55 |
56 | /**
57 | * Wyświetla liczbę na konsolę.
58 | * @param I liczba
59 | */
60 | void PConsole::printNumber(int I)
61 | {
62 | if (verbose)
63 | stream << "CONSOLE/out-number: ";
64 | stream << I;
65 | if (verbose)
66 | stream << std::endl;
67 | }
68 |
69 | /**
70 | * Wyświetla znak na konsolę.
71 | * @param I znak reprezentowany maszynowo przez liczbę
72 | */
73 | void PConsole::printChar(int I)
74 | {
75 | unsigned char UC = I;
76 | if (verbose)
77 | stream << "CONSOLE/out-char: ";
78 | // stream << std::setw(3) << UC;
79 | stream << UC;
80 | if (verbose)
81 | stream << " (" << I << ")" << std::endl;
82 | }
83 |
84 | /**
85 | * Wczytuje z konsoli liczbę.
86 | * @return wczytana liczba
87 | */
88 | int PConsole::readNumber()
89 | {
90 | int var;
91 | if (verbose) {
92 | stream << "CONSOLE/in-number: ";
93 | } else {
94 | stream << "? ";
95 | }
96 | std::cin >> var;
97 | return var;
98 | }
99 |
100 | /**
101 | * Wczytuje z konsoli znak.
102 | * @return wczytany znak reprezentowany maszynowo przez liczbę
103 | */
104 | int PConsole::readChar()
105 | {
106 | char C;
107 | if (verbose) {
108 | stream << "CONSOLE/in-char: ";
109 | } else {
110 | stream << "? ";
111 | }
112 | std::cin >> C;
113 | int I = (int) C;
114 | return I;
115 | }
116 |
--------------------------------------------------------------------------------
/src/core/p_calc_stack.h:
--------------------------------------------------------------------------------
1 | #ifndef P_CALC_STACK
2 | #define P_CALC_STACK
3 |
4 | //// includes
5 |
6 | // piet core
7 | #include "p_enums.h"
8 | #include "p_structs.h"
9 |
10 | // C++
11 | // none
12 |
13 | // STL
14 | #include // lista użyta celowo (a nie stos ), aby ułatwić wyświetlanie zawartości stosu
15 |
16 | // Qt
17 | // none
18 |
19 | /** \file pcalcstack.h
20 | * \brief plik nagłówkowy klasy PCalcStack
21 | *
22 | * Plik nagłówkowy zawiera definicję klasy PCalcStack.
23 | */
24 |
25 | /** \brief Stos
26 | *
27 | * Klasa pełniąca funkcję stosu wykorzystywanego do interpretowania kodu Pieta. Wszystkie jej funkcjonalności są dokładnie określone przez instrukcje dozwolone w języku Piet - począwszy od podstawowych (kładzenie/zdejmowanie elementów), poprzez arytmetyczne i logiczne (zmieniające elementy na szczycie stosu w zależności od ich wartości) a skończywszy na operacjach sterujących głowicą (przestawianie 'codel chooser' i 'direction pointer' - patrz: specyfikacja Piet), operacjach modyfikujących strukturę elementów stosu oraz operacjach I/O.
28 |
29 | Stanowi jeden z dwóch obiektów potrzebnych do pełnej interpretacji kodu, używanych przez tzw. "wirtualną maszynę Pieta", najwyższy w hierarchi obiekt.
30 | */
31 | class PCalcStack {
32 |
33 | private:
34 |
35 | /**
36 | * Pole logiczne definiujące tryb gadatliwy.
37 | */
38 | bool verbose;
39 |
40 | protected:
41 |
42 | /**
43 | * Struktura przechowująca wszystkie wartości stosu. Jest nią lista a nie stos - celowo - aby ułatwić implementację niektórych operacji: operacji Pieta ROLL. wyświetlanie wszystkich elementów stosu itd. Użycie zwykłego stosu skomplikowałoby zakodowanie tych metod bardzo znacznie - i niepotrzebnie.
44 | */
45 | std::list values;
46 |
47 | public:
48 |
49 | PCalcStack();
50 | ~PCalcStack();
51 |
52 | void setVerbosity(bool);
53 |
54 | void clear();
55 | void prepareToExecute();
56 |
57 | int size();
58 | std::list::iterator begin_iterator();
59 | std::list::iterator end_iterator();
60 | bool hasAtLeastNElements(unsigned int);
61 |
62 | // operacje podstawowe:
63 |
64 | void instrPush(int);
65 | int instrPop();
66 |
67 | // operacje arytmetyczne:
68 |
69 | void instrAdd();
70 | void instrSubtract();
71 | void instrMultiply();
72 | void instrDivide();
73 | void instrModulo();
74 |
75 | // operacje logiczne:
76 |
77 | void instrNot();
78 | void instrGreater();
79 |
80 | // operacje na strukturze elementów:
81 |
82 | void instrDuplicate();
83 | void instrRoll();
84 |
85 | };
86 |
87 | #endif
88 |
--------------------------------------------------------------------------------
/src/core/p_code_pointer.h:
--------------------------------------------------------------------------------
1 | #ifndef P_CODE_POINTER
2 | #define P_CODE_POINTER
3 |
4 | //// includes
5 |
6 | // piet core
7 | #include "p_enums.h"
8 | #include "p_structs.h"
9 |
10 | // C++
11 | // none
12 |
13 | // STL
14 | // none
15 |
16 | // Qt
17 | #include
18 | #include
19 |
20 | /** \file pcodepointer.h
21 | * \brief plik nagłówkowy klasy PCodePointer
22 | *
23 | * Plik nagłówkowy zawiera definicję klasy PCodePointer.
24 | */
25 |
26 | /** \brief Głowica obrazu kodu
27 | *
28 | * Klasa pełniąca funkcję głowicy która porusza się po tzw. "obrazie kodu". Wykonuje wszystkie operacje bezpośrednio związane z odczytywaniem piksli z obrazu, posiada (zmieniające się w trakcie działania programu) współrzędne oraz dodatkowe elementy, takie jak 'codel chooser' i 'direction pointer' (patrz: specyfikacja języka Piet).
29 |
30 | Obok managera kolorów i managera bloków koloru jest trzecim elementem wykorzystywanym przez tzw. "maszynę kodu" i (razem z nimi) służy do właściwej, jednoznacznej interpretacji kodu Pieta.
31 | */
32 | class PCodePointer {
33 |
34 | static const PCodelChooserValues INIT_cc = cc_left;
35 | static const PDirectionPointerValues INIT_dp = dp_right;
36 |
37 | private:
38 |
39 | PPoint initial_coords;
40 | PPoint coords; // współrzędne na które wskazuje głowica
41 |
42 | /**
43 | * Pole logiczne definiujące tryb gadatliwy.
44 | */
45 | bool verbose;
46 |
47 | protected:
48 |
49 | /**
50 | * Referencja do obrazu kodu, po którym porusza się głowica.
51 | */
52 | QImage *image; // obraz kodu (plik graficzny którego pixle będą interpretowane)
53 |
54 | /**
55 | * Codel chooser (CC, selektor kodeli).
56 | */
57 | PCodelChooserValues codel_chooser;
58 | void setCodelChooser(PCodelChooserValues);
59 |
60 | /**
61 | * Direction pointer (DP, wskaźnik kierunku).
62 | */
63 | PDirectionPointerValues direction_pointer; // direction pointer
64 | void setDirectionPointer(PDirectionPointerValues);
65 |
66 | void turnDirectionPointerClockwise();
67 | void turnDirectionPointerAnticlockwise();
68 |
69 | public:
70 |
71 | PCodePointer(QImage *, PPoint);
72 | ~PCodePointer();
73 |
74 | void setVerbosity(bool);
75 |
76 | void clear();
77 |
78 | PPoint getCoordinates();
79 | void setCoordinateX(int);
80 | void incCoordinateX();
81 | void decCoordinateX();
82 | void setCoordinateY(int);
83 | void incCoordinateY();
84 | void decCoordinateY();
85 | void setCoordinates(PPoint);
86 | QRgb getPointedPixel();
87 |
88 | QRgb getPixel(PPoint);
89 | bool pointOutsideImage(PPoint);
90 |
91 | PDirectionPointerValues getDirectionPointerValue();
92 | PCodelChooserValues getCodelChooserValue();
93 | void toggleCodelChooser();
94 | void toggleDirectionPointer();
95 | void toggle();
96 |
97 | };
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/src/core/p_block_manager.h:
--------------------------------------------------------------------------------
1 | #ifndef P_BLOCK_MANAGER
2 | #define P_BLOCK_MANAGER
3 |
4 | //// includes
5 |
6 | // piet core
7 | #include "p_enums.h"
8 | #include "p_structs.h"
9 | #include "p_code_pointer.h"
10 |
11 | // C++
12 | // none
13 |
14 | // STL
15 | #include
16 |
17 | // Qt
18 | #include
19 | #include
20 |
21 | /** \file pblockmanager.h
22 | * \brief plik nagłówkowy klasy PBlockManager
23 | *
24 | * Plik nagłówkowy zawiera definicję klasy PBlockManager.
25 | */
26 |
27 | /** \brief Manager bloków kolorów
28 | *
29 | * Klasa odpowiedzialna właściwie tylko za jedną, ale dosyć skomplikowaną operację - obliczanie ilości kodeli w danym bloku koloru. Ta wydzielona klasa posiada własne struktury danych i algorytm i zwraca maszynie kodu (klasie opakowującej) liczbę kodeli w danym bloku.
30 | */
31 | class PBlockManager {
32 |
33 | private:
34 |
35 | int height, width; // wymiary obrazu kodu
36 | int **fields; // 2-wymiarowa tablica pomocnicza
37 |
38 | void allocateMultiArray();
39 | void deallocateMultiArray();
40 |
41 | void reqCrawlMultiArray(QRgb, PPoint);
42 |
43 | void countCodels(); // zlicza kodele bloku kolorów na który wskazuje głowica
44 | void findBorderCodels(); // wyznacza skrajne krawędzie bloków kolorów
45 |
46 | int findRowMostLeftCodel(int);
47 | int findRowMostRightCodel(int);
48 | int findColumnTopCodel(int);
49 | int findColumnBottomCodel(int);
50 |
51 | /**
52 | * Pole logiczne definiujące tryb gadatliwy.
53 | */
54 | bool verbose;
55 |
56 | std::stringstream &stream;
57 |
58 | protected:
59 |
60 | /**
61 | * Referencja do obrazu kodu.
62 | */
63 | QImage *image;
64 | /**
65 | * Referencja do glowicy obrazu kodu.
66 | */
67 | PCodePointer *pointer;
68 | /**
69 | * Pole przechowujące liczbę kodeli bloku kolorów (liczoną osobno przy wykonywaniu każdej instrukcji przez wirtualną maszynę).
70 | */
71 | int codel_block_count;
72 |
73 | /** Pole określające odciętą (współrzędną) skrajnego kodela z prawej strony, znajdującego się w aktualnie badanym bloku koloru. */ int border_right_codel;
74 | /** Pole określające rzędną (współrzędną) skrajnego kodela z dołu, znajdującego się w aktualnie badanym bloku koloru. */ int border_down_codel;
75 | /** Pole określające odciętą (współrzędną) skrajnego kodela z lewej strony, znajdującego się w aktualnie badanym bloku koloru. */ int border_left_codel;
76 | /** Pole określające rzędną (współrzędną) skrajnego kodela z góry, znajdującego się w aktualnie badanym bloku koloru. */ int border_up_codel;
77 |
78 | void fillMultiArray(int);
79 | void clearMultiArray();
80 |
81 | public:
82 |
83 | PBlockManager(QImage *, PCodePointer *, std::stringstream &);
84 | ~PBlockManager();
85 |
86 | void setVerbosity(bool);
87 |
88 | void searchAndFillCodels(); // przygotowuje pomoczniczą tablicę do użytku i podstawia potrzebną liczbę kodeli pod zmienną
89 | int getCodelBlockCount();
90 |
91 | PPoint getNextPossibleCodel();
92 |
93 | // development:
94 |
95 | void __dev__showMultiArray();
96 | void __dev__showCountAndBorderCodels();
97 |
98 | };
99 |
100 | #endif
101 |
--------------------------------------------------------------------------------
/src/core/p_enums.cpp:
--------------------------------------------------------------------------------
1 | #include "p_enums.h"
2 |
3 | const char * PEnums::stdColor(PStdColors color)
4 | {
5 | switch (color) {
6 | case color_light_red: return "light red";
7 | case color_normal_red: return "normal red";
8 | case color_dark_red: return "dark red";
9 | case color_light_yellow: return "light yellow";
10 | case color_normal_yellow: return "normal yellow";
11 | case color_dark_yellow: return "dark yellow";
12 | case color_light_green: return "light green";
13 | case color_normal_green: return "normal green";
14 | case color_dark_green: return "dark green";
15 | case color_light_cyan: return "light cyan";
16 | case color_normal_cyan: return "normal cyan";
17 | case color_dark_cyan: return "dark cyan";
18 | case color_light_blue: return "light blue";
19 | case color_normal_blue: return "normal blue";
20 | case color_dark_blue: return "dark blue";
21 | case color_light_magenta: return "light magenta";
22 | case color_normal_magenta: return "normal magenta";
23 | case color_dark_magenta: return "dark magenta";
24 | case color_white: return "white";
25 | case color_black: return "black";
26 | }
27 | }
28 |
29 | const char * PEnums::nonStdColorBehavior(PNonStdColorBehavior behavior)
30 | {
31 | switch (behavior) {
32 | case beh_treat_as_white: return "treat as white";
33 | case beh_treat_as_black: return "treat as black";
34 | case beh_nearest_upper: return "nearest upper";
35 | case beh_nearest_lower: return "nearest lower";
36 | case beh_nearest_neighbour: return "nearest neighbour";
37 | }
38 | }
39 |
40 | const char * PEnums::codelChooser(PCodelChooserValues codel_chooser)
41 | {
42 | switch (codel_chooser) {
43 | case cc_left: return "left";
44 | case cc_right: return "right";
45 | }
46 | }
47 |
48 | const char * PEnums::directionPointer(PDirectionPointerValues direction_pointer)
49 | {
50 | switch (direction_pointer) {
51 | case dp_right: return "right";
52 | case dp_down: return "down";
53 | case dp_left: return "left";
54 | case dp_up: return "up";
55 | }
56 | }
57 |
58 | const char * PEnums::machineState(PMachineStates state)
59 | {
60 | switch (state) {
61 | case state_ready: return "ready";
62 | case state_running: return "running";
63 | case state_finished: return "finished";
64 | }
65 | }
66 |
67 | const char * PEnums::instruction(PInstructions instruction)
68 | {
69 | switch (instruction) {
70 | case pietInstr_special_empty: return "empty";
71 | case pietInstr_stack_push: return "push";
72 | case pietInstr_stack_pop: return "pop";
73 | case pietInstr_arithm_add: return "add";
74 | case pietInstr_arithm_subtract: return "subtract";
75 | case pietInstr_arithm_multiply: return "multiply";
76 | case pietInstr_arithm_divide: return "divide";
77 | case pietInstr_arithm_modulo: return "modulo";
78 | case pietInstr_logic_not: return "not";
79 | case pietInstr_logic_greater: return "greater";
80 | case pietInstr_runtime_pointer: return "pointer";
81 | case pietInstr_runtime_switch: return "switch";
82 | case pietInstr_stack_duplicate: return "duplicate";
83 | case pietInstr_stack_roll: return "roll";
84 | case pietInstr_io_in_number: return "read number";
85 | case pietInstr_io_in_char: return "read char";
86 | case pietInstr_io_out_number: return "print number";
87 | case pietInstr_io_out_char: return "print char";
88 | case pietInstr_special_terminate: return "terminate";
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/core/p_virtual_machine.h:
--------------------------------------------------------------------------------
1 | #ifndef P_VIRTUAL_MACHINE
2 | #define P_VIRTUAL_MACHINE
3 |
4 | //// includes
5 |
6 | // piet core
7 | #include "p_enums.h"
8 | #include "p_structs.h"
9 | #include "p_console.h"
10 | #include "p_block_manager.h"
11 | #include "p_color_manager.h"
12 | #include "p_code_pointer.h"
13 | #include "p_calc_stack.h"
14 |
15 | // C++
16 | #include
17 | #include
18 |
19 | // STL
20 | // none
21 |
22 | // Qt
23 | #include
24 |
25 | /** \file pvirtualmachine.h
26 | * \brief plik nagłówkowy klasy PVirtualMachine
27 | *
28 | * Plik nagłówkowy zawiera definicję klasy PVirtualMachine.
29 | */
30 |
31 | /** \brief Wirtualna maszyna Pieta
32 | *
33 | * Klasa realizująca tzw. "wirtualną maszynę Pieta", która posiada wszystkie mechanizmy potrzebne do egzekucji kodu Pieta.
34 |
35 | Klasa sama w sobie posiada niewiele mechanizmów (precyzyjniej: najmniej jak to było możliwe), aby wszystkie szczegółowe operacje wydzielić dla pozostałych klas w obrębie projektu. Wirtualna maszyna zajmuje się (oprócz tworzenia pomocniczych obiektów) tylko egzekucją pojedynczych instrukcji Pieta (oraz związane z tym zatrzymywanie, uruchamianie, przygotowywanie maszyny).
36 |
37 | Jej dwoma najważniejszymi elementami są: stos, na którym przechowywane są tymczasowe wartości, oraz tzw. "maszyna kodu", odpowiedzialna za pełną interpretację kodu.
38 | */
39 | class PVirtualMachine {
40 |
41 | private:
42 |
43 | PMachineStates state;
44 | QImage *image; // obraz kodu (plik graficzny którego pixle będą interpretowane)
45 | PCodePointer *pointer; // wskaźnik czytający obraz powyższy kodu
46 | PColorManager *color_manager; // maszyna zajmująca się przetwarzaniem i interpretacją kolorów
47 | PBlockManager *block_manager;
48 | std::stringstream &stream;
49 | void construct();
50 |
51 | int step;
52 |
53 | bool verbose;
54 | void setVerbosityRecursively(bool);
55 |
56 | protected:
57 |
58 | /**
59 | * Stos przechowujący wszystkie tymczasowe wartości
60 | */
61 | PCalcStack *stack;
62 | /**
63 | * Konsola wejścia/wyjścia Pieta, obsługująca operacje komunikacji z użytkownikiem
64 | */
65 | PConsole *console;
66 |
67 | void setState(PMachineStates);
68 |
69 | void prepareToExecute();
70 |
71 | virtual void readNumber() = 0;
72 | virtual void readChar() = 0;
73 |
74 | public:
75 |
76 | PVirtualMachine(const char *, std::stringstream &);
77 | ~PVirtualMachine();
78 |
79 | bool isReady();
80 | bool isRunning();
81 | bool isFinished();
82 |
83 | bool startMachine();
84 | bool restartMachine();
85 | bool stopMachine();
86 |
87 | bool isVerbose();
88 | void toggleVerbosity();
89 | void setVerbosity(bool);
90 |
91 | std::list::iterator calc_stack_begin_iterator();
92 | std::list::iterator calc_stack_end_iterator();
93 |
94 | const QImage* getImage() const;
95 |
96 | // TODO zastanowic sie jaki typ ma zwracac
97 | void executeAllInstr(); // wykonywanie instrukcji do końca działania programu
98 | bool executeSingleInstr(); // wykonanie jednej instrukcji
99 |
100 | bool pointIsBlackOrOutside(PPoint);
101 | bool pointIsWhite(PPoint);
102 | void slidePointerAcrossWhiteBlock();
103 | void slideAcrossWhiteBlock(PPoint &);
104 |
105 | PInstructions movePointerAndGetInstructionToExecute(); // jedna z najważniejszych metod tej klasy - koordynuje wykonywanie pojedynczego polecenia interpretera
106 |
107 | PInstructions getInstructionByIndex(int);
108 |
109 | PMachineStates getState();
110 |
111 | // code pointer
112 | PPoint getCodePointerCoordinates();
113 | PDirectionPointerValues getDirectionPointer();
114 | PCodelChooserValues getCodelChooser();
115 |
116 | // development:
117 |
118 | void __dev__printImageInfo();
119 | void __dev__printConsole();
120 |
121 | };
122 |
123 | #endif
124 |
--------------------------------------------------------------------------------
/src/core/p_enums.h:
--------------------------------------------------------------------------------
1 | #ifndef P_ENUMS
2 | #define P_ENUMS
3 |
4 | /** \file penums.h
5 | * \brief Plik nagłówkowy z definicjami enumeracji
6 | *
7 | * Plik nagłówkowy zawiera wszystkie definicje enumeracji które są wykorzystywane w projekcie.
8 | */
9 |
10 | /** \brief Standardowe kolory
11 | *
12 | * Enumeracja wyszczególniająca kolory standardowe wykorzystywane do określania wykonywanej instrukcji.
13 | */
14 | enum PStdColors {
15 | color_light_red,
16 | color_normal_red,
17 | color_dark_red,
18 | color_light_yellow,
19 | color_normal_yellow,
20 | color_dark_yellow,
21 | color_light_green,
22 | color_normal_green,
23 | color_dark_green,
24 | color_light_cyan,
25 | color_normal_cyan,
26 | color_dark_cyan,
27 | color_light_blue,
28 | color_normal_blue,
29 | color_dark_blue,
30 | color_light_magenta,
31 | color_normal_magenta,
32 | color_dark_magenta,
33 | color_white,
34 | color_black
35 | };
36 |
37 | /** \brief Interpretacja niestandardowych kolorów
38 | *
39 | * Enumeracja wyszczególniająca możliwe sposoby interpretacji kolorów niestandardowych.
40 | */
41 | enum PNonStdColorBehavior {
42 | beh_treat_as_white,
43 | beh_treat_as_black,
44 | beh_nearest_upper,
45 | beh_nearest_lower,
46 | beh_nearest_neighbour
47 | };
48 |
49 | /** \brief Tryby codel chooser
50 | *
51 | * Enumeracja wyszczególniająca tryby pracy codel chooser, czyli kierunki w których głowica ma szukać skrajnego kodela po dojściu do granicy bloku w kierunku wskazanym przez direction pointer.
52 | */
53 | enum PCodelChooserValues {
54 | cc_left,
55 | cc_right
56 | };
57 |
58 | /** \brief Tryby direction pointer
59 | *
60 | * Enumeracja wyszczególniająca tryby pracy direction pointer, czyli kierunki w których głowica ma poruszać się aż dojdzie do granicy bloku kolorów (potem codel chooser określa z której strony przejdzie do nowego bloku - dzięki temu glowica przechodzi z jednego bloku kolorów do drugiego i wykonują się instrukcje Pieta).
61 | */
62 | enum PDirectionPointerValues {
63 | dp_right,
64 | dp_down,
65 | dp_left,
66 | dp_up
67 | };
68 |
69 | /** \brief stany maszyny wirtualnej
70 | *
71 | * Enumeracja wyszczególniająca stany tzw. "maszyny wirtualnej Pieta", która zajmuje się pełną interpretacją kodu Pieta.
72 | */
73 | enum PMachineStates {
74 | state_ready,
75 | state_running,
76 | state_finished
77 | };
78 |
79 | /** \brief instrukcje Pieta
80 | *
81 | * Enumeracja wyszczególniająca wszystkie instrukcje wykonywane przez język Piet.
82 | */
83 | enum PInstructions {
84 | pietInstr_special_empty, /** 0 - dodatkowa instrukcja wysyłana do wirtualnej maszyny komunikująca o 8 nieudanych próbach wykonania przez głowicę ruchu, zakończenie pracy programu */
85 | pietInstr_stack_push, /** 1 - instrukcja PUSH */
86 | pietInstr_stack_pop, /** 2 - instrukcja POP */
87 | pietInstr_arithm_add, /** 3 - instrukcja ADD */
88 | pietInstr_arithm_subtract, /** 4 - instrukcja SUB */
89 | pietInstr_arithm_multiply, /** 5 - instrukcja MUL */
90 | pietInstr_arithm_divide, /** 6 - instrukcja DIV */
91 | pietInstr_arithm_modulo, /** 7 - instrukcja MOD */
92 | pietInstr_logic_not, /** 8 - instrukcja NOT */
93 | pietInstr_logic_greater, /** 9 - instrukcja GREATER */
94 | pietInstr_runtime_pointer, /** 10 - instrukcja POINER */
95 | pietInstr_runtime_switch, /** 11 - instrukcja SWITCH */
96 | pietInstr_stack_duplicate, /** 12 - instrukcja DUP */
97 | pietInstr_stack_roll, /** 13 - instrukcja ROLL */
98 | pietInstr_io_in_number, /** 14 - instrukcja IN(number) */
99 | pietInstr_io_in_char, /** 15 - instrukcja IN(char) */
100 | pietInstr_io_out_number, /** 16 - instrukcja OUT(number) */
101 | pietInstr_io_out_char, /** 17 - instrukcja OUT(char) */
102 | pietInstr_special_terminate, /** 18 - instrukcja TERMINATE */
103 | };
104 |
105 | class PEnums {
106 |
107 | public:
108 | static const char * stdColor(PStdColors);
109 | static const char * nonStdColorBehavior(PNonStdColorBehavior);
110 | static const char * codelChooser(PCodelChooserValues);
111 | static const char * directionPointer(PDirectionPointerValues);
112 | static const char * machineState(PMachineStates);
113 | static const char * instruction(PInstructions);
114 |
115 | };
116 |
117 | #endif
118 |
--------------------------------------------------------------------------------
/src/gui/main_window.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 |
15 | 800
16 | 600
17 |
18 |
19 |
20 | Piet Esoteric Language Interpreter
21 |
22 |
23 |
24 | :/images/view-form-action.png:/images/view-form-action.png
25 |
26 |
27 |
28 | -
29 |
30 |
31 | true
32 |
33 |
34 | ArrowCursor
35 |
36 |
37 |
38 |
39 |
40 |
41 |
66 |
67 |
68 |
69 | :/images/help-contents.png:/images/help-contents.png
70 |
71 |
72 | About
73 |
74 |
75 | About
76 |
77 |
78 | Show information about the program
79 |
80 |
81 |
82 |
83 |
84 | :/images/application-exit.png:/images/application-exit.png
85 |
86 |
87 | Quit
88 |
89 |
90 | Quit application
91 |
92 |
93 | Quit application
94 |
95 |
96 |
97 |
98 |
99 | :/images/quickopen.png:/images/quickopen.png
100 |
101 |
102 | Run
103 |
104 |
105 | Run Piet program from image file
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | actionQuit
115 | triggered()
116 | MainWindow
117 | close()
118 |
119 |
120 | -1
121 | -1
122 |
123 |
124 | 334
125 | 277
126 |
127 |
128 |
129 |
130 | actionAbout
131 | triggered()
132 | MainWindow
133 | displayAbout()
134 |
135 |
136 | -1
137 | -1
138 |
139 |
140 | 399
141 | 299
142 |
143 |
144 |
145 |
146 | actionRun
147 | triggered()
148 | MainWindow
149 | openChildWindow()
150 |
151 |
152 | -1
153 | -1
154 |
155 |
156 | 399
157 | 299
158 |
159 |
160 |
161 |
162 |
163 | displayAbout()
164 | openChildWindow()
165 |
166 |
167 |
--------------------------------------------------------------------------------
/src/gui/machine_widget.cpp:
--------------------------------------------------------------------------------
1 | #include "machine_widget.h"
2 | #include "ui_machine_widget.h"
3 |
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | #include "p_enums.h"
11 | #include "p_structs.h"
12 | #include "p_gui_virtual_machine.h"
13 | #include "program_image_widget.h"
14 |
15 | MachineWidget::MachineWidget(QWidget *parent) :
16 | QWidget(parent),
17 | ui(new Ui::MachineWidget)
18 | {
19 | ui->setupUi(this);
20 | connect(this, SIGNAL(fileChosen(QString)), this, SLOT(createMachine(QString)));
21 |
22 | program_image = new ProgramImageWidget();
23 | ui->groupBoxSource->layout()->addWidget(program_image);
24 | program_image->show();
25 |
26 | stream = new std::stringstream();
27 |
28 | disableMachineInterface();
29 | std::cout << "machine widget constructed" << std::endl;
30 | }
31 |
32 | MachineWidget::~MachineWidget()
33 | {
34 | if (machine_created)
35 | {
36 | delete piet;
37 | }
38 | delete stream;
39 | delete program_image;
40 | delete ui;
41 | std::cout << "machine widget destructed" << std::endl;
42 | }
43 |
44 | void MachineWidget::toggleVerbosity(bool verbose)
45 | {
46 | piet->setVerbosity(verbose);
47 | }
48 |
49 | void MachineWidget::chooseFile()
50 | {
51 | QString filepath = QFileDialog::getOpenFileName(this,
52 | tr("Open File"), "", tr("Files (*.*)"));
53 |
54 | if (!filepath.isEmpty()) {
55 | QImage *image = new QImage(filepath);
56 | if (image->isNull()) {
57 | QMessageBox::information(this, tr(
58 | "Image Viewer"), tr("Cannot load %1.").arg(filepath));
59 | return;
60 | } else {
61 | emit fileChosen(filepath);
62 | }
63 | }
64 | }
65 |
66 | void MachineWidget::createMachine(QString filepath)
67 | {
68 | this->setWindowTitle(filepath);
69 | ui->consoleOutputBrowser->setText("");
70 |
71 | if (machine_created)
72 | {
73 | delete piet;
74 | }
75 |
76 | piet = new PGuiVirtualMachine(filepath.toStdString().c_str(), *stream);
77 | program_image->setPiet(piet);
78 | program_image->render();
79 | machine_created = true;
80 | updateInformation();
81 | }
82 |
83 | ///////////////////////////////////////////////////////////////////////////////
84 |
85 | void MachineWidget::enableMachineInterface()
86 | {
87 | machine_created = true;
88 | ui->pushButtonExecuteAllInstructions->setEnabled(true);
89 | ui->pushButtonExecuteSingleInstruction->setEnabled(true);
90 | ui->pushButtonStop->setEnabled(true);
91 | }
92 |
93 | void MachineWidget::disableMachineInterface()
94 | {
95 | machine_created = false;
96 | ui->pushButtonExecuteAllInstructions->setEnabled(false);
97 | ui->pushButtonExecuteSingleInstruction->setEnabled(false);
98 | ui->pushButtonStop->setEnabled(false);
99 | }
100 |
101 | void MachineWidget::executeSingleInstruction()
102 | {
103 | piet->executeSingleInstr();
104 | std::string output(stream->str());
105 | stream->str(""); // clearing
106 | ui->consoleOutputBrowser->setText(ui->consoleOutputBrowser->toPlainText().append(output.c_str()));
107 | updateInformation();
108 | }
109 |
110 | void MachineWidget::executeAllInstructions()
111 | {
112 | piet->executeAllInstr();
113 | std::string output(stream->str());
114 | stream->str(""); // clearing
115 | ui->consoleOutputBrowser->setText(ui->consoleOutputBrowser->toPlainText().append(output.c_str()));
116 | updateInformation();
117 | }
118 |
119 | void MachineWidget::startMachine()
120 | {
121 | piet->startMachine();
122 | std::cout << "STARTED" << std::endl;
123 | enableMachineInterface();
124 | updateCodeCoordinates();
125 | updateState();
126 | }
127 |
128 | void MachineWidget::restartMachine()
129 | {
130 | piet->restartMachine();
131 | updateState();
132 | }
133 |
134 | void MachineWidget::stopMachine()
135 | {
136 | piet->stopMachine();
137 | disableMachineInterface();
138 | updateState();
139 | }
140 |
141 | void MachineWidget::clearCalcStack()
142 | {
143 | while(ui->listWidgetCalcStack->count())
144 | ui->listWidgetCalcStack->takeItem(0);
145 | }
146 |
147 | void MachineWidget::fillCalcStack()
148 | {
149 | for (std::list::iterator it = piet->calc_stack_begin_iterator(); it != piet->calc_stack_end_iterator(); ++it)
150 | ui->listWidgetCalcStack->addItem(QString::number(*it));
151 | }
152 |
153 | void MachineWidget::updateState()
154 | {
155 | PMachineStates state = piet->getState();
156 | ui->labelStateValue->setText(PEnums::machineState(state));
157 | if (state == state_finished) {
158 | ui->pushButtonExecuteAllInstructions->setEnabled(false);
159 | ui->pushButtonExecuteSingleInstruction->setEnabled(false);
160 | }
161 | }
162 |
163 | void MachineWidget::updateCodeCoordinates()
164 | {
165 | PPoint coords = piet->getCodePointerCoordinates();
166 | ui->labelPointerXValue->setText(QString::number(coords.x));
167 | ui->labelPointerYValue->setText(QString::number(coords.y));
168 |
169 | PCodelChooserValues cc = piet->getCodelChooser();
170 | ui->labelPointerCCValue->setText(PEnums::codelChooser(cc));
171 |
172 | PDirectionPointerValues dp = piet->getDirectionPointer();
173 | ui->labelPointerDPValue->setText(PEnums::directionPointer(dp));
174 | }
175 |
176 | void MachineWidget::updateInformation()
177 | {
178 | clearCalcStack();
179 | fillCalcStack();
180 | updateState();
181 | updateCodeCoordinates();
182 | }
183 |
--------------------------------------------------------------------------------
/src/core/p_color_manager.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_color_manager.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 |
11 | //C
12 | #include
13 |
14 | // C++
15 | #include
16 |
17 | // STL
18 | // none
19 |
20 | // Qt
21 | #include
22 |
23 | /** \file pcolormanager.cpp
24 | * \brief Plik z kodem źródłowym klasy PColorManager
25 | *
26 | * Plik zawiera kod źródłowy klasy PColorManager.
27 | */
28 |
29 | PColorManager::PColorManager(std::stringstream &str) : stream(str)
30 | {
31 | debug("CONSTRUCTOR ----- color-manager START\n");
32 | verbose = false;
33 | initColorValues();
34 | debug("CONSTRUCTOR ----- color-manager END\n");
35 | }
36 |
37 | PColorManager::~PColorManager()
38 | {
39 | debug("DESTRUCTOR ----- color-manager START\n");
40 |
41 | debug("DESTRUCTOR ----- color-manager END\n");
42 | }
43 |
44 | /**
45 | * Ustala tryb gadatliwy.
46 | * @param verbosity tryb gadatliwy
47 | */
48 | void PColorManager::setVerbosity(bool verbosity)
49 | {
50 | verbose = verbosity;
51 | }
52 |
53 | /**
54 | * Inicjuje wartości zmiennych typu QRgb reprezentujących wszystkie 20 kolorów standardowych Pieta. Są one potem wykorzystywane praktycznie cały czas: do wyznaczania instrukcji które powinny być wykonane, do sprawdzania białych lub czarnych bloków.
55 | */
56 | void PColorManager::initColorValues()
57 | {
58 | // red
59 | LIGHT_RED = qRgb(255, 192, 192);
60 | NORMAL_RED = qRgb(255, 0, 0);
61 | DARK_RED = qRgb(192, 0, 0);
62 | // yellow
63 | LIGHT_YELLOW = qRgb(255, 255, 192);
64 | NORMAL_YELLOW = qRgb(255, 255, 0);
65 | DARK_YELLOW = qRgb(192, 192, 0);
66 | // green
67 | LIGHT_GREEN = qRgb(192, 255, 192);
68 | NORMAL_GREEN = qRgb(0, 255, 0);
69 | DARK_GREEN = qRgb(0, 192, 0);
70 | // cyan
71 | LIGHT_CYAN = qRgb(192, 255, 255);
72 | NORMAL_CYAN = qRgb(0, 255, 255);
73 | DARK_CYAN = qRgb(0, 192, 192);
74 | // blue
75 | LIGHT_BLUE = qRgb(192, 192, 255);
76 | NORMAL_BLUE = qRgb(0, 0, 255);
77 | DARK_BLUE = qRgb(0, 0, 192);
78 | // magenta
79 | LIGHT_MAGENTA = qRgb(255, 192, 255);
80 | NORMAL_MAGENTA = qRgb(255, 0, 255);
81 | DARK_MAGENTA = qRgb(192, 0, 192);
82 | // black, white
83 | WHITE = qRgb(255, 255, 255);
84 | BLACK = qRgb(0, 0, 0);
85 | }
86 |
87 | /**
88 | * Zwraca kolor jako element enumeracji dla zadanej wartości koloru typu QRgb.
89 | * @param color zadany kolor (wartość)
90 | * @return kolor (element enumeracji)
91 | */
92 | PStdColors PColorManager::getColorName(QRgb color)
93 | {
94 | if (color == LIGHT_RED) {
95 | return color_light_red;
96 | } else if (color == NORMAL_RED) {
97 | return color_normal_red;
98 | } else if (color == DARK_RED) {
99 | return color_dark_red;
100 | } else if (color == LIGHT_YELLOW) {
101 | return color_light_yellow;
102 | } else if (color == NORMAL_YELLOW) {
103 | return color_normal_yellow;
104 | } else if (color == DARK_YELLOW) {
105 | return color_dark_yellow;
106 | } else if (color == LIGHT_GREEN) {
107 | return color_light_green;
108 | } else if (color == NORMAL_GREEN) {
109 | return color_normal_green;
110 | } else if (color == DARK_GREEN) {
111 | return color_dark_green;
112 | } else if (color == LIGHT_CYAN) {
113 | return color_light_cyan;
114 | } else if (color == NORMAL_CYAN) {
115 | return color_normal_cyan;
116 | } else if (color == DARK_CYAN) {
117 | return color_dark_cyan;
118 | } else if (color == LIGHT_BLUE) {
119 | return color_light_blue;
120 | } else if (color == NORMAL_BLUE) {
121 | return color_normal_blue;
122 | } else if (color == DARK_BLUE) {
123 | return color_dark_blue;
124 | } else if (color == LIGHT_MAGENTA) {
125 | return color_light_magenta;
126 | } else if (color == NORMAL_MAGENTA) {
127 | return color_normal_magenta;
128 | } else if (color == DARK_MAGENTA) {
129 | return color_dark_magenta;
130 | } else if (color == WHITE) {
131 | return color_white;
132 | } else if (color == BLACK) {
133 | return color_black;
134 | } else {
135 | stream << "ERROR: PStdColors PColorManager::getColorName(QRgb color)" << std::endl;
136 | stream << "R:" << qRed(color) << " G:" << qGreen(color) << " B:" << qBlue(color) << std::endl;
137 | exit(1);
138 | }
139 | }
140 |
141 | int PColorManager::lightnessCycleDifference(PStdColors c1, PStdColors c2)
142 | {
143 | int c1code = (int) c1, c2code = (int) c2;
144 | return ((c1code - c2code + 21) % 3);
145 | }
146 |
147 | int PColorManager::saturationCycleDifference(PStdColors c1, PStdColors c2)
148 | {
149 | int c1code = (int) c1, c2code = (int) c2;
150 | return ( ( (c1code / 3) - (c2code / 3) + 6) % 6);
151 | }
152 |
153 | /**
154 | * Wyznacza instrukcję Pieat jaka ma zostać wykonana na podstawie dwóch kolorów bloków: pierwszy - który głowica opuściła i drugi - do którego głowica weszła. Metoda implementuje algorytm wyznaczania instrukcji opisany w tabeli 1.2 w rozdziale 1 pracy magisterskiej.
155 | * @param old_color kolor bloku który głowica opuściła
156 | * @param new_color kolor bloku do którego głowica weszła
157 | * @return indeks instrukcji która powinna zostać wykonana
158 | */
159 | int PColorManager::getInstructionIndex(QRgb old_color, QRgb new_color)
160 | {
161 | PStdColors p_old_color = getColorName(old_color);
162 | PStdColors p_new_color = getColorName(new_color);
163 |
164 | if (verbose) {
165 | stream << PEnums::stdColor(p_old_color) << "(" << ( (int) p_old_color ) << ")";
166 | stream << " -> ";
167 | stream << PEnums::stdColor(p_new_color) << "(" << ( (int) p_new_color ) << ")" << "; ";
168 | }
169 |
170 | int lightness_diff = lightnessCycleDifference(p_new_color, p_old_color);
171 | int saturation_diff = saturationCycleDifference(p_new_color, p_old_color);
172 |
173 | return ( 3 * saturation_diff + lightness_diff );
174 | }
175 |
--------------------------------------------------------------------------------
/src/core/p_code_pointer.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_code_pointer.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 |
11 | // C++
12 | #include
13 |
14 | // STL
15 | // none
16 |
17 | // Qt
18 | // none
19 |
20 | /** \file pcodepointer.cpp
21 | * \brief Plik z kodem źródłowym klasy PCodePointer
22 | *
23 | * Plik zawiera kod źródłowy klasy PCodePointer.
24 | */
25 |
26 | /**
27 | * Konstruktor głowicy obrazu kodu. Nie robi nic szczególnego.
28 | */
29 | PCodePointer::PCodePointer(QImage *code_image, PPoint initial)
30 | {
31 | debug("CONSTRUCTOR ----- code-pointer START\n");
32 | verbose = false;
33 | initial_coords = initial;
34 | image = code_image; // referencja do obiektu obrazu kodu
35 | debug("CONSTRUCTOR ----- code-pointer END\n");
36 | }
37 |
38 | /**
39 | * Destruktor głowicy obrazu kodu. Nie robi nic szczególnego.
40 | */
41 | PCodePointer::~PCodePointer()
42 | {
43 | debug("DESTRUCTOR ----- code-pointer START\n");
44 |
45 | debug("DESTRUCTOR ----- code-pointer END\n");
46 | }
47 |
48 | /**
49 | * Ustala tryb gadatliwy.
50 | * @param verbosity tryb gadatliwy
51 | */
52 | void PCodePointer::setVerbosity(bool verbosity)
53 | {
54 | verbose = verbosity;
55 | }
56 |
57 | /**
58 | * Ustawia atrybuty głowicy (współrzędne oraz DP i CC) na wartości domyślne.
59 | */
60 | void PCodePointer::clear()
61 | {
62 | coords.x = initial_coords.x;
63 | coords.y = initial_coords.y;
64 | codel_chooser = INIT_cc;
65 | direction_pointer = INIT_dp;
66 | }
67 |
68 | //==================================================================
69 |
70 | /**
71 | * Zwraca piksel wskazywany przez głowicę.
72 | * @return piksel wskazywany przez głowicę
73 | */
74 | QRgb PCodePointer::getPointedPixel()
75 | {
76 | return image->pixel(coords.x, coords.y);
77 | }
78 |
79 | /**
80 | * Zwraca piksel o zadanych współrzędnych.
81 | * @param point współrzędne punktu
82 | * @return piksel o wskazanych współrzędnych
83 | */
84 | QRgb PCodePointer::getPixel(PPoint point)
85 | {
86 | return image->pixel(point.x, point.y);
87 | }
88 |
89 | //==================================================================
90 |
91 | /**
92 | * Ustala wartość DP.
93 | * @param dp wartość DP
94 | */
95 | void PCodePointer::setDirectionPointer(PDirectionPointerValues dp)
96 | {
97 | direction_pointer = dp;
98 | }
99 |
100 | /**
101 | * Zwraca wartość DP.
102 | * @return wartość DP
103 | */
104 | PDirectionPointerValues PCodePointer::getDirectionPointerValue()
105 | {
106 | return direction_pointer;
107 | }
108 |
109 | //==================================================================
110 |
111 | /**
112 | * Ustala wartość CC.
113 | * @param cc wartość CC
114 | */
115 | void PCodePointer::setCodelChooser(PCodelChooserValues cc)
116 | {
117 | codel_chooser = cc;
118 | }
119 |
120 | /**
121 | * Zwraca wartość DP.
122 | * @return wartość DP
123 | */
124 | PCodelChooserValues PCodePointer::getCodelChooserValue()
125 | {
126 | return codel_chooser;
127 | }
128 |
129 | //==================================================================
130 |
131 | /**
132 | * Obraca DP zgodnie z ruchem wskazówek zegara raz.
133 | */
134 | void PCodePointer::turnDirectionPointerClockwise()
135 | {
136 | switch (direction_pointer) {
137 | case dp_right:
138 | direction_pointer = dp_down;
139 | break;
140 | case dp_down:
141 | direction_pointer = dp_left;
142 | break;
143 | case dp_left:
144 | direction_pointer = dp_up;
145 | break;
146 | case dp_up:
147 | direction_pointer = dp_right;
148 | break;
149 | }
150 | }
151 |
152 | /**
153 | * Obraca DP przeciwnie do ruchu wskazówek zegara raz.
154 | */
155 | void PCodePointer::turnDirectionPointerAnticlockwise()
156 | {
157 | switch (direction_pointer) {
158 | case dp_right:
159 | direction_pointer = dp_up;
160 | break;
161 | case dp_down:
162 | direction_pointer = dp_right;
163 | break;
164 | case dp_left:
165 | direction_pointer = dp_down;
166 | break;
167 | case dp_up:
168 | direction_pointer = dp_left;
169 | break;
170 | }
171 | }
172 |
173 | /**
174 | * Zmienia wartość CC w sytuacji, gdy głowica nie mogła iść dalej w dotychczasowym kierunku. Używane wewnątrz metody toggle().
175 | */
176 | void PCodePointer::toggleCodelChooser()
177 | {
178 | switch (codel_chooser) {
179 | case cc_left:
180 | codel_chooser = cc_right;
181 | break;
182 | case cc_right:
183 | codel_chooser = cc_left;
184 | break;
185 | }
186 | }
187 |
188 | /**
189 | * Zmienia wartość DP w sytuacji, gdy głowica nie mogła iść dalej w dotychczasowym kierunku. Używane wewnątrz metody toggle().
190 | */
191 | void PCodePointer::toggleDirectionPointer()
192 | {
193 | turnDirectionPointerClockwise();
194 | }
195 |
196 | /**
197 | * Zmienia wartość CC oraz DP w sytuacji, gdy głowica nie mogła iść dalej w dotychczasowym kierunku.
198 | */
199 | void PCodePointer::toggle()
200 | {
201 | if (codel_chooser == cc_left) {
202 | toggleCodelChooser();
203 | } else {
204 | toggleCodelChooser();
205 | turnDirectionPointerClockwise();
206 | }
207 | }
208 |
209 | //==================================================================
210 |
211 | /**
212 | * Zwraca współrzędne głowicy.
213 | * @return współrzędne głowicy
214 | */
215 | PPoint PCodePointer::getCoordinates()
216 | {
217 | return coords;
218 | }
219 |
220 | /**
221 | * Ustala współrzędną X głowicy.
222 | * @param newX nowa wartość współrzędnej X
223 | */
224 | void PCodePointer::setCoordinateX(int newX)
225 | {
226 | coords.x = newX;
227 | }
228 |
229 | /**
230 | * Inkrementuje współrzędną X głowicy.
231 | */
232 | void PCodePointer::incCoordinateX()
233 | {
234 | coords.x++;
235 | }
236 |
237 | /**
238 | * Dekrementuje współrzędną X głowicy.
239 | */
240 | void PCodePointer::decCoordinateX()
241 | {
242 | coords.x--;
243 | }
244 |
245 | /**
246 | * Ustala współrzędną Y głowicy.
247 | * @param newY nowa wartość współrzędnej Y
248 | */
249 | void PCodePointer::setCoordinateY(int newY)
250 | {
251 | coords.y = newY;
252 | }
253 |
254 | /**
255 | * Inkrementuje współrzędną Y głowicy.
256 | */
257 | void PCodePointer::incCoordinateY()
258 | {
259 | coords.y++;
260 | }
261 |
262 | /**
263 | * Dekrementuje współrzędną Y głowicy.
264 | */
265 | void PCodePointer::decCoordinateY()
266 | {
267 | coords.y--;
268 | }
269 |
270 | /**
271 | * Ustala współrzędne głowicy.
272 | * @param new_point punkt (nowe współrzędne)
273 | */
274 | void PCodePointer::setCoordinates(PPoint new_point)
275 | {
276 | coords = new_point;
277 | }
278 |
279 | /**
280 | * Determinuje, czy punkt o zadanych współrzędnych mieści się w obrazie kodu.
281 | * @param point wskazany punkt
282 | * @return czy mieści się w obrazie kodu
283 | */
284 | bool PCodePointer::pointOutsideImage(PPoint point)
285 | {
286 | return (point.x < 0 || point.x >= image->width() || point.y < 0 || point.y >= image->height());
287 | }
288 |
--------------------------------------------------------------------------------
/src/core/p_calc_stack.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_calc_stack.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 |
11 | // C++
12 | #include
13 |
14 | // STL
15 | #include
16 |
17 | // Qt
18 | // none
19 |
20 | /** \file pcalcstack.cpp
21 | * \brief Plik z kodem źródłowym klasy PCalcStack
22 | *
23 | * Plik zawiera kod źródłowy klasy PCalcStack.
24 | */
25 |
26 | /**
27 | * Konstruktor stosu. Nie robi nic szczególnego.
28 | */
29 | PCalcStack::PCalcStack()
30 | {
31 | debug("CONSTRUCTOR ----- calc stack START\n");
32 | verbose = false;
33 | debug("CONSTRUCTOR ----- calc stack END\n");
34 | }
35 |
36 | /**
37 | * Destruktor stosu. Nie robi nic szczególnego.
38 | */
39 | PCalcStack::~PCalcStack()
40 | {
41 | debug("DESTRUCTOR ----- calc stack START\n");
42 | debug("DESTRUCTOR ----- calc stack END\n");
43 | }
44 |
45 | /**
46 | * Ustala tryb gadatliwy.
47 | * @param verbosity tryb gadatliwy
48 | */
49 | void PCalcStack::setVerbosity(bool verbosity)
50 | {
51 | verbose = verbosity;
52 | }
53 |
54 | /**
55 | * Czyści stos - usuwa wszystkie elementy.
56 | */
57 | void PCalcStack::clear()
58 | {
59 | values.clear();
60 | }
61 |
62 | /**
63 | * Przygotowuje stos do użycia (czyści go).
64 | */
65 | void PCalcStack::prepareToExecute()
66 | {
67 | clear();
68 | }
69 |
70 | /**
71 | * Zwraca rozmiar stosu.
72 | * @return rozmiar stosu
73 | */
74 | int PCalcStack::size()
75 | {
76 | return values.size();
77 | }
78 |
79 | std::list::iterator PCalcStack::begin_iterator()
80 | {
81 | return values.begin();
82 | }
83 |
84 | std::list::iterator PCalcStack::end_iterator()
85 | {
86 | return values.end();
87 | }
88 |
89 | /**
90 | * Sprawdza, czy stos posiada co najmniej zadaną liczbę elementów na stosie. Metoda wykorzystywana np. przed wykonaniem operacji ADD: muszą być na stosie co najmniej dwa elementy, aby udało się wykonać operację.
91 | * @param elements minimalna liczba elementów stosu
92 | * @return rozmiar stosu
93 | */
94 | bool PCalcStack::hasAtLeastNElements(unsigned int elements)
95 | {
96 | return (values.size() >= elements);
97 | }
98 |
99 | //==========================================================================
100 | // operacje podstawowe:
101 |
102 | /**
103 | * Wykonuje operację PUSH: odkłada element na stosie.
104 | * @param item element do odłożenia na stosie
105 | */
106 | void PCalcStack::instrPush(int item)
107 | {
108 | values.push_front(item);
109 | }
110 |
111 | /**
112 | * Wykonuje operację POP: zdejmuje element ze stosu.
113 | * @return zdjęty ze stosu element
114 | */
115 | int PCalcStack::instrPop()
116 | {
117 | int el = values.front();
118 | values.pop_front();
119 | return el;
120 | }
121 |
122 | //==========================================================================
123 | // operacje arytmetyczne:
124 |
125 | /**
126 | * Wykonuje operację ADD: zdejmuje ze szczytu stosu dwa elementy, dodaje ich wartości a wynik odkłada z powrotem na stosie.
127 | */
128 | void PCalcStack::instrAdd()
129 | {
130 | int el1 = values.front();
131 | values.pop_front();
132 | int el2 = values.front();
133 | values.pop_front();
134 | values.push_front(el2 + el1);
135 | }
136 |
137 | /**
138 | * Wykonuje operację SUB: zdejmuje ze szczytu stosu dwa elementy, oblicza różnicę: element pod elementem szczytowym - element szczytowy, a wynik odkłada z powrotem na stosie.
139 | */
140 | void PCalcStack::instrSubtract()
141 | {
142 | int el1 = values.front();
143 | values.pop_front();
144 | int el2 = values.front();
145 | values.pop_front();
146 | values.push_front(el2 - el1);
147 | }
148 |
149 | /**
150 | * Wykonuje operację MUL: zdejmuje ze szczytu stosu dwa elementy, mnoży ich wartości a wynik odkłada z powrotem na stosie.
151 | */
152 | void PCalcStack::instrMultiply()
153 | {
154 | int el1 = values.front();
155 | values.pop_front();
156 | int el2 = values.front();
157 | values.pop_front();
158 | values.push_front(el2 * el1);
159 | }
160 |
161 | /**
162 | * Wykonuje operację DIV: zdejmuje ze szczytu stosu dwa elementy, oblicza iloraz: element pod elementem szczytowym / element szczytowy, a wynik odkłada z powrotem na stosie.
163 | */
164 | void PCalcStack::instrDivide()
165 | {
166 | int el1 = values.front();
167 | values.pop_front();
168 | int el2 = values.front();
169 | values.pop_front();
170 | values.push_front(el2 / el1);
171 | }
172 |
173 | /**
174 | * Wykonuje operację MOD: zdejmuje ze szczytu stosu dwa elementy, oblicza dzielenie modulo: element pod elementem szczytowym % element szczytowy, a wynik odkłada z powrotem na stosie.
175 | */
176 | void PCalcStack::instrModulo()
177 | {
178 | int el1 = values.front();
179 | values.pop_front();
180 | int el2 = values.front();
181 | values.pop_front();
182 | values.push_front(el2 % el1);
183 | }
184 |
185 | //==========================================================================
186 | // operacje logiczne:
187 |
188 | /**
189 | * Wykonuje operację NOT: zdejmuje element ze szczytu stosu i zwraca jego logiczną negację: 1, jeśli element był równy zero lub 0 w przeciwnym razie.
190 | */
191 | void PCalcStack::instrNot()
192 | {
193 | int el = values.front();
194 | values.pop_front();
195 | values.push_front(el != 0 ? 0 : 1);
196 | }
197 |
198 | /**
199 | * Wykonuje operację GREATER: zdejmuje ze szczytu stosu dwa elementy i sprawdza, czy element pod elementem szczytowym jest większy od elementu szczytowego; jeśli tak - odkłada na stosie wartość 1, jeśli nie - 0.
200 | */
201 | void PCalcStack::instrGreater()
202 | {
203 | int el1 = values.front();
204 | values.pop_front();
205 | int el2 = values.front();
206 | values.pop_front();
207 | values.push_front(el2 > el1 ? 1 : 0);
208 | }
209 |
210 | //==========================================================================
211 | // operacje na stosie:
212 |
213 | /**
214 | * Wykonuje operację DUP: odkłada na stosie kopię elementu szczytowego stosu.
215 | */
216 | void PCalcStack::instrDuplicate()
217 | {
218 | int el = values.front();
219 | values.push_front(el);
220 | }
221 |
222 | /**
223 | * Wykonuje operację ROLL, modyfikującą strukturę stosu. Zdejmuje ze szczytu stosu dwa elementy: element ze szczytu stanowi ilość przesunięć elementów stosu (ozn. C), drugi element (który był pod elementem szczytowym) określa rozmiar fragmentu stosu jaki ulegnie modyfikacji (ozn. S). Po zdjęciu tych elementów następuje przesuwanie elementów: nowy element ze szczytu stosu przesuwa się na sam dół modyfikowanego fragmentu stosu (określanego przez S); operacja powtarza się tyle razy ile wynosi wartość C.
224 | */
225 | void PCalcStack::instrRoll()
226 | {
227 | std::list tmp;
228 | int loop_count = values.front();
229 | values.pop_front();
230 | int depth = values.front();
231 | values.pop_front();
232 | if (depth > 0) {
233 | for (int i = 0; i < depth; i++) {
234 | tmp.push_back(values.front());
235 | values.pop_front();
236 | }
237 | if (loop_count > 0) {
238 | for (int i = loop_count; i > 0; i--) {
239 | tmp.push_back(tmp.front());
240 | tmp.pop_front();
241 | }
242 | } else {
243 | for (int i = loop_count; i < 0; i++) {
244 | tmp.push_front(tmp.back());
245 | tmp.pop_back();
246 | }
247 | }
248 | for (int i = 0; i < depth; i++) {
249 | values.push_front(tmp.back());
250 | tmp.pop_back();
251 | }
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/src/console.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // piet core
4 | #include "core/p_console_virtual_machine.h"
5 | #include "core/p_enums.h"
6 | #include "debug.h"
7 |
8 | // C++
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | // STL
15 | #include
16 |
17 | // Qt
18 | #include
19 | #include
20 |
21 | /** \file test.cpp
22 | * \brief Plik z kodem źródłowym aplikacji
23 | *
24 | * Plik zawiera kod źródłowy aplikacji testującej interpreter języka Piet. Program przeznaczony do użytku pod konsolą systemu Unix.
25 | */
26 |
27 | /*! \mainpage Dokumentacja kodu projektu Piet
28 | *
29 | * Piet to graficzny język programowania autorstwa Davida Morgan-Mar. Interpreter został stworzony przez Tomasza Ducina. Poniższy tekst pochodzi ze wstępu do rozdziału 1, "Język Piet", pracy magisterskiej Tomasza Ducina pt. "Języki ezoteryczne Piet i Salvador jako uniwersalne maszyny obliczeniowe".
30 | *
31 | * Język zawdzięcza swoją nazwę imieniu malarza, Pieta Mondriana, malarza który zapoczątkował gałąź geometrycznego malarstwa abstrakcyjnego. Z założenia, programy mają przypominać obrazy malarstwa abstrakcyjnego.
32 | *
33 | * Interpreter Pieta wyposażony jest w głowicę, która odczytuje piksle z obrazu, przesuwając się po nim. Dane przetwarzane w trakcie działania programu są umieszczane na stosie.
34 | *
35 | * Sposób pisania kodu (a szczególnie algorytmów obliczeniowych) różni się bardzo znacząco od programowania w innych językach nie tylko z powodu iż Piet jest językiem graficznym. Najważniejszymi dwiema cechami egzekucji kodu są: [1] porównywanie sąsiednich kolorów w celu wyboru instrukcji do wykonania (za pomocą głowicy) oraz [2] tzw. bloki kolorów (w których sąsiadujące piksle mają ten sam kolor). Na kod Pieta należy patrzeć „całościowo”, ogarniając kształt całości obrazu, a nie tylko dowolne niewielkie fragmenty. To jest właśnie zasadnicza różnica w sposobie programowania między Pietem i językami imperatywnymi (a również Salvadorem). W uproszczeniu, egzekucja kodu imperatywnego może wyglądać tak: „podstaw wartość pod zmienną, następnie na jej podstawie oblicz kolejne wyrażenie i podstaw pod inną zmienną. Teraz, mając przygotowane wszystkie pomocnicze wartości, sprawdzamy jedną z nich: jeśli sprawdzana wartość jest dodatnia, wykonaj blok instrukcji nr 1, jeśli ujemna, wykonaj blok nr 2, jeśli zero, wyświetl komunikat”. W językach imperatywnych mamy ściśle określoną, liniową kolejność wykonywania instrukcji, łatwo nam ją kontrolować. W Piecie natomiast kierunek w którym przesunie się głowica (czyli kolejność wykonywania instrukcji) zależy od trzech czynników: [1] aktualnego kierunku ruchu głowicy, [2] kolorów po których porusza się głowica i [3] kształtu bloków kolorów. Sprawia to, że programowanie skomplikowanych algorytmów jest stosunkowo trudne.
36 | *
37 | */
38 |
39 | /**
40 | * Ustawia kolor czcionki konsoli Unix.
41 | * @param color liczba definiująca kolor czcionki pod konsolą (escape string)
42 | */
43 | void setConsoleColor(int color)
44 | {
45 | std::cout << "\033[" << color << "m";
46 | }
47 |
48 | /**
49 | * Wyświetla komunikat błędu na konsolę.
50 | * @param error tekst komunikatu błędu
51 | */
52 | void printFormattedError(std::string error)
53 | {
54 | setConsoleColor(31);
55 | std::cout << error << std::endl;
56 | setConsoleColor(0);
57 | }
58 |
59 | /**
60 | * Wyświetla standardowy komunikat na konsolę.
61 | * @param message tekst standardowego komunikatu
62 | */
63 | void printFormattedMessage(std::string message)
64 | {
65 | setConsoleColor(32);
66 | std::cout << message << std::endl;
67 | setConsoleColor(0);
68 | }
69 |
70 | /**
71 | * Wyświetla tekst powitalny programu.
72 | */
73 | void runWelcome()
74 | {
75 | setConsoleColor(33);
76 | std::cout << std::endl;
77 | std::cout << "Interpreter języka Piet" << std::endl;
78 | std::cout << "Załącznik do pracy magisterskiej:" << std::endl;
79 | std::cout << "\"Graficzne języki programowania na przykładzie języków Piet i Salvador\"" << std::endl;
80 | std::cout << "Tomasz Ducin, 2009" << std::endl;
81 | setConsoleColor(0);
82 | std::cout << std::endl;
83 | }
84 |
85 | /**
86 | * Wyświetla menu programu, prosi użytkownika o wybór zadania i zwraca ów wybór.
87 | * @return numer zadania wybrany przez użytkownika
88 | */
89 | int runMenu(PConsoleVirtualMachine *m)
90 | {
91 | std::cout << "wybierz opcję:" << std::endl;
92 | std::cout << "1. uruchom maszynę i wykonuj instrukcje krok po kroku" << std::endl;
93 | std::cout << "2. uruchom maszynę i wykonaj wszystkie instrukcje" << std::endl;
94 | std::cout << "3. włącz/wyłącz tryb gadatliwy (" << (m->isVerbose() ? "włączony" : "wyłączony" ) << ")" << std::endl;
95 | std::cout << "4. koniec" << std::endl;
96 |
97 | std::string answer;
98 | std::cout << std::endl << "> "; getline(std::cin, answer); std::cout << std::endl;
99 | while (!atoi(answer.c_str()))
100 | {
101 | std::cout << "> "; getline(std::cin, answer); std::cout << std::endl;
102 | }
103 | return atoi(answer.c_str());
104 | }
105 |
106 | /**
107 | * Główna procedura całej aplikacji. Wyświetla przywitanie, potem w pętli pobiera od użytkownika numer zadania i wykonuje je. Działanie programu zależy od decyzji użytkownika.
108 | */
109 | void runProgram(PConsoleVirtualMachine *m, std::stringstream &stream)
110 | {
111 | // wyświetlanie informacji o programie
112 | runWelcome();
113 | // zmienne robocze sterujące pracą programu
114 | int continued = 1, choice;
115 | int final_choice = 4;
116 | // główna pętla programu
117 | while (continued)
118 | {
119 | // wyświetlanie menu programu i pobranie odpowiedzi od użytkownika
120 | choice = runMenu(m);
121 | // wykonanie danego zadania w zależności od odpowiedzi użytkownika
122 | switch (choice)
123 | {
124 | case 1: // uruchom maszynę i wykonuj instrukcje krok po kroku
125 | if ( m->startMachine() ) {
126 | std::cout << "hit enter after each step" << std::endl << std::endl;
127 | std::string confirm_str;
128 | while (m->isRunning())
129 | {
130 | if ( m->executeSingleInstr() ) {
131 | std::cout << stream.str() << std::endl;
132 | stream.str("");
133 | printFormattedMessage("\r\ninstruction executed");
134 | } else {
135 | printFormattedError("instruction error");
136 | }
137 | getline(std::cin, confirm_str);
138 | }
139 | } else {
140 | printFormattedError("machine is not ready");
141 | }
142 | break;
143 | case 2: // uruchom maszynę i wykonaj wszystkie instrukcje
144 | if ( m->startMachine() ) {
145 | printFormattedMessage("maszyna uruchomiona");
146 | m->executeAllInstr();
147 | } else {
148 | printFormattedError("maszyna nie jest gotowa");
149 | }
150 | break;
151 | case 3: // włącz/wyłącz tryb gadatliwy
152 | m->toggleVerbosity();
153 | break;
154 | case 4: // koniec
155 | m->stopMachine();
156 | break;
157 | }
158 | continued = (choice != final_choice) && (m->isRunning() || m->isReady());
159 | }
160 | if (choice != final_choice)
161 | printFormattedMessage("\r\nPraca programu zakończona");
162 | else
163 | printFormattedError("Praca programu przerwana");
164 | }
165 |
166 | /**
167 | * Procedura wejściowa aplikacji, pośrednicząca z linią poleceń (wczytuje nazwę programu z tablicy parametrów). Tworzy wszystkie potrzebne zmienne i wywołuje runProgram().
168 | * @param argc liczba parametrów pobranych z komendy uruchamiającej program
169 | * @param argv tablica z wartościami parametrów pobranych z komendy uruchamiającej program
170 | */
171 | int main(int argc, char **argv)
172 | {
173 | if ( argc != 2 ) // źle wywołany program
174 | {
175 | printFormattedMessage("Podaj nazwę programu przez argument");
176 | return 1;
177 | }
178 | std::string program_path(argv[1]);
179 | std::ifstream fin(program_path.c_str());
180 | if ( !fin )
181 | {
182 | std::string message("Plik ");
183 | message.append(program_path.c_str()).append(" nie istnieje. Sprawdź przyczynę błędu i spróbuj ponownie");
184 | printFormattedMessage(message);
185 | return 2;
186 | }
187 | // tworzenie wirtualnej maszyny Pieta, odpalenie aplikacji, zniszczenie maszyny
188 | std::stringstream stream;
189 | PConsoleVirtualMachine *m = new PConsoleVirtualMachine(program_path.c_str(), stream);
190 | runProgram(m, stream);
191 | std::cout << stream.str() << std::endl;
192 | delete m;
193 | }
194 |
195 |
--------------------------------------------------------------------------------
/src/gui/machine_widget.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MachineWidget
4 |
5 |
6 |
7 | 0
8 | 0
9 | 600
10 | 320
11 |
12 |
13 |
14 |
15 | 600
16 | 320
17 |
18 |
19 |
20 |
21 | 600
22 | 320
23 |
24 |
25 |
26 | Virtual Machine
27 |
28 |
29 | -
30 |
31 |
32 | Program Source Image
33 |
34 |
35 |
-
36 |
37 |
38 | Browse...
39 |
40 |
41 |
42 |
43 |
44 |
45 | -
46 |
47 |
-
48 |
49 |
-
50 |
51 |
52 | State
53 |
54 |
55 |
-
56 |
57 |
-
58 |
59 |
60 | stop
61 |
62 |
63 |
64 | -
65 |
66 |
67 | start
68 |
69 |
70 |
71 | -
72 |
73 |
74 | restart
75 |
76 |
77 |
78 |
79 |
80 | -
81 |
82 |
-
83 |
84 |
85 | State:
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | -
102 |
103 |
104 | Pointer
105 |
106 |
107 |
-
108 |
109 |
-
110 |
111 |
112 | X:
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 |
121 |
122 |
123 | -
124 |
125 |
126 | Y:
127 |
128 |
129 |
130 | -
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | -
140 |
141 |
-
142 |
143 |
144 | CC:
145 |
146 |
147 |
148 | -
149 |
150 |
151 |
152 |
153 |
154 |
155 | -
156 |
157 |
158 | DP:
159 |
160 |
161 |
162 | -
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | -
175 |
176 |
177 | Instructions
178 |
179 |
180 |
-
181 |
182 |
183 | true
184 |
185 |
186 | >
187 |
188 |
189 |
190 | -
191 |
192 |
-
193 |
194 |
195 | true
196 |
197 |
198 | >>
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 | -
210 |
211 |
-
212 |
213 |
214 | Verbose
215 |
216 |
217 |
218 |
219 |
220 | -
221 |
222 |
223 | Output
224 |
225 |
226 |
-
227 |
228 |
229 |
230 | Courier 10 Pitch
231 | 10
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | -
242 |
243 |
244 |
245 | 60
246 | 16777215
247 |
248 |
249 |
250 | Data
251 |
252 |
253 |
-
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 | pushButtonBrowse
265 | clicked()
266 | MachineWidget
267 | chooseFile()
268 |
269 |
270 | 86
271 | 57
272 |
273 |
274 | 87
275 | 72
276 |
277 |
278 |
279 |
280 | pushButtonExecuteAllInstructions
281 | clicked()
282 | MachineWidget
283 | executeAllInstructions()
284 |
285 |
286 | 561
287 | 60
288 |
289 |
290 | 47
291 | 147
292 |
293 |
294 |
295 |
296 | pushButtonExecuteSingleInstruction
297 | clicked()
298 | MachineWidget
299 | executeSingleInstruction()
300 |
301 |
302 | 517
303 | 60
304 |
305 |
306 | 268
307 | 143
308 |
309 |
310 |
311 |
312 | checkBoxVerbose
313 | clicked(bool)
314 | MachineWidget
315 | toggleVerbosity(bool)
316 |
317 |
318 | 569
319 | 95
320 |
321 |
322 | 67
323 | 224
324 |
325 |
326 |
327 |
328 | pushButtonRestart
329 | clicked()
330 | MachineWidget
331 | restartMachine()
332 |
333 |
334 | 461
335 | 60
336 |
337 |
338 | 301
339 | 65
340 |
341 |
342 |
343 |
344 | pushButtonStart
345 | clicked()
346 | MachineWidget
347 | startMachine()
348 |
349 |
350 | 371
351 | 46
352 |
353 |
354 | 278
355 | 87
356 |
357 |
358 |
359 |
360 | pushButtonStop
361 | clicked()
362 | MachineWidget
363 | stopMachine()
364 |
365 |
366 | 316
367 | 51
368 |
369 |
370 | 277
371 | 114
372 |
373 |
374 |
375 |
376 |
377 | chooseFile()
378 | executeSingleInstruction()
379 | executeAllInstructions()
380 | toggleVerbosity(bool)
381 | startMachine()
382 | restartMachine()
383 | stopMachine()
384 |
385 |
386 |
--------------------------------------------------------------------------------
/src/core/p_block_manager.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_block_manager.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 | #include "p_code_pointer.h"
11 |
12 | // C++
13 | #include
14 |
15 | // STL
16 | // none
17 |
18 | // Qt
19 | #include
20 | #include
21 |
22 | /** \file pblockmanager.cpp
23 | * \brief Plik z kodem źródłowym klasy PBlockManager
24 | *
25 | * Plik zawiera kod źródłowy klasy PBlockManager.
26 | */
27 |
28 | /**
29 | * Konstruktor menadżera bloków. Pobiera informacje o obrazie z których będzie korzystał za każdym razem gdy wirtualna maszyna będzie chciała wykonać jakąkolwiek instrukcję. Ponadto, alokuje pamięć pod 2-wymiarową tablicę pomocniczą służącą do obliczania ilości kodeli w danym bloku koloru.
30 | */
31 | PBlockManager::PBlockManager(QImage *given_image, PCodePointer *given_pointer, std::stringstream &str) : stream(str)
32 | {
33 | debug("CONSTRUCTOR ----- block-manager START\n");
34 | verbose = false;
35 | image = given_image;
36 | pointer = given_pointer;
37 | height = image->height();
38 | width = image->width();
39 | allocateMultiArray();
40 | debug("CONSTRUCTOR ----- block-manager END\n");
41 | }
42 |
43 | /**
44 | * Destruktor menadżera bloków. Dealokouje pamięć przeznaczoną dla 2-wymiarowej tablicy pomocniczej służącej do obliczania ilości kodeli w danym bloku koloru.
45 | */
46 | PBlockManager::~PBlockManager()
47 | {
48 | debug("DESTRUCTOR ----- block-manager START\n");
49 | deallocateMultiArray();
50 | debug("DESTRUCTOR ----- block-manager END\n");
51 | }
52 |
53 | /**
54 | * Ustala tryb gadatliwy.
55 | * @param verbosity tryb gadatliwy
56 | */
57 | void PBlockManager::setVerbosity(bool verbosity)
58 | {
59 | verbose = verbosity;
60 | }
61 |
62 | //==================================================================
63 | // zarządzanie pomocniczą 2-wymiarową tablicą
64 |
65 | /**
66 | * Przydziela pamięć pod 2-wymiarową tablicę pomocniczą służącą do obliczenia ilości kodeli w bloku koloru. Metoda wywoływana tylko raz, w konstruktorze. Tablica ta, używana wielokrotnie, jest czyszczona, nie tworzy się jej od nowa przy każdym użyciu.
67 | */
68 | void PBlockManager::allocateMultiArray()
69 | {
70 | fields = new int *[height];
71 | for (int i=0; ipixel(seedPoint.x, seedPoint.y) == seedColor) { // aktualnie sprawdzany kodel spełnia warunek
122 | fields[seedPoint.y][seedPoint.x] = 1; // oznacz go '1' (że spełnia warunek)
123 |
124 | // i sprawdź jego wszystkie 4 sąsiednie punkty (pion, poziom, nie skos)
125 | // podstaw pod robocze zmienne współrzędne hipotetycznego kodela
126 | // sprawdź czy mieści się w rysunku i czy nie został już oznaczony
127 | // jeśli powyższe warunki spełnione, wywołaj rekursywnie tą samą metodę dla nowego kodela
128 |
129 | tmpPoint.x = seedPoint.x; tmpPoint.y = seedPoint.y + 1;
130 | if (!pointer->pointOutsideImage(tmpPoint) && fields[tmpPoint.y][tmpPoint.x] == 0) {
131 | reqCrawlMultiArray(seedColor, tmpPoint);
132 | }
133 |
134 | tmpPoint.x = seedPoint.x; tmpPoint.y = seedPoint.y - 1;
135 | if (!pointer->pointOutsideImage(tmpPoint) && fields[tmpPoint.y][tmpPoint.x] == 0) {
136 | reqCrawlMultiArray(seedColor, tmpPoint);
137 | }
138 |
139 | tmpPoint.x = seedPoint.x + 1; tmpPoint.y = seedPoint.y;
140 | if (!pointer->pointOutsideImage(tmpPoint) && fields[tmpPoint.y][tmpPoint.x] == 0) {
141 | reqCrawlMultiArray(seedColor, tmpPoint);
142 | }
143 |
144 | tmpPoint.x = seedPoint.x - 1; tmpPoint.y = seedPoint.y;
145 | if (!pointer->pointOutsideImage(tmpPoint) && fields[tmpPoint.y][tmpPoint.x] == 0) {
146 | reqCrawlMultiArray(seedColor, tmpPoint);
147 | }
148 | } else {
149 | fields[seedPoint.y][seedPoint.x] = 2; // oznacz, że kodel ma inny kolor niż zadany parametrem
150 | }
151 | }
152 |
153 | /**
154 | * Metoda zlicza liczbę kodeli w pomocniczej 2-wymiarowej tabeli (która została właśnie sprawdzona) oznaczonych '1', czyli kodeli spełniających warunek (ten sam kolor co kolor zadany).
155 | */
156 | void PBlockManager::countCodels()
157 | {
158 | int count = 0;
159 | for (int i=0; igetPointedPixel(), pointer->getCoordinates()); // rekursywne oznaczanie kodeli
183 | countCodels();
184 | findBorderCodels();
185 | }
186 |
187 | //==================================================================
188 |
189 | int PBlockManager::findRowMostLeftCodel(int row)
190 | {
191 | int column = 0;
192 | while ( fields[row][column] != 1 )
193 | column++;
194 | return column;
195 | }
196 |
197 | int PBlockManager::findRowMostRightCodel(int row)
198 | {
199 | int column = width - 1;
200 | while ( fields[row][column] != 1 )
201 | column--;
202 | return column;
203 | }
204 |
205 | int PBlockManager::findColumnTopCodel(int column)
206 | {
207 | int row = 0;
208 | while ( fields[row][column] != 1 )
209 | row++;
210 | return row;
211 | }
212 |
213 | int PBlockManager::findColumnBottomCodel(int column)
214 | {
215 | int row = height - 1;
216 | while ( fields[row][column] != 1 )
217 | row--;
218 | return row;
219 | }
220 |
221 | //
222 | void PBlockManager::findBorderCodels()
223 | {
224 | bool found = false;
225 | int h;
226 | for (int i=0; i border_right_codel) {
240 | border_right_codel = j;
241 | }
242 | }
243 | }
244 | }
245 | border_down_codel = h;
246 | }
247 |
248 | /**
249 | * Wyznacza współrzędne punktu sąsiadującego bloku kolorów, od którego przesunie się głowica przy aktualnych wartościach DP i CC.
250 | * @return współrzedne punktu
251 | */
252 | PPoint PBlockManager::getNextPossibleCodel()
253 | {
254 | PPoint new_point;
255 | PPoint actual_point = pointer->getCoordinates();
256 | // w zależności od wartości DIRECTION POINTER
257 | switch( pointer->getDirectionPointerValue() ) {
258 | // dla każdego z 4 kierunków sprawdź wartość CODEL CHOOSER
259 | // i na tej podstawie jednoznacznie określ nowego kodela (z następnego bloku)
260 | case dp_right:
261 | switch ( pointer->getCodelChooserValue() ) {
262 | case cc_left:
263 | // dp = prawo, cc = lewo, kierunek = skrajny górny
264 | new_point.y = findColumnTopCodel(border_right_codel);
265 | break;
266 | case cc_right:
267 | // dp = prawo, cc = prawo, kierunek = skrajny dolny
268 | new_point.y = findColumnBottomCodel(border_right_codel);
269 | break;
270 | }
271 | new_point.x = border_right_codel + 1;
272 | break;
273 | case dp_down:
274 | switch ( pointer->getCodelChooserValue() ) {
275 | case cc_left:
276 | // dp = dół, cc = lewo, kierunek = skrajny prawy
277 | new_point.x = findRowMostRightCodel(border_down_codel);
278 | break;
279 | case cc_right:
280 | // dp = dół, cc = prawo, kierunek = skrajny lewy
281 | new_point.x = findRowMostLeftCodel(border_down_codel);
282 | break;
283 | }
284 | new_point.y = border_down_codel + 1;
285 | break;
286 | case dp_left:
287 | switch ( pointer->getCodelChooserValue() ) {
288 | case cc_left:
289 | // dp = lewo, cc = lewo, kierunek = skrajny dolny
290 | new_point.y = findColumnBottomCodel(border_left_codel);
291 | break;
292 | case cc_right:
293 | // dp = lewo, cc = prawo, kierunek = skrajny górny
294 | new_point.y = findColumnTopCodel(border_left_codel);
295 | break;
296 | }
297 | new_point.x = border_left_codel - 1;
298 | break;
299 | case dp_up:
300 | switch ( pointer->getCodelChooserValue() ) {
301 | case cc_left:
302 | // dp = góra, cc = lewo, kierunek = skrajny lewy
303 | new_point.x = findRowMostLeftCodel(border_up_codel);
304 | break;
305 | case cc_right:
306 | // dp = góra, cc = prawo, kierunek = skrajny prawy
307 | new_point.x = findRowMostRightCodel(border_up_codel);
308 | break;
309 | }
310 | new_point.y = border_up_codel - 1;
311 | break;
312 | }
313 | return new_point;
314 | }
315 |
316 | //==================================================================
317 |
318 | /**
319 | * METODA TESTOWA. Metoda wyświetla na stdout 2-wymiarową tablicę pomocniczą.
320 | */
321 | void PBlockManager::__dev__showMultiArray()
322 | {
323 | for (int i=0; i
2 |
3 |
4 |
5 | umbrello uml modeller http://uml.sf.net
6 | 1.5.8
7 | UnicodeUTF8
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/src/core/p_virtual_machine.cpp:
--------------------------------------------------------------------------------
1 | //// includes
2 |
3 | // header file
4 | #include "p_virtual_machine.h"
5 |
6 | // piet core
7 | #include "../debug.h"
8 | #include "p_enums.h"
9 | #include "p_structs.h"
10 | #include "p_console.h"
11 | #include "p_calc_stack.h"
12 |
13 | // C++
14 | #include
15 |
16 | // STL
17 | // none
18 |
19 | // Qt
20 | #include
21 | #include
22 |
23 | /** \file pvirtualmachine.cpp
24 | * \brief Plik z kodem źródłowym klasy PVirtualMachine
25 | *
26 | * Plik zawiera kod źródłowy klasy PVirtualMachine.
27 | */
28 |
29 | /**
30 | * Konstruktor maszyny wirtualnej interpretującej dowolny program w języku Piet. Tworzy wszystkie pomocnicze obiekty których działanie jest wykorzystywane i koordynowane przez wirtualną maszynę.
31 | */
32 | PVirtualMachine::PVirtualMachine(const char * filename, std::stringstream &str) : stream(str)
33 | {
34 | debug("CONSTRUCTOR - virtual-machine START\n");
35 |
36 | verbose = false;
37 |
38 | // stworzenie obiektu obrazu kodu, po którym będzie poruszać się głowica
39 |
40 | image = new QImage(filename);
41 |
42 | // punkt współrzędnych początkowych - oraz stworzenie głowicy poruszającej się po powyższym obrazie
43 | PPoint initial;
44 | initial.x = initial.y = 0;
45 | pointer = new PCodePointer(image, initial);
46 |
47 | // obiekt odpowiedzialny za geometryczną interpretację bloków kolorów
48 | block_manager = new PBlockManager(image, pointer, str);
49 |
50 | // obiekt przetwarzający wszystko związane z kolorami
51 | color_manager = new PColorManager(str);
52 |
53 | // stos przechowujący tymczasowe wartości
54 | stack = new PCalcStack();
55 |
56 | // obiekt odpowiedzialny za wczytywanie i wyświetlanie danych od użytkownika
57 | console = new PConsole(str);
58 |
59 | // przygotowanie maszyny do uruchomienia ("wyzerowanie")
60 | prepareToExecute();
61 |
62 | debug("CONSTRUCTOR - virtual-machine END\n");
63 | }
64 |
65 | /**
66 | * Destruktor wirtualnej maszyny Pieta. Wywołuje destruktory dla pomocniczych obiektów tworzonych w konstruktorze wirtualnej maszyny.
67 | */
68 | PVirtualMachine::~PVirtualMachine()
69 | {
70 | debug("DESTRUCTOR - virtual-machine START\n");
71 | // likwidacja kolejnych pomocniczych obiektów używanych przez wirtualną maszynę
72 | delete image;
73 | delete pointer;
74 | delete block_manager;
75 | delete color_manager;
76 | delete stack;
77 | delete console;
78 | debug("DESTRUCTOR - virtual-machine END\n");
79 | }
80 |
81 | /** \brief Przygotowanie do uruchomienia/zresetowania wirtualnej maszyny
82 | *
83 | * Metoda używana w celu przygotowania wirtualnej maszyny do uruchomienia. Maszyna mogła być w trakcie działania, mogła zakończyć działanie lub mogła być gotowa do uruchomienia.
84 | */
85 | void PVirtualMachine::prepareToExecute()
86 | {
87 | stack->clear();
88 | pointer->clear();
89 | setState(state_ready);
90 | step = 0;
91 | }
92 |
93 | //=============================================================================
94 |
95 | /** \brief zwraca stan wirtualnej maszyny Salvadora
96 | *
97 | * W każdej chwili istnienia, wirtualna maszyna Pieta musi znajdować się w jakimś stanie (PMachineStates). Metoda zwraca aktualny stan wirtualnej maszyny.
98 | */
99 | PMachineStates PVirtualMachine::getState()
100 | {
101 | return state;
102 | }
103 |
104 | /** \brief ustawia stan wirtualnej maszyny Salvadora
105 | *
106 | * W każdej chwili istnienia, wirtualna maszyna Pieta musi znajdować się w jakimś stanie (PMachineStates). Metoda ustawia stan wirtualnej maszyny.
107 | * \param state stan jaki zostanie przypisany wirtualnej maszynie
108 | */
109 | void PVirtualMachine::setState(PMachineStates state)
110 | {
111 | this->state = state;
112 | }
113 |
114 | /**
115 | * Sprawdza czy maszyna jest gotowa do rozpoczęcia pracy (sprawdzany stan maszyny).
116 | * @return czy maszyna jest gotowa do uruchomienia
117 | */
118 | bool PVirtualMachine::isReady()
119 | {
120 | return (state == state_ready);
121 | }
122 |
123 | /**
124 | * Sprawdza czy maszyna pracuje (sprawdzany stan maszyny).
125 | * @return czy maszyna pracuje
126 | */
127 | bool PVirtualMachine::isRunning()
128 | {
129 | return (state == state_running);
130 | }
131 |
132 | /**
133 | * Sprawdza czy maszyna zakończyła działanie (sprawdzany stan maszyny).
134 | * @return czy maszyna zakończyła działanie
135 | */
136 | bool PVirtualMachine::isFinished()
137 | {
138 | return (state == state_finished);
139 | }
140 |
141 | //=========================================================
142 |
143 | /**
144 | * Uruchamia maszynę (ustawia odpowiedni stan).
145 | * @return czy operacja się powiodła
146 | */
147 | bool PVirtualMachine::startMachine()
148 | {
149 | if (isReady()) {
150 | setState(state_running);
151 | return true;
152 | } else {
153 | return false;
154 | }
155 | }
156 |
157 | /**
158 | * Restartuje maszynę (ustawia odpowiedni stan).
159 | * @return czy operacja się powiodła
160 | */
161 | bool PVirtualMachine::restartMachine()
162 | {
163 | prepareToExecute();
164 | return true;
165 | }
166 |
167 | /**
168 | * Zatrzymuje maszynę (ustawia odpowiedni stan).
169 | * @return czy operacja się powiodła
170 | */
171 | bool PVirtualMachine::stopMachine()
172 | {
173 | if (isRunning()) {
174 | setState(state_finished);
175 | return true;
176 | } else {
177 | return false;
178 | }
179 | }
180 |
181 | //=========================================================
182 |
183 | void PVirtualMachine::setVerbosityRecursively(bool verbosity)
184 | {
185 | verbose = verbosity;
186 | console->setVerbosity(verbosity);
187 | color_manager->setVerbosity(verbosity);
188 | block_manager->setVerbosity(verbosity);
189 | stack->setVerbosity(verbosity);
190 | pointer->setVerbosity(verbosity);
191 | }
192 |
193 | /**
194 | * Sprawdza, czy maszyna ma włączony tryb gadatliwy
195 | * @return tryb gadatliwy
196 | */
197 | bool PVirtualMachine::isVerbose()
198 | {
199 | return verbose;
200 | }
201 |
202 | /**
203 | * Przełącza tryb gadatliwy na przeciwny. Przełącza tryb we wszystkich podrzędnych obiektach.
204 | */
205 | void PVirtualMachine::toggleVerbosity()
206 | {
207 | if (verbose) {
208 | setVerbosityRecursively(false);
209 | } else {
210 | setVerbosityRecursively(true);
211 | }
212 | }
213 |
214 | void PVirtualMachine::setVerbosity(bool verbose)
215 | {
216 | setVerbosityRecursively(verbose);
217 | }
218 |
219 | //=========================================================
220 |
221 | std::list::iterator PVirtualMachine::calc_stack_begin_iterator()
222 | {
223 | return stack->begin_iterator();
224 | }
225 |
226 | std::list::iterator PVirtualMachine::calc_stack_end_iterator()
227 | {
228 | return stack->end_iterator();
229 | }
230 |
231 | //=========================================================
232 |
233 | const QImage* PVirtualMachine::getImage() const
234 | {
235 | return this->image;
236 | }
237 |
238 | //=========================================================
239 |
240 | /**
241 | * Wykonuje WSZYSTKIE instrukcje aż do zakończenia pracy programu. Jeśli tryb gadatliwy został uprzednio włączony, wszystkie informacje o przebeigu pracy są wyświetlane.
242 | */
243 | void PVirtualMachine::executeAllInstr()
244 | {
245 | if (verbose) {
246 | __dev__printImageInfo();
247 | }
248 | while ( isRunning() ) {
249 | executeSingleInstr();
250 | }
251 | }
252 |
253 | /**
254 | * Wykonuje POJEDYNCZĄ instrukcję aż do zakończenia pracy programu. Jeśli tryb gadatliwy został uprzednio włączony, wszystkie informacje o przebeigu pracy są wyświetlane.
255 | */
256 | bool PVirtualMachine::executeSingleInstr()
257 | {
258 | if (verbose) {
259 | stream << std::endl << "krok:" << step << "; ";
260 | __dev__printConsole();
261 | }
262 | bool result = true; // czy operacja została wykonana
263 | int ivar;
264 | if ( isRunning() ) {
265 | PInstructions instruction = movePointerAndGetInstructionToExecute();
266 | if (verbose) {
267 | stream << "instr: " << PEnums::instruction(instruction) << std::endl;
268 | }
269 | // w zależności od tego jaką instrukcję zwróci maszyna kodu
270 | switch(instruction)
271 | {
272 | // wykonaj inną operację używając stosu
273 | case pietInstr_special_empty:
274 | // pusta instrukcja - głowica przesunięta po białym bloku
275 | break;
276 | case pietInstr_stack_push:
277 | stack->instrPush( block_manager->getCodelBlockCount() ); // połóż na stosie liczbę równą liczbie kodeli w bloku kolorów wskazywanym aktualnie przez głowicę
278 | break;
279 | case pietInstr_stack_pop:
280 | if (stack->hasAtLeastNElements(1)) {
281 | ivar = stack->instrPop(); // zdejmuje ze stosu liczbę (i nic z nią nie robi)
282 | } else {
283 | result = false;
284 | }
285 | break;
286 | case pietInstr_arithm_add:
287 | if (stack->hasAtLeastNElements(2)) {
288 | stack->instrAdd(); // zdejmuje 2 szczytowe elementy i odkłada ich sumę
289 | } else {
290 | result = false;
291 | }
292 | break;
293 | case pietInstr_arithm_subtract:
294 | if (stack->hasAtLeastNElements(2)) {
295 | stack->instrSubtract(); // zdejmuje 2 szczytowe elementy i odkłada ich różnicę
296 | } else {
297 | result = false;
298 | }
299 | break;
300 | case pietInstr_arithm_multiply:
301 | if (stack->hasAtLeastNElements(2)) {
302 | stack->instrMultiply(); // zdejmuje 2 szczytowe elementy i odkłada ich iloczyn
303 | } else {
304 | result = false;
305 | }
306 | break;
307 | case pietInstr_arithm_divide:
308 | if (stack->hasAtLeastNElements(2)) {
309 | stack->instrDivide(); // zdejmuje 2 szczytowe elementy i odkłada ich iloraz
310 | } else {
311 | result = false;
312 | }
313 | break;
314 | case pietInstr_arithm_modulo:
315 | if (stack->hasAtLeastNElements(2)) {
316 | stack->instrModulo(); // zdejmuje 2 szczytowe elementy i odkłada resztę z ich dzielenia
317 | } else {
318 | result = false;
319 | }
320 | break;
321 | case pietInstr_logic_not:
322 | if (stack->hasAtLeastNElements(1)) {
323 | stack->instrNot(); // zdejmuje element szczytowy i odkłada 1 (el = 0) lub 0 (el != 0)
324 | } else {
325 | result = false;
326 | }
327 | break;
328 | case pietInstr_logic_greater:
329 | if (stack->hasAtLeastNElements(2)) {
330 | stack->instrGreater(); // zdejmuje 2 szczytowe elementy i odkłada 1 (jeśli ostatni większy) lub 0 (przeciwnie)
331 | } else {
332 | result = false;
333 | }
334 | break;
335 | case pietInstr_runtime_pointer:
336 | if (stack->hasAtLeastNElements(1)) {
337 | for (int num = stack->instrPop(); num > 0; num--)
338 | pointer->toggleDirectionPointer();
339 | } else {
340 | result = false;
341 | }
342 | break;
343 | case pietInstr_runtime_switch:
344 | if (stack->hasAtLeastNElements(1)) {
345 | if (stack->instrPop() % 2)
346 | pointer->toggleCodelChooser();
347 | } else {
348 | result = false;
349 | }
350 | break;
351 | case pietInstr_stack_duplicate:
352 | if (stack->hasAtLeastNElements(1)) {
353 | stack->instrDuplicate();
354 | } else {
355 | result = false;
356 | }
357 | break;
358 | case pietInstr_stack_roll:
359 | if (stack->hasAtLeastNElements(2)) {
360 | stack->instrRoll();
361 | } else {
362 | result = false;
363 | }
364 | break;
365 | case pietInstr_io_in_number:
366 | readNumber();
367 | break;
368 | case pietInstr_io_in_char:
369 | readChar();
370 | break;
371 | case pietInstr_io_out_number:
372 | if (stack->hasAtLeastNElements(1)) {
373 | console->printNumber(stack->instrPop());
374 | } else {
375 | result = false;
376 | }
377 | break;
378 | case pietInstr_io_out_char:
379 | if (stack->hasAtLeastNElements(1)) {
380 | console->printChar(stack->instrPop());
381 | } else {
382 | result = false;
383 | }
384 | break;
385 | case pietInstr_special_terminate:
386 | // 8 nieudanych prób przesunięcia głowicy do następnego kodela kończy pracę interpretera
387 | if ( !stopMachine() ) {
388 | stream << "ERROR: bool PVirtualMachine::executeSingleInstr()" << std::endl;
389 | exit(1);
390 | }
391 | break;
392 | default:
393 | stream << "ERROR: bool PVirtualMachine::executeSingleInstr()" << std::endl;
394 | exit(1);
395 | }
396 | } else {
397 | result = false;
398 | }
399 | step++;
400 | return result;
401 | }
402 |
403 | //==================================================================
404 |
405 | /**
406 | * Sprawdza, czy wskazany punkt jest koloru czarnego lub się znajduje poza granicami obrazu kodu. Jeśli tak, głowica będzie musiała zmienić swoje DP i/lub CC. Wirtualna maszyna wykorzystuje do tego głowicę obrazu kodu oraz menadżera kolorów.
407 | * @param point wskazany punkt
408 | * @return czy punkt jest czarny lub poza granicami obrazu kodu
409 | */
410 | bool PVirtualMachine::pointIsBlackOrOutside(PPoint point)
411 | {
412 | bool black = false, outside = pointer->pointOutsideImage(point);
413 | if (!outside) {
414 | black = (color_manager->getColorName(pointer->getPixel(point)) == color_black );
415 | }
416 | return ( outside || black );
417 | }
418 |
419 | /**
420 | * Sprawdza, czy wskazany punkt jest koloru białego. Jeśli tak, to jeśli głowica dodatkowo prześlizgnie się przez biały blok, nie wykona w tym krokużadnej operacji. Wirtualna maszyna wykorzystuje do tego głowicę obrazu kodu oraz menadżera kolorów.
421 | * @param point wskazany punkt
422 | * @return czy punkt jest biały
423 | */
424 | bool PVirtualMachine::pointIsWhite(PPoint point)
425 | {
426 | return (color_manager->getColorName(pointer->getPixel(point)) == color_white );
427 | }
428 |
429 | /**
430 | * Przesuwa głowicę o jeden kodel przez biały blok. Metoda wywoływana wielokrotnie przez metodę slideAcrossWhiteBlock().
431 | */
432 | void PVirtualMachine::slidePointerAcrossWhiteBlock()
433 | {
434 | while (color_manager->getColorName(pointer->getPointedPixel()) == color_white)
435 | switch (pointer->getDirectionPointerValue()) {
436 | case dp_right:
437 | pointer->incCoordinateX();
438 | break;
439 | case dp_down:
440 | pointer->incCoordinateY();
441 | break;
442 | case dp_left:
443 | pointer->decCoordinateX();
444 | break;
445 | case dp_up:
446 | pointer->decCoordinateY();
447 | break;
448 | }
449 | }
450 |
451 | /**
452 | * Przesuwa głowicę, uwzględniając jej wartości DP i CC, na koniec białego bloku (parametr point, przekazywany przez zmienną - ulega zmianie w trakcie wykonywania operacji). Następnie wirtualna maszyna bada, czy otrzymany punkt znajduje się poza obrazem kodu lub jest czarny (wtedy głowica zmienia wartości DP i/lub CC i być może ponownie będzie wędrowała z wyjściowego punktu przez biały blok).
453 | * @param point wskazany punkt
454 | */
455 | void PVirtualMachine::slideAcrossWhiteBlock(PPoint &point)
456 | {
457 | while ( (!pointer->pointOutsideImage(point)) && (color_manager->getColorName(pointer->getPixel(point)) == color_white) )
458 | switch (pointer->getDirectionPointerValue()) {
459 | case dp_right:
460 | point.x++;
461 | break;
462 | case dp_down:
463 | point.y++;
464 | break;
465 | case dp_left:
466 | point.x--;
467 | break;
468 | case dp_up:
469 | point.y--;
470 | break;
471 | }
472 | }
473 |
474 | /**
475 | * Metoda nakazuje przesunięcie głowicy oraz wyznacza jaka instrukcja ma zostać wykonana (wszystko wykorzystując pomocnicze obiekty wirtualnej maszyny). Jedna z ważniejszych i bardziej skomplikowanych metod całego interpretera.
476 | */
477 | PInstructions PVirtualMachine::movePointerAndGetInstructionToExecute()
478 | {
479 | PInstructions result_instr; // robocza zmienna wynikowa
480 | PPoint possible_point; // nowy, szukany kodel na który ma zostać przesunięta głowica
481 | QRgb old_color = pointer->getPointedPixel(); // kolor pierwotnego kodela, czyli wskazywanego przez głowicę przed jej przesunięciem
482 | block_manager->searchAndFillCodels(); // oblicza liczbę kodeli bloku koloru w którym się znajduje kodel wskazywany przez głowicę
483 | bool isWhite = false, isBlack;
484 |
485 | if (verbose)
486 | block_manager->__dev__showCountAndBorderCodels();
487 |
488 | int attempts = 0; // licznik prób wykonania przez głowicę ruchu (patrz: specyfikacja, "czarne bloki i granice") Jeśli po 8 próbach nie uda się wykonać ruchu, program kończy działanie.
489 | bool continued = true; // zmienna sterująca pętlą
490 | while (continued) {
491 | isBlack = isWhite = false; // odznaczenie informacji na początek każdego obrotu pętli (odświeżenie)
492 | possible_point = block_manager->getNextPossibleCodel(); // wyznacz hipotetyczny nowy kodel
493 | if (verbose) {
494 | stream << "try:" << attempts << "[" << possible_point.x << "," << possible_point.y << "]; ";
495 | }
496 |
497 | if ( pointIsBlackOrOutside(possible_point) ) {
498 | isBlack = true;
499 | } else if ( pointIsWhite(possible_point) ) {
500 | slideAcrossWhiteBlock(possible_point);
501 | isWhite = true;
502 | if ( pointIsBlackOrOutside(possible_point) ) {
503 | isBlack = true;
504 | }
505 | }
506 |
507 | if (isBlack) {
508 | // nie udało się
509 | attempts++;
510 | if (attempts % 2) {
511 | pointer->toggleCodelChooser();
512 | } else {
513 | pointer->toggleDirectionPointer();
514 | }
515 | continued = (attempts < 8);
516 | } else {
517 | pointer->setCoordinates(possible_point);
518 | if (verbose)
519 | stream << "new:[" << possible_point.x << "," << possible_point.y << "]" << "; ";
520 | continued = false;
521 | }
522 | }
523 | // pętla zerwana - albo przesunięto głowicę albo program zakończony, poniżej selekcja
524 | if (attempts == 8) {
525 | result_instr = pietInstr_special_terminate; // zakończenie programu, 8 nieudanych prób
526 | } else if (isWhite) {
527 | result_instr = pietInstr_special_empty;
528 | } else { // głowica została przesunięta
529 | QRgb new_color = pointer->getPointedPixel(); // odczytanie koloru kodelu wskazywanego przez głowicę po przesunięciu
530 | result_instr = getInstructionByIndex( color_manager->getInstructionIndex(old_color, new_color) ); // interpretacja instrukcji do wykonanai na podstawie kolorów kodeli - starego i nowego
531 | }
532 | return result_instr; // zwrócenie wyniku (instrukcji do wykonania)
533 | }
534 |
535 | //==================================================================
536 |
537 | /**
538 | * Zwraca instrukcję Pieta (element enumeracji) dla zadanego indeksu instrukcji Pieta.
539 | * @param index indeks instrukcji Pieta
540 | * @return instrukcja Pieta
541 | */
542 | PInstructions PVirtualMachine::getInstructionByIndex(int index)
543 | {
544 | switch(index) {
545 | case 0:
546 | return pietInstr_special_empty;
547 | case 1:
548 | return pietInstr_stack_push;
549 | case 2:
550 | return pietInstr_stack_pop;
551 | case 3:
552 | return pietInstr_arithm_add;
553 | case 4:
554 | return pietInstr_arithm_subtract;
555 | case 5:
556 | return pietInstr_arithm_multiply;
557 | case 6:
558 | return pietInstr_arithm_divide;
559 | case 7:
560 | return pietInstr_arithm_modulo;
561 | case 8:
562 | return pietInstr_logic_not;
563 | case 9:
564 | return pietInstr_logic_greater;
565 | case 10:
566 | return pietInstr_runtime_pointer;
567 | case 11:
568 | return pietInstr_runtime_switch;
569 | case 12:
570 | return pietInstr_stack_duplicate;
571 | case 13:
572 | return pietInstr_stack_roll;
573 | case 14:
574 | return pietInstr_io_in_number;
575 | case 15:
576 | return pietInstr_io_in_char;
577 | case 16:
578 | return pietInstr_io_out_number;
579 | case 17:
580 | return pietInstr_io_out_char;
581 | case 18:
582 | return pietInstr_special_terminate;
583 | default:
584 | stream << "ERROR: PInstructions PVirtualMachine::getInstructionByIndex(int index)" << std::endl;
585 | exit(1);
586 | }
587 | }
588 |
589 | PPoint PVirtualMachine::getCodePointerCoordinates()
590 | {
591 | return pointer->getCoordinates();
592 | }
593 |
594 | PDirectionPointerValues PVirtualMachine::getDirectionPointer()
595 | {
596 | return pointer->getDirectionPointerValue();
597 | }
598 |
599 | PCodelChooserValues PVirtualMachine::getCodelChooser()
600 | {
601 | return pointer->getCodelChooserValue();
602 | }
603 |
604 | /**
605 | * METODA TESTOWA. Wyświetla informacje o obrazie kodu.
606 | */
607 | void PVirtualMachine::__dev__printImageInfo()
608 | {
609 | stream << std::endl << "CODE IMAGE/ " << "[" << image->width() << "x" << image->height() << "]" << std::endl;
610 | }
611 |
612 | /**
613 | * METODA TESTOWA. Wyświetla informacje o całej maszynie i jej elementach składowych.
614 | */
615 | void PVirtualMachine::__dev__printConsole()
616 | {
617 | stream << "CODE POINTER/";
618 |
619 | PPoint coords = pointer->getCoordinates();
620 | stream << "[" << coords.x << "," << coords.y << "]";
621 |
622 | PDirectionPointerValues dp = pointer->getDirectionPointerValue();
623 | stream << "DP:" << PEnums::directionPointer(dp) << "(" << (int) dp << ")";
624 |
625 | PCodelChooserValues cc = pointer->getCodelChooserValue();
626 | stream << "CC:" << PEnums::codelChooser(cc) << "(" << (int) cc << ")";
627 |
628 | stream << std::endl << "DATA STACK/";
629 | stream << "rozm:" << stack->size() << " elem: ";
630 | for (std::list::iterator it = stack->begin_iterator(); it != stack->end_iterator(); ++it) {
631 | stream << *it << " ";
632 | }
633 | stream << std::endl;
634 | }
635 |
--------------------------------------------------------------------------------