├── doc ├── classes.png └── classes.xmi ├── images ├── programs │ ├── fib.png │ ├── pi.png │ ├── 2toN.png │ ├── adder.png │ ├── alpha.png │ ├── hello1.png │ ├── hello2.png │ ├── hello3.png │ ├── hello4.png │ ├── hello5.png │ ├── hello6.png │ ├── power.png │ ├── prime.png │ ├── proof.png │ ├── umcs.png │ ├── 99bottles.png │ ├── factorial.png │ └── hellomondrian.png └── traces │ ├── pi-trace.png │ ├── 2toN-trace.png │ ├── fib-trace.png │ ├── umcs-trace.png │ ├── adder-trace.png │ ├── alpha-trace.png │ ├── hello1-trace.png │ ├── hello2-trace.png │ ├── hello3-trace.png │ ├── hello4-trace.png │ ├── hello5-trace.png │ ├── hello6-trace.png │ ├── power-trace.png │ ├── prime-trace.png │ ├── proof-trace.png │ ├── 99bottles-trace.png │ ├── factorial-trace.png │ └── hellomondrian-trace.png ├── src ├── gui │ ├── images │ │ ├── quickopen.png │ │ ├── help-contents.png │ │ ├── application-exit.png │ │ └── view-form-action.png │ ├── images.qrc │ ├── main.cpp │ ├── child_window.cpp │ ├── child_window.h │ ├── main_window.h │ ├── gui.pro │ ├── p_gui_virtual_machine.h │ ├── program_image_widget.h │ ├── CMakeLists.txt │ ├── main_window.cpp │ ├── machine_widget.h │ ├── p_gui_virtual_machine.cpp │ ├── program_image_widget.cpp │ ├── program_image_widget.ui │ ├── main_window.ui │ ├── machine_widget.cpp │ └── machine_widget.ui ├── CMakeLists.txt ├── core │ ├── CMakeLists.txt │ ├── p_structs.h │ ├── p_console_virtual_machine.cpp │ ├── p_console_virtual_machine.h │ ├── p_console.h │ ├── p_color_manager.h │ ├── p_console.cpp │ ├── p_calc_stack.h │ ├── p_code_pointer.h │ ├── p_block_manager.h │ ├── p_enums.cpp │ ├── p_virtual_machine.h │ ├── p_enums.h │ ├── p_color_manager.cpp │ ├── p_code_pointer.cpp │ ├── p_calc_stack.cpp │ ├── p_block_manager.cpp │ └── p_virtual_machine.cpp ├── debug.h └── console.cpp ├── .travis.yml ├── .gitignore ├── TODO.md ├── CMakeLists.txt └── README.md /doc/classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/doc/classes.png -------------------------------------------------------------------------------- /images/programs/fib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/fib.png -------------------------------------------------------------------------------- /images/programs/pi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/pi.png -------------------------------------------------------------------------------- /images/programs/2toN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/2toN.png -------------------------------------------------------------------------------- /images/programs/adder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/adder.png -------------------------------------------------------------------------------- /images/programs/alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/alpha.png -------------------------------------------------------------------------------- /images/programs/hello1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello1.png -------------------------------------------------------------------------------- /images/programs/hello2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello2.png -------------------------------------------------------------------------------- /images/programs/hello3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello3.png -------------------------------------------------------------------------------- /images/programs/hello4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello4.png -------------------------------------------------------------------------------- /images/programs/hello5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello5.png -------------------------------------------------------------------------------- /images/programs/hello6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hello6.png -------------------------------------------------------------------------------- /images/programs/power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/power.png -------------------------------------------------------------------------------- /images/programs/prime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/prime.png -------------------------------------------------------------------------------- /images/programs/proof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/proof.png -------------------------------------------------------------------------------- /images/programs/umcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/umcs.png -------------------------------------------------------------------------------- /images/traces/pi-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/pi-trace.png -------------------------------------------------------------------------------- /images/traces/2toN-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/2toN-trace.png -------------------------------------------------------------------------------- /images/traces/fib-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/fib-trace.png -------------------------------------------------------------------------------- /images/traces/umcs-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/umcs-trace.png -------------------------------------------------------------------------------- /src/gui/images/quickopen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/src/gui/images/quickopen.png -------------------------------------------------------------------------------- /images/programs/99bottles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/99bottles.png -------------------------------------------------------------------------------- /images/programs/factorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/factorial.png -------------------------------------------------------------------------------- /images/traces/adder-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/adder-trace.png -------------------------------------------------------------------------------- /images/traces/alpha-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/alpha-trace.png -------------------------------------------------------------------------------- /images/traces/hello1-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello1-trace.png -------------------------------------------------------------------------------- /images/traces/hello2-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello2-trace.png -------------------------------------------------------------------------------- /images/traces/hello3-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello3-trace.png -------------------------------------------------------------------------------- /images/traces/hello4-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello4-trace.png -------------------------------------------------------------------------------- /images/traces/hello5-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello5-trace.png -------------------------------------------------------------------------------- /images/traces/hello6-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hello6-trace.png -------------------------------------------------------------------------------- /images/traces/power-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/power-trace.png -------------------------------------------------------------------------------- /images/traces/prime-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/prime-trace.png -------------------------------------------------------------------------------- /images/traces/proof-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/proof-trace.png -------------------------------------------------------------------------------- /images/programs/hellomondrian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/programs/hellomondrian.png -------------------------------------------------------------------------------- /images/traces/99bottles-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/99bottles-trace.png -------------------------------------------------------------------------------- /images/traces/factorial-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/factorial-trace.png -------------------------------------------------------------------------------- /src/gui/images/help-contents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/src/gui/images/help-contents.png -------------------------------------------------------------------------------- /src/gui/images/application-exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/src/gui/images/application-exit.png -------------------------------------------------------------------------------- /src/gui/images/view-form-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/src/gui/images/view-form-action.png -------------------------------------------------------------------------------- /images/traces/hellomondrian-trace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/piet/HEAD/images/traces/hellomondrian-trace.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE(${QT_USE_FILE}) 2 | ADD_DEFINITIONS(${QT_DEFINITIONS}) 3 | 4 | ADD_SUBDIRECTORY(core) 5 | ADD_SUBDIRECTORY(gui) 6 | 7 | ADD_EXECUTABLE(piet-console console.cpp) 8 | TARGET_LINK_LIBRARIES(piet-console PietCore) -------------------------------------------------------------------------------- /src/gui/images.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/application-exit.png 4 | images/help-contents.png 5 | images/quickopen.png 6 | images/view-form-action.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_LIBRARY(PietCore 2 | p_enums.cpp 3 | p_block_manager.cpp 4 | p_calc_stack.cpp 5 | p_code_pointer.cpp 6 | p_color_manager.cpp 7 | p_console.cpp 8 | p_virtual_machine.cpp 9 | p_console_virtual_machine.cpp) 10 | 11 | TARGET_LINK_LIBRARIES(PietCore ${QT_LIBRARIES}) 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | 6 | install: 7 | - sudo apt-get update 8 | - sudo apt-get install libqt4-dev qt4-qmake 9 | - sudo apt-get install cmake 10 | 11 | script: mkdir build && cd build && cmake .. && make 12 | 13 | notifications: 14 | email: 15 | - tomasz.ducin@gmail.com 16 | -------------------------------------------------------------------------------- /src/gui/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "main_window.h" 3 | 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication app(argc, argv); 9 | app.setOrganizationName("Tomasz Ducin"); 10 | app.setApplicationName("Application Example"); 11 | MainWindow w; 12 | w.show(); 13 | 14 | return app.exec(); 15 | } 16 | -------------------------------------------------------------------------------- /src/gui/child_window.cpp: -------------------------------------------------------------------------------- 1 | #include "child_window.h" 2 | 3 | #include 4 | 5 | #include "machine_widget.h" 6 | 7 | ChildWindow::ChildWindow(QWidget *parent) : 8 | QMdiSubWindow(parent) 9 | { 10 | machineWidget = new MachineWidget(this); 11 | this->setWidget(machineWidget); 12 | } 13 | 14 | ChildWindow::~ChildWindow() 15 | { 16 | delete machineWidget; 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDEs 2 | *.kdev4 3 | .project 4 | .cproject 5 | *~ 6 | 7 | # Documentation 8 | doc/output 9 | 10 | # Compilation output 11 | build 12 | src/gui-build-desktop 13 | src/gui/gui.pro.user 14 | 15 | # Compiled Object files 16 | *.slo 17 | *.lo 18 | *.o 19 | 20 | # Compiled Dynamic libraries 21 | *.so 22 | *.dylib 23 | 24 | # Compiled Static libraries 25 | *.lai 26 | *.la 27 | *.a 28 | -------------------------------------------------------------------------------- /src/gui/child_window.h: -------------------------------------------------------------------------------- 1 | #ifndef CHILD_WINDOW_H 2 | #define CHILD_WINDOW_H 3 | 4 | #include "machine_widget.h" 5 | 6 | namespace Ui { 7 | class ChildWindow; 8 | } 9 | 10 | class ChildWindow : public QMdiSubWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit ChildWindow(QWidget *parent = 0); 16 | ~ChildWindow(); 17 | 18 | private: 19 | MachineWidget *machineWidget; 20 | }; 21 | 22 | #endif // CHILD_WINDOW_H 23 | -------------------------------------------------------------------------------- /src/gui/main_window.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_WINDOW_H 2 | #define MAIN_WINDOW_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class MainWindow; 8 | } 9 | 10 | class MainWindow : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit MainWindow(QWidget *parent = 0); 16 | ~MainWindow(); 17 | 18 | public slots: 19 | void openChildWindow(); 20 | void displayAbout(); 21 | 22 | private: 23 | Ui::MainWindow *ui; 24 | }; 25 | 26 | #endif // MAIN_WINDOW_H 27 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * PVM: throw/handle exceptions inside constructor (file doesn't exist, file is not an image or image corrupted) 2 | * PVM: add steps count field (how many steps were made) 3 | * PVM: constructor takes filename string parameter 4 | * provide an interface (abstract class) for all Qt-related operations (to make PVM independent on library used) 5 | * docs: pol -> eng 6 | * P[GUI]VM - virtual method: when the VM state changes, it should emit a signal to be caught by machine_widget (this will trigger GUI state update) -------------------------------------------------------------------------------- /src/core/p_structs.h: -------------------------------------------------------------------------------- 1 | #ifndef P_STRUCTS 2 | #define P_STRUCTS 3 | 4 | /** \file pstructs.h 5 | * \brief Plik nagłówkowy z definicjami rekordów 6 | * 7 | * Plik nagłówkowy zawiera wszystkie definicje rekordów które są wykorzystywane w projekcie. 8 | */ 9 | 10 | /** 11 | * Struktura reprezentująca punkt (a w zasadzie tylko jego współrzędne) na pewnym obrazie. 12 | */ 13 | typedef struct struct_point { 14 | /** Odcięta (współrzędna) punktu. */ int x; 15 | /** Rzędna (współrzędna) punktu. */ int y; 16 | } PPoint; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef P_DEBUG 2 | #define P_DEBUG 3 | 4 | /** \file debug.h 5 | * \brief Plik nagłówkowy debuggera 6 | * 7 | * Plik zawiera makro definiujące operacje debuggera. 8 | */ 9 | 10 | /** 11 | * Procedura wykorzystywana w fazie implementowania aplikacji: do kontroli pamięci, kolejności operacji itp. Gdy aplikacja jest funkcjonalna, procedura nie jest już używana. 12 | */ 13 | #ifdef DEBUG 14 | #define debug(...) do { \ 15 | fprintf(stderr, __VA_ARGS__); \ 16 | } while(false) 17 | #else 18 | #define debug(...) 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/core/p_console_virtual_machine.cpp: -------------------------------------------------------------------------------- 1 | //// includes 2 | 3 | // header file 4 | #include "p_console_virtual_machine.h" 5 | 6 | // piet core 7 | #include "../debug.h" 8 | 9 | // C++ 10 | // none 11 | 12 | // STL 13 | // none 14 | 15 | // Qt 16 | // none 17 | 18 | /** \file pconsolevirtualmachine.cpp 19 | * \brief Plik z kodem źródłowym klasy PConsoleVirtualMachine 20 | * 21 | * Plik zawiera kod źródłowy klasy PConsoleVirtualMachine. 22 | */ 23 | 24 | PConsoleVirtualMachine::PConsoleVirtualMachine(const char * filepath, std::stringstream &str) 25 | : PVirtualMachine(filepath, str) 26 | { 27 | } 28 | 29 | void PConsoleVirtualMachine::readNumber() 30 | { 31 | stack->instrPush(console->readNumber()); 32 | } 33 | 34 | void PConsoleVirtualMachine::readChar() 35 | { 36 | stack->instrPush(console->readChar()); 37 | } 38 | -------------------------------------------------------------------------------- /src/gui/gui.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2013-01-25T23:40:41 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | TARGET = gui 10 | TEMPLATE = app 11 | 12 | LIBS += ../../build/src/core/libPietCore.a 13 | INCLUDEPATH += ../core 14 | 15 | SOURCES += \ 16 | main.cpp\ 17 | main_window.cpp \ 18 | child_window.cpp \ 19 | machine_widget.cpp \ 20 | program_image_widget.cpp \ 21 | p_gui_virtual_machine.cpp 22 | 23 | HEADERS += \ 24 | main_window.h \ 25 | child_window.h \ 26 | machine_widget.h \ 27 | program_image_widget.h \ 28 | p_gui_virtual_machine.h 29 | 30 | FORMS += \ 31 | main_window.ui \ 32 | machine_widget.ui \ 33 | program_image_widget.ui 34 | 35 | RESOURCES += \ 36 | images.qrc 37 | -------------------------------------------------------------------------------- /src/gui/p_gui_virtual_machine.h: -------------------------------------------------------------------------------- 1 | #ifndef P_GUI_VIRTUAL_MACHINE 2 | #define P_GUI_VIRTUAL_MACHINE 3 | 4 | #include 5 | 6 | #include "p_virtual_machine.h" 7 | 8 | /** \file p_gui_virtual_machine.h 9 | * \brief plik nagłówkowy klasy PGuiVirtualMachine 10 | * 11 | * Plik nagłówkowy zawiera definicję klasy PGuiVirtualMachine. 12 | */ 13 | 14 | /** \brief Wirtualna maszyna Pieta dla aplikacji desktopowych 15 | * 16 | * Implementacja "wirtualnej maszyny Pieta" dla aplikacji desktopowych. 17 | */ 18 | class PGuiVirtualMachine : public PVirtualMachine { 19 | 20 | public: 21 | PGuiVirtualMachine(const char *, std::stringstream& ); 22 | 23 | protected: 24 | bool validateNumber(int); 25 | virtual void readNumber(); 26 | 27 | bool validateChar(QString); 28 | virtual void readChar(); 29 | 30 | public slots: 31 | void inputSubmitted(); 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/core/p_console_virtual_machine.h: -------------------------------------------------------------------------------- 1 | #ifndef P_CONSOLE_VIRTUAL_MACHINE 2 | #define P_CONSOLE_VIRTUAL_MACHINE 3 | 4 | //// includes 5 | 6 | // piet core 7 | #include "p_virtual_machine.h" 8 | 9 | // C++ 10 | // none 11 | 12 | // STL 13 | // none 14 | 15 | // Qt 16 | // none 17 | 18 | /** \file pconsolevirtualmachine.h 19 | * \brief plik nagłówkowy klasy PConsoleVirtualMachine 20 | * 21 | * Plik nagłówkowy zawiera definicję klasy PConsoleVirtualMachine. 22 | */ 23 | 24 | /** \brief Wirtualna maszyna Pieta dla aplikacji konsolowych 25 | * 26 | * Implementacja "wirtualnej maszyny Pieta" dla aplikacji konsolowych. 27 | */ 28 | class PConsoleVirtualMachine : public PVirtualMachine { 29 | 30 | public: 31 | 32 | PConsoleVirtualMachine(const char *, std::stringstream& ); 33 | 34 | protected: 35 | 36 | virtual void readNumber(); 37 | virtual void readChar(); 38 | 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/gui/program_image_widget.h: -------------------------------------------------------------------------------- 1 | #ifndef PROGRAM_IMAGE_WIDGET_H 2 | #define PROGRAM_IMAGE_WIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "p_gui_virtual_machine.h" 10 | 11 | namespace Ui { 12 | class ProgramImageWidget; 13 | } 14 | 15 | class ProgramImageWidget : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit ProgramImageWidget(QWidget *parent = 0); 21 | ~ProgramImageWidget(); 22 | 23 | void setPiet(PGuiVirtualMachine *); 24 | void render(); 25 | 26 | private: 27 | float getZoomSize(); 28 | PGuiVirtualMachine *piet; 29 | 30 | public slots: 31 | void zoomIn(); 32 | void zoomOut(); 33 | 34 | private: 35 | Ui::ProgramImageWidget *ui; 36 | 37 | bool image_created; 38 | 39 | QGraphicsScene *scene; 40 | signed char zoom_scale; 41 | }; 42 | 43 | #endif // PROGRAM_IMAGE_WIDGET_H 44 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.2) 2 | 3 | PROJECT(piet) 4 | 5 | FIND_PACKAGE(Qt4 REQUIRED) 6 | 7 | ADD_SUBDIRECTORY(src) 8 | 9 | # generating documentation with Doxygen 10 | find_package(Doxygen) 11 | if(DOXYGEN_FOUND) 12 | set(DOXYGEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/doc) 13 | set(DOXYGEN_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) 14 | configure_file(${DOXYGEN_DIR}/Doxyfile.in ${DOXYGEN_CONFIG} @ONLY) 15 | add_custom_target(doc 16 | ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG} 17 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 18 | COMMENT "Generating API documentation with Doxygen" VERBATIM) 19 | execute_process(COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_CONFIG} 20 | OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/doxygen.exec.log" 21 | ERROR_FILE "${CMAKE_CURRENT_BINARY_DIR}/doxygen.error.log") 22 | else(DOXYGEN_FOUND) 23 | message(STATUS "Documentation could not be generated") 24 | endif(DOXYGEN_FOUND) 25 | 26 | -------------------------------------------------------------------------------- /src/core/p_console.h: -------------------------------------------------------------------------------- 1 | #ifndef P_CONSOLE 2 | #define P_CONSOLE 3 | 4 | //// includes 5 | 6 | // piet core 7 | #include "p_enums.h" 8 | #include "p_structs.h" 9 | 10 | // C++ 11 | #include 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 | [![Build Status](https://travis-ci.org/ducin/piet.png?branch=master)](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 | 42 | 43 | 44 | 0 45 | 0 46 | 800 47 | 21 48 | 49 | 50 | 51 | 52 | Help 53 | 54 | 55 | 56 | 57 | 58 | File 59 | 60 | 61 | 62 | 63 | 64 | 65 | 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 | --------------------------------------------------------------------------------