From ad71cf95462aa8cc98c0c5185f429af2f748b566 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Tue, 26 Mar 2024 12:41:26 +0800 Subject: [PATCH 01/14] add cgml-demos, add cgml-py to dependencies --- compiler/CGML.py | 8 ++ examples/CyberiadaFormat-Autoborder.graphml | 113 ++++++++++++++++++ examples/CyberiadaFormat-Blinker.graphml | 79 ++++++++++++ examples/{ => old}/(old)testSchema.json | 0 .../Autoborder_638213644305392731.graphml | 0 examples/{ => old}/Berloga.graphml | 0 .../{ => old}/ExampleSketch/ExampleSketch.ino | 0 .../{ => old}/MonoFileExample/cpp_example.cpp | 0 examples/{ => old}/MultifilesExample/foo.cpp | 0 examples/{ => old}/MultifilesExample/foo.hpp | 0 examples/{ => old}/MultifilesExample/main.cpp | 0 examples/{ => old}/MultifilesExample/main.o | Bin examples/{ => old}/arduino-blinker.json | 0 .../{ => old}/bearlogaSchemas/Autoborder.json | 0 .../Autoborder_638330223036439120.graphml | 0 .../Autoborder_638330223036439121.json | 0 .../BearlogaDefend-Autoborder.json | 0 .../BearlogaDefend-Generator.json | 0 .../BearlogaDefend-Smoker.json | 0 .../BearlogaDefend-Stapler.json | 0 .../Generator_638331191524332730.graphml | 0 .../Smoker_638331191988353340.graphml | 0 .../Stapler_638331190677085090.graphml | 0 .../{ => old}/ideExamples/digitalOut.json | 0 examples/{ => old}/testAnalogIn.json | 0 examples/{ => old}/testAnalogOut.json | 0 examples/{ => old}/testCounter.json | 0 examples/{ => old}/testDigitalIn.json | 0 examples/{ => old}/testDigitalOut.json | 0 examples/{ => old}/testPWM.json | 0 examples/{ => old}/testSerial.json | 0 examples/{ => old}/testSerial2.json | 0 examples/{ => old}/testShiftOut.json | 0 examples/{ => old}/testTimer.json | 0 poetry.lock | 19 ++- pyproject.toml | 3 +- requirements.txt | 12 -- test/test_client.py | 28 ++--- 38 files changed, 233 insertions(+), 29 deletions(-) create mode 100644 compiler/CGML.py create mode 100644 examples/CyberiadaFormat-Autoborder.graphml create mode 100644 examples/CyberiadaFormat-Blinker.graphml rename examples/{ => old}/(old)testSchema.json (100%) rename examples/{ => old}/Autoborder_638213644305392731.graphml (100%) rename examples/{ => old}/Berloga.graphml (100%) rename examples/{ => old}/ExampleSketch/ExampleSketch.ino (100%) rename examples/{ => old}/MonoFileExample/cpp_example.cpp (100%) rename examples/{ => old}/MultifilesExample/foo.cpp (100%) rename examples/{ => old}/MultifilesExample/foo.hpp (100%) rename examples/{ => old}/MultifilesExample/main.cpp (100%) rename examples/{ => old}/MultifilesExample/main.o (100%) rename examples/{ => old}/arduino-blinker.json (100%) rename examples/{ => old}/bearlogaSchemas/Autoborder.json (100%) rename examples/{ => old}/bearlogaSchemas/Autoborder_638330223036439120.graphml (100%) rename examples/{ => old}/bearlogaSchemas/Autoborder_638330223036439121.json (100%) rename examples/{ => old}/bearlogaSchemas/BearlogaDefend-Autoborder.json (100%) rename examples/{ => old}/bearlogaSchemas/BearlogaDefend-Generator.json (100%) rename examples/{ => old}/bearlogaSchemas/BearlogaDefend-Smoker.json (100%) rename examples/{ => old}/bearlogaSchemas/BearlogaDefend-Stapler.json (100%) rename examples/{ => old}/bearlogaSchemas/Generator_638331191524332730.graphml (100%) rename examples/{ => old}/bearlogaSchemas/Smoker_638331191988353340.graphml (100%) rename examples/{ => old}/bearlogaSchemas/Stapler_638331190677085090.graphml (100%) rename examples/{ => old}/ideExamples/digitalOut.json (100%) rename examples/{ => old}/testAnalogIn.json (100%) rename examples/{ => old}/testAnalogOut.json (100%) rename examples/{ => old}/testCounter.json (100%) rename examples/{ => old}/testDigitalIn.json (100%) rename examples/{ => old}/testDigitalOut.json (100%) rename examples/{ => old}/testPWM.json (100%) rename examples/{ => old}/testSerial.json (100%) rename examples/{ => old}/testSerial2.json (100%) rename examples/{ => old}/testShiftOut.json (100%) rename examples/{ => old}/testTimer.json (100%) delete mode 100644 requirements.txt diff --git a/compiler/CGML.py b/compiler/CGML.py new file mode 100644 index 0000000..0b97c69 --- /dev/null +++ b/compiler/CGML.py @@ -0,0 +1,8 @@ +"""Module for work with CyberiadaMl.""" +from cyberiadaml_py.cyberiadaml_parser import CGMLParser +from fullgraphmlparser.stateclasses import StateMachine + + +def parse(xml: str) -> StateMachine: + parser = CGMLParser() + parser.parseCGML(xml) \ No newline at end of file diff --git a/examples/CyberiadaFormat-Autoborder.graphml b/examples/CyberiadaFormat-Autoborder.graphml new file mode 100644 index 0000000..f07a84c --- /dev/null +++ b/examples/CyberiadaFormat-Autoborder.graphml @@ -0,0 +1,113 @@ + + + +Cyberiada-GraphML + + + + + + + + + + + + + + BearlogaDefend + name/ Автобортник +author/ Матросов В.М. +contact/ matrosov@mail.ru +description/ Пример описания схемы, +который может быть многострочным, потому что так удобнее +unit/ Autoborder + + + + + Бой + entry/ +exit/ + + really important information + + + + Сближение + entry/ +МодульДвижения.ДвигатьсяКЦели() + +exit/ + + + + + Атака + entry/ +ОружиеЦелевое.АтаковатьЦель() + +exit/ + + + + + + + Скан + entry/ +Сенсор.ПоискВрагаПоДистанции(мин) + +exit/ +Сенсор.ОстановкаПоиска() + + + + + + + + + dasdasd + + + + + + #c81afd + АнализаторЦели.ЦельУничтожена/ + + + + + #438048 + АнализаторЦели.ЦельПотеряна/ + + + + + #df2db6 + Сенсор.ЦельПолучена/ + + + + + #f450c8 + ОружиеЦелевое.ЦельВошлаВЗонуАтаки/ + + + + + #7517fe + ОружиеЦелевое.ЦельВышлаИзЗоныАтаки/ + + + + + + \ No newline at end of file diff --git a/examples/CyberiadaFormat-Blinker.graphml b/examples/CyberiadaFormat-Blinker.graphml new file mode 100644 index 0000000..ff05b9e --- /dev/null +++ b/examples/CyberiadaFormat-Blinker.graphml @@ -0,0 +1,79 @@ + + + +Cyberiada-GraphML + + + + + + + + + + + ArduinoUno + name/ Arduino-Blinker +description/ Включение и выключение лампочки по таймеру + + + + + + + + + + LED1 + type/ LED +name/ Светодиод +description/ Встроенный в плату светодиод, чтобы им мигать +pin/ 12 + + + + + timer1 + type/ Timer +name/ Светодиод +description/ Программный таймер. + + + + + Включен + entry/ +LED1.on() +timer1.start(1000) + + + + + + Выключен + entry/ +LED1.off() +timer1.start(1000) + + + + + + + + + timer1.timeout/ + #F29727 + + + + + timer1.timeout/ + + #F24C3D + + + + diff --git a/examples/(old)testSchema.json b/examples/old/(old)testSchema.json similarity index 100% rename from examples/(old)testSchema.json rename to examples/old/(old)testSchema.json diff --git a/examples/Autoborder_638213644305392731.graphml b/examples/old/Autoborder_638213644305392731.graphml similarity index 100% rename from examples/Autoborder_638213644305392731.graphml rename to examples/old/Autoborder_638213644305392731.graphml diff --git a/examples/Berloga.graphml b/examples/old/Berloga.graphml similarity index 100% rename from examples/Berloga.graphml rename to examples/old/Berloga.graphml diff --git a/examples/ExampleSketch/ExampleSketch.ino b/examples/old/ExampleSketch/ExampleSketch.ino similarity index 100% rename from examples/ExampleSketch/ExampleSketch.ino rename to examples/old/ExampleSketch/ExampleSketch.ino diff --git a/examples/MonoFileExample/cpp_example.cpp b/examples/old/MonoFileExample/cpp_example.cpp similarity index 100% rename from examples/MonoFileExample/cpp_example.cpp rename to examples/old/MonoFileExample/cpp_example.cpp diff --git a/examples/MultifilesExample/foo.cpp b/examples/old/MultifilesExample/foo.cpp similarity index 100% rename from examples/MultifilesExample/foo.cpp rename to examples/old/MultifilesExample/foo.cpp diff --git a/examples/MultifilesExample/foo.hpp b/examples/old/MultifilesExample/foo.hpp similarity index 100% rename from examples/MultifilesExample/foo.hpp rename to examples/old/MultifilesExample/foo.hpp diff --git a/examples/MultifilesExample/main.cpp b/examples/old/MultifilesExample/main.cpp similarity index 100% rename from examples/MultifilesExample/main.cpp rename to examples/old/MultifilesExample/main.cpp diff --git a/examples/MultifilesExample/main.o b/examples/old/MultifilesExample/main.o similarity index 100% rename from examples/MultifilesExample/main.o rename to examples/old/MultifilesExample/main.o diff --git a/examples/arduino-blinker.json b/examples/old/arduino-blinker.json similarity index 100% rename from examples/arduino-blinker.json rename to examples/old/arduino-blinker.json diff --git a/examples/bearlogaSchemas/Autoborder.json b/examples/old/bearlogaSchemas/Autoborder.json similarity index 100% rename from examples/bearlogaSchemas/Autoborder.json rename to examples/old/bearlogaSchemas/Autoborder.json diff --git a/examples/bearlogaSchemas/Autoborder_638330223036439120.graphml b/examples/old/bearlogaSchemas/Autoborder_638330223036439120.graphml similarity index 100% rename from examples/bearlogaSchemas/Autoborder_638330223036439120.graphml rename to examples/old/bearlogaSchemas/Autoborder_638330223036439120.graphml diff --git a/examples/bearlogaSchemas/Autoborder_638330223036439121.json b/examples/old/bearlogaSchemas/Autoborder_638330223036439121.json similarity index 100% rename from examples/bearlogaSchemas/Autoborder_638330223036439121.json rename to examples/old/bearlogaSchemas/Autoborder_638330223036439121.json diff --git a/examples/bearlogaSchemas/BearlogaDefend-Autoborder.json b/examples/old/bearlogaSchemas/BearlogaDefend-Autoborder.json similarity index 100% rename from examples/bearlogaSchemas/BearlogaDefend-Autoborder.json rename to examples/old/bearlogaSchemas/BearlogaDefend-Autoborder.json diff --git a/examples/bearlogaSchemas/BearlogaDefend-Generator.json b/examples/old/bearlogaSchemas/BearlogaDefend-Generator.json similarity index 100% rename from examples/bearlogaSchemas/BearlogaDefend-Generator.json rename to examples/old/bearlogaSchemas/BearlogaDefend-Generator.json diff --git a/examples/bearlogaSchemas/BearlogaDefend-Smoker.json b/examples/old/bearlogaSchemas/BearlogaDefend-Smoker.json similarity index 100% rename from examples/bearlogaSchemas/BearlogaDefend-Smoker.json rename to examples/old/bearlogaSchemas/BearlogaDefend-Smoker.json diff --git a/examples/bearlogaSchemas/BearlogaDefend-Stapler.json b/examples/old/bearlogaSchemas/BearlogaDefend-Stapler.json similarity index 100% rename from examples/bearlogaSchemas/BearlogaDefend-Stapler.json rename to examples/old/bearlogaSchemas/BearlogaDefend-Stapler.json diff --git a/examples/bearlogaSchemas/Generator_638331191524332730.graphml b/examples/old/bearlogaSchemas/Generator_638331191524332730.graphml similarity index 100% rename from examples/bearlogaSchemas/Generator_638331191524332730.graphml rename to examples/old/bearlogaSchemas/Generator_638331191524332730.graphml diff --git a/examples/bearlogaSchemas/Smoker_638331191988353340.graphml b/examples/old/bearlogaSchemas/Smoker_638331191988353340.graphml similarity index 100% rename from examples/bearlogaSchemas/Smoker_638331191988353340.graphml rename to examples/old/bearlogaSchemas/Smoker_638331191988353340.graphml diff --git a/examples/bearlogaSchemas/Stapler_638331190677085090.graphml b/examples/old/bearlogaSchemas/Stapler_638331190677085090.graphml similarity index 100% rename from examples/bearlogaSchemas/Stapler_638331190677085090.graphml rename to examples/old/bearlogaSchemas/Stapler_638331190677085090.graphml diff --git a/examples/ideExamples/digitalOut.json b/examples/old/ideExamples/digitalOut.json similarity index 100% rename from examples/ideExamples/digitalOut.json rename to examples/old/ideExamples/digitalOut.json diff --git a/examples/testAnalogIn.json b/examples/old/testAnalogIn.json similarity index 100% rename from examples/testAnalogIn.json rename to examples/old/testAnalogIn.json diff --git a/examples/testAnalogOut.json b/examples/old/testAnalogOut.json similarity index 100% rename from examples/testAnalogOut.json rename to examples/old/testAnalogOut.json diff --git a/examples/testCounter.json b/examples/old/testCounter.json similarity index 100% rename from examples/testCounter.json rename to examples/old/testCounter.json diff --git a/examples/testDigitalIn.json b/examples/old/testDigitalIn.json similarity index 100% rename from examples/testDigitalIn.json rename to examples/old/testDigitalIn.json diff --git a/examples/testDigitalOut.json b/examples/old/testDigitalOut.json similarity index 100% rename from examples/testDigitalOut.json rename to examples/old/testDigitalOut.json diff --git a/examples/testPWM.json b/examples/old/testPWM.json similarity index 100% rename from examples/testPWM.json rename to examples/old/testPWM.json diff --git a/examples/testSerial.json b/examples/old/testSerial.json similarity index 100% rename from examples/testSerial.json rename to examples/old/testSerial.json diff --git a/examples/testSerial2.json b/examples/old/testSerial2.json similarity index 100% rename from examples/testSerial2.json rename to examples/old/testSerial2.json diff --git a/examples/testShiftOut.json b/examples/old/testShiftOut.json similarity index 100% rename from examples/testShiftOut.json rename to examples/old/testShiftOut.json diff --git a/examples/testTimer.json b/examples/old/testTimer.json similarity index 100% rename from examples/testTimer.json rename to examples/old/testTimer.json diff --git a/poetry.lock b/poetry.lock index 08278fd..b7a4541 100644 --- a/poetry.lock +++ b/poetry.lock @@ -399,6 +399,21 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "cyberiadaml-py" +version = "0.1.1" +description = "The Python 3 library for processing the CyberiadaML state machine graphs" +optional = false +python-versions = "<3.11,>=3.10" +files = [ + {file = "cyberiadaml_py-0.1.1-py3-none-any.whl", hash = "sha256:742577da1fe7c0d921bb1020edd9ada63a5bd480e5c5b4243cc009a9fdaa3a92"}, + {file = "cyberiadaml_py-0.1.1.tar.gz", hash = "sha256:b95e6708578306af52940ab7ff20cce9f217c1550b4d75ac9938220658558a34"}, +] + +[package.dependencies] +pydantic = ">=2.6.1,<3.0.0" +xmltodict = ">=0.13.0,<0.14.0" + [[package]] name = "exceptiongroup" version = "1.2.0" @@ -1131,5 +1146,5 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" -python-versions = "^3.10" -content-hash = "dd5600874685863889e370ed4daf447e3e14487564c340f6e97542fc9b96884e" +python-versions = ">=3.10,<3.11" +content-hash = "d3a368e5e1caf749b63a67004258b018ed2cd7ea0444a758a185a56a5753ab93" diff --git a/pyproject.toml b/pyproject.toml index 87d5f94..e9ccfc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ license = "GNU General Public License v3.0" readme = "README.md" [tool.poetry.dependencies] -python = "^3.10" +python = ">=3.10,<3.11" aiofile = "3.8.7" aiofiles = "23.1.0" aiohttp = "3.8.4" @@ -17,6 +17,7 @@ aioshutil =" 1.3" asyncjson = "0.0.1" pydantic = "^2.5.2" xmltodict = "^0.13.0" +cyberiadaml-py = "^0.1.1" [tool.poetry.group.dev.dependencies] flake8 = "^6.1.0" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 2d21a34..0000000 --- a/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -aiofile==3.8.7 -aiofiles==23.1.0 -aiohttp==3.8.4 -aiologger==0.7.0 -aiopath==0.6.11 -aioshutil==1.3 -asyncjson==0.0.1 -clang==16.0.1.1 -lxml==4.9.2 -pytest==7.3.2 -pytest-asyncio==0.21.0 -xmltodict==0.13.0 diff --git a/test/test_client.py b/test/test_client.py index df4a4a4..d5d959a 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -26,7 +26,7 @@ def getPath(): # client = Client() # await client.doConnect(f'{BASE_ADDR}/source') # req = await client.sendMultiFileProject( -# 'examples/MultifilesExample', +# 'examples/old/MultifilesExample', # 'g++', # ['-std=c++2a'], # ['*.cpp', '*.hpp'] @@ -54,7 +54,7 @@ def getPath(): # client = Client() # await client.doConnect(f'{BASE_ADDR}/source') # req = await client.sendMultiFileProject( -# '../examples/ExampleSketch/', +# '../examples/old/ExampleSketch/', # 'arduino-cli', # ['-b', 'arduino:avr:uno', 'ExampleSketch.ino'], # ['*.ino']) @@ -79,7 +79,7 @@ async def test_berlogaImport(): client = Client() await client.doConnect(f'{BASE_ADDR}/berloga/import') # response = await client.importBerlogaScheme('compiler/schemas/Autoborder_with_actions.graphml') - response = await client.importBerlogaScheme('examples/bearlogaSchemas/Autoborder_638330223036439120.graphml', 'Autoborder_12314124') + response = await client.importBerlogaScheme('examples/old/bearlogaSchemas/Autoborder_638330223036439120.graphml', 'Autoborder_12314124') print(response) path = 'client/' + strftime('%Y-%m-%d %H:%M:%S', gmtime()) + str(random.randint(0, 10000)) + '/' @@ -112,7 +112,7 @@ async def test_berlogaExport(): async def test_timerSchema(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testTimer.json') + response = await client.sendSMJson('examples/old/testTimer.json') print(response) dirname = strftime('%Y-%m-%d %H:%M:%S', gmtime()) path = getPath() @@ -135,7 +135,7 @@ async def test_timerSchema(): async def test_counterSchema(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testCounter.json') + response = await client.sendSMJson('examples/old/testCounter.json') print(response) path = getPath() build_path = path + '/build/' @@ -163,7 +163,7 @@ async def test_counterSchema(): async def test_Serial(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testSerial.json') + response = await client.sendSMJson('examples/old/testSerial.json') print(response) path = getPath() build_path = path + '/build/' @@ -191,7 +191,7 @@ async def test_Serial(): async def test_Serial2(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testSerial2.json') + response = await client.sendSMJson('examples/old/testSerial2.json') print(response) dirname = strftime('%Y-%m-%d %H:%M:%S', gmtime()) path = getPath() @@ -220,7 +220,7 @@ async def test_Serial2(): async def test_PWM(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testPWM.json') + response = await client.sendSMJson('examples/old/testPWM.json') print(response) path = getPath() build_path = path + '/build/' @@ -248,7 +248,7 @@ async def test_PWM(): async def test_digitalOut(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testDigitalOut.json') + response = await client.sendSMJson('examples/old/testDigitalOut.json') print(response) path = getPath() build_path = path + '/build/' @@ -276,7 +276,7 @@ async def test_digitalOut(): async def test_digitalIn(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testDigitalIn.json') + response = await client.sendSMJson('examples/old/testDigitalIn.json') print(response) path = getPath() build_path = path + '/build/' @@ -305,7 +305,7 @@ async def test_digitalIn(): async def test_blinker(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/arduino-blinker.json') + response = await client.sendSMJson('examples/old/arduino-blinker.json') print(response) path = getPath() build_path = path + '/build/' @@ -333,7 +333,7 @@ async def test_blinker(): async def test_analogOut(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testAnalogOut.json') + response = await client.sendSMJson('examples/old/testAnalogOut.json') print(response) path = getPath() build_path = path + '/build/' @@ -361,7 +361,7 @@ async def test_analogOut(): async def test_analogIn(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testAnalogIn.json') + response = await client.sendSMJson('examples/old/testAnalogIn.json') print(response) path = getPath() build_path = path + '/build/' @@ -389,7 +389,7 @@ async def test_analogIn(): async def test_ShiftOut(): client = Client() await client.doConnect(BASE_ADDR) - response = await client.sendSMJson('examples/testShiftOut.json') + response = await client.sendSMJson('examples/old/testShiftOut.json') print(response) path = getPath() build_path = path + '/build/' From 28547a3a5501878088962f062ccc84745e481bb6 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Tue, 26 Mar 2024 14:33:40 +0800 Subject: [PATCH 02/14] new platform types --- compiler/platforms/Arduino.json | 470 ++++++++++++++++++ .../{schemas => platforms}/Autoborder.json | 0 compiler/{schemas => platforms}/Berloga.json | 0 .../{schemas => platforms}/Generator.json | 0 compiler/{schemas => platforms}/Smoker.json | 0 compiler/{schemas => platforms}/Stapler.json | 0 .../{schemas => platforms}/berlogaScheme.json | 0 compiler/schemas/Arduino.json | 428 ---------------- compiler/types/ide_types.py | 3 - compiler/types/platform_types.py | 71 ++- test/test_cgml.py | 50 ++ 11 files changed, 569 insertions(+), 453 deletions(-) create mode 100644 compiler/platforms/Arduino.json rename compiler/{schemas => platforms}/Autoborder.json (100%) rename compiler/{schemas => platforms}/Berloga.json (100%) rename compiler/{schemas => platforms}/Generator.json (100%) rename compiler/{schemas => platforms}/Smoker.json (100%) rename compiler/{schemas => platforms}/Stapler.json (100%) rename compiler/{schemas => platforms}/berlogaScheme.json (100%) delete mode 100644 compiler/schemas/Arduino.json create mode 100644 test/test_cgml.py diff --git a/compiler/platforms/Arduino.json b/compiler/platforms/Arduino.json new file mode 100644 index 0000000..cfbeeec --- /dev/null +++ b/compiler/platforms/Arduino.json @@ -0,0 +1,470 @@ +{ + "name": "Arduino Uno", + "description": "Платформа для программирования микроконтроллера Arduino Uno. Включает в себя компоненты для взаимодействия с кнопками, светодиодами, Serial и другими элементами, которые могут понадобиться в процессе.\n Соберите схему, запрограммируйте Arduino Uno и насладитесь результатом вашей работы!", + "icon": "путь/до/иконки", + "staticComponents": false, + "language": "C++", + "author": "Maxim Klypin", + "visual": true, + "compile": true, + "compilingSettings": { + "compiler": "arduino-cli", + "flags": ["-b", "avr:arduino:uno"] + }, + "components": { + "Button": { + "description": "Компонент для взаимодействия с физической кнопкой", + "img": "arduino/button.svg", + "signals": { + "isPressed": { + "img": "arduino/isPressed.svg", + "description": "Создает сигнал, если кнопка была нажата", + "checkMethod": "isPressed" + }, + "clicked": { + "img": "arduino/clicked.svg", + "description": "Создает сигнал, если кнопка была кликнута", + "checkMethod": "clicked" + } + }, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, к которому подключена кнопка" + }, + "buttonMode": { + "type": "uint8_t", + "description": "buttonMode indicates BUTTON_PULLUP or BUTTON_PULLDOWN resistor", + "optional": true + } + }, + "variables": { + "value": { + "img": "common/value.svg", + "type": "int", + "description": "Текущее значение на пине" + } + }, + "buildFiles": ["Button.h", "Button.ino"], + "importFiles": ["Button.h"], + "methods": {}, + "singletone": false + }, + + "LED": { + "description": "Компонент для взаимодействия со светодиодом", + "img": "arduino/led.svg", + "signals": {}, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, к которому подключен светодиод" + } + }, + "variables": { + "value": { + "img": "common/value.svg", + "type": "int", + "description": "Текущее значение на пине" + } + }, + "methods": { + "on": { + "img": "arduino/switch-on.svg", + "description": "Зажечь светодиод" + }, + "off": { + "img": "arduino/switch-off.svg", + "description": "Выключить светодиод" + }, + "toggle": { + "img": "arduino/toggle.svg", + "description": "Меняет состояние кнопки на противоположное" + }, + "blink": { + "img": "arduino/blink.svg", + "parameters": [ + { + "name": "times", + "type": "byte", + "description": "Количество миганий" + }, + { + "name": "interval", + "type": "unsigned int", + "description": "Длительность мигания" + } + ], + "description": "Мигает кнопкой определенное количество раз с определенной длительностью каждого мигания" + } + }, + "buildFiles": ["LED.h", "LED.ino"], + "importFiles": ["LED.h"], + "singletone": false + }, + + "Timer": { + "description": "Программный таймер", + "img": "arduino/timer.svg", + "signals": { + "timeout": { + "img": "arduino/timeout.svg", + "description": "Время вышло!", + "checkMethod": "timeout" + } + }, + "constructorParameters": {}, + "methods": { + "reset": { + "img": "arduino/reset.svg", + "description": "Сбросить таймер, отчет начнется сначала" + }, + "disable": { + "img": "arduino/timer-stop.svg", + "description": "Отключить таймер." + }, + "enable": { + "img": "arduino/timer-start.svg", + "description": "Включить таймер." + }, + "start": { + "img": "arduino/start.svg", + "parameters": [ + { + "name": "interval", + "type": "unsigned long", + "description": "Интервал срабатывания." + } + ], + "description": "Запустить таймер. Будет сигнал раз в интервал." + } + }, + "buildFiles": ["Timer.h", "Timer.ino"], + "importFiles": ["Timer.h"], + "singletone": false, + "variables": { + "difference": { + "img": "arduino/difference.svg", + "type": "unsigned long", + "description": "Оставшееся время до окончания таймера." + } + } + }, + "Counter": { + "description": "Переменная-счетчик.", + "img": "arduino/counter.svg", + "signals": { + "isEqual": { + "img": "arduino/isEqual.svg", + "description": "Издать сигнал, если значение счетчика равно value", + "checkMethod": "isEqual", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + }, + "isLess": { + "img": "arduino/isLess.svg", + "description": "Издать сигнал, если значение счетчика меньше value", + "checkMethod": "isLess", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + }, + "isGreater": { + "img": "arduino/isGreater.svg", + "description": "Издать сигнал, если значение счетчика больше value", + "checkMethod": "isGreater", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + } + }, + "constructorParameters": {}, + "methods": { + "add": { + "img": "arduino/add.svg", + "description": "Добавить value к значению счетчика", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + }, + "sub": { + "img": "arduino/sub.svg", + "description": "Вычесть value к значению счетчика", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + }, + "reset": { + "img": "arduino/reset.svg", + "description": "Обнулить значение счетчика." + } + }, + "variables": { + "value": { + "img": "common/value.svg", + "description": "Текущее значение счетчика", + "type": "int" + } + }, + "buildFiles": ["Counter.h", "Counter.ino"], + "importFiles": ["Counter.h"], + "singletone": false + }, + "QHsmSerial": { + "description": "Класс-надстройка над Serial. Вызывает сигналы при получении данных.", + "img": "arduino/serial.svg", + "signals": { + "noByteReceived": { + "img": "arduino/noByteReceived.svg", + "description": "Был вызван read, но данные не были получены", + "checkMethod": "noByteReceived" + }, + "byteReceived": { + "img": "arduino/byteReceived.svg", + "description": "Были получены данные", + "checkMethod": "byteReceived" + } + }, + "initializationParameters": { + "baud": { + "description": "Установить частоту работы Serial", + "type": "unsigned long" + } + }, + "initializationFunction": "init", + "methods": { + "println": { + "img": "arduino/println.svg", + "description": "Вывести данные в Serial монитор с добавлением \\n в конце", + "parameters": [ + { + "name": "data", + "description": "Данные для вывода", + "type": "int | char[]" + } + ] + }, + "print": { + "img": "arduino/print.svg", + "description": "Вывести данные в Serial монитор.", + "parameters": [ + { + "name": "data", + "description": "Данные для вывода", + "type": "int | char[]" + } + ] + }, + "read": { + "img": "arduino/read.svg", + "description": "Запросить данные из Serial." + } + }, + "variables": { + "lastByte": { + "type": "int", + "description": "Последний прочитанный байт.", + "img": "common/value.svg" + } + }, + "loopActions": ["read"], + "buildFiles": ["QHsmSerial.h", "QHsmSerial.ino"], + "importFiles": ["QHsmSerial.h"], + "singletone": true + }, + "PWM": { + "description": "Класс, реализующий ШИМ", + "img": "arduino/pwm.svg", + "signals": {}, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, на котором будет установлен ШИМ" + } + }, + "methods": { + "write": { + "img": "arduino/write.svg", + "parameters": [ + { + "name": "value", + "type": "int" + } + ], + "description": "Установить значение на ШИМ" + } + }, + "buildFiles": ["PWM.h", "PWM.ino"], + "importFiles": ["PWM.h"], + "variables": {}, + "singletone": false + }, + + "DigitalOut": { + "description": "Класс для подачи LOW, HIGH на пин", + "img": "arduino/digitalOut.svg", + "signals": {}, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, на который будет подаваться сигнал." + } + }, + "methods": { + "low": { + "img": "arduino/switch-off.svg", + "description": "Подать LOW на пин." + }, + "high": { + "img": "arduino/switch-on.svg", + "description": "Подать HIGH на пин." + } + }, + "variables": { + "value": { + "img": "common/value.svg", + "type": "int", + "description": "Текущее значение на пине." + } + }, + "buildFiles": ["DigitalOut.h", "DigitalOut.ino"], + "importFiles": ["DigitalOut.h"], + "singletone": false + }, + + "DigitalIn": { + "description": "Класс для считывания сигнала с пина", + "img": "arduino/digitalIn.svg", + "signals": { + "isChanged": { + "img": "arduino/toggle.svg", + "description": "Сигнал вызывается, когда меняется значение на пине.", + "checkMethod": "isChanged" + } + }, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, с которого будут считываться данные." + } + }, + "methods": {}, + "variables": { + "value": { + "img": "common/value.svg", + "type": "int", + "description": "Текущее значение на пине." + } + }, + "loopActions": ["read"], + "buildFiles": ["DigitalIn.h", "DigitalIn.ino"], + "importFiles": ["DigitalIn.h"], + "singletone": false + }, + + "AnalogOut": { + "description": "Класс для установки значения на аналоговые пины", + "img": "arduino/analogOut.svg", + "signals": {}, + "methods": { + "write": { + "img": "arduino/write.svg", + "parameters": [ + { + "name": "value", + "type": "int" + } + ], + "description": "Установить значение на аналоговый пин" + } + }, + "constructorParameters": {}, + "variables": { + "value": { + "img": "common/value.svg", + "type": "int", + "description": "Текущее значение на пине." + } + }, + "buildFiles": ["AnalogOut.h", "AnalogOut.ino"], + "importFiles": ["AnalogOut.h"], + "singletone": false + }, + + "AnalogIn": { + "description": "Класс для получения значения с аналогового пина", + "img": "arduino/analogIn.svg", + "signals": {}, + "methods": {}, + "constructorParameters": { + "pin": { + "type": "uint8_t", + "description": "Пин, с которого будут считываться данные." + } + }, + "variables": { + "value": { + "type": "int", + "description": "Данные, считанные с аналогового пина" + } + }, + "loopActions": ["read"], + "buildFiles": ["AnalogIn.h", "AnalogIn.ino"], + "importFiles": ["AnalogIn.h"], + "singletone": false + }, + + "ShiftRegister": { + "description": "Класс вывода байта информации на порт вход/выхода последовательно (побитно).", + "img": "arduino/shiftRegister.svg", + "signals": {}, + "methods": { + "shift": { + "img": "arduino/shift.svg", + "description": "Выводит байт информации на порт вход/выхода последовательно (побитно).\nВывод может осуществляться как с первого (левого), так и с последнего (правого) бита. \nКаждый бит последовательно подается на заданный порт, после чего подается сигнал на синхронизирующий порт вход/выход, информируя о доступности к считыванию бита.", + "parameters": [ + { + "name": "value", + "type": "int" + } + ] + } + }, + "constructorParameters": { + "dataPin": { + "type": "uint8_t", + "description": "Пин вход/выхода, на который выводятся биты" + }, + "clockPin": { + "type": "uint8_t", + "description": "Пин по которому производится синхронизация " + }, + "bitOrder": { + "type": "uint8_t", + "description": "Порядок битов. MSBFIRST - первый бит самый значимый, LSBFIRST - последний", + "optional": true + } + }, + "buildFiles": ["ShiftRegister.h", "ShiftRegister.ino"], + "importFiles": ["ShiftRegister.h"], + "variables": {}, + "singletone": false + } + } +} diff --git a/compiler/schemas/Autoborder.json b/compiler/platforms/Autoborder.json similarity index 100% rename from compiler/schemas/Autoborder.json rename to compiler/platforms/Autoborder.json diff --git a/compiler/schemas/Berloga.json b/compiler/platforms/Berloga.json similarity index 100% rename from compiler/schemas/Berloga.json rename to compiler/platforms/Berloga.json diff --git a/compiler/schemas/Generator.json b/compiler/platforms/Generator.json similarity index 100% rename from compiler/schemas/Generator.json rename to compiler/platforms/Generator.json diff --git a/compiler/schemas/Smoker.json b/compiler/platforms/Smoker.json similarity index 100% rename from compiler/schemas/Smoker.json rename to compiler/platforms/Smoker.json diff --git a/compiler/schemas/Stapler.json b/compiler/platforms/Stapler.json similarity index 100% rename from compiler/schemas/Stapler.json rename to compiler/platforms/Stapler.json diff --git a/compiler/schemas/berlogaScheme.json b/compiler/platforms/berlogaScheme.json similarity index 100% rename from compiler/schemas/berlogaScheme.json rename to compiler/platforms/berlogaScheme.json diff --git a/compiler/schemas/Arduino.json b/compiler/schemas/Arduino.json deleted file mode 100644 index 2888df0..0000000 --- a/compiler/schemas/Arduino.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "platform": { - "ArduinoUno": { - "name": "Arduino Uno", - "components": { - "Button": { - "description": "Hardware Abstraction for Buttons. It provides an easy way of handling buttons.", - "img": "arduino/button.svg", - "signals": { - "isPressed": { - "img": "arduino/isPressed.svg", - "description": "Return true if the button has been pressed" - }, - "clicked": { - "img": "arduino/clicked.svg", - "description": "Return > 0 if the button is clicked, or 0 if not." - } - }, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "sets the pin that this switch is connected to" - }, - "buttonMode": { - "type": "uint8_t", - "description": "buttonMode indicates BUTTON_PULLUP or BUTTON_PULLDOWN resistor" - } - }, - "variables": { - "value": { - "img": "common/value.svg", - "type": "int", - "description": "Текущее значение на пине" - } - }, - "methods": {}, - "singletone": false - }, - - "LED": { - "description": "Hardware Abstraction for LEDs. It provides an easy way of handling LEDs.", - "img": "arduino/led.svg", - "signals": {}, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "pin - the pin connected to this LED" - } - }, - "variables": { - "value": { - "img": "common/value.svg", - "type": "int", - "description": "Текущее значение на пине" - } - }, - "methods": { - "on": { - "img": "arduino/switch-on.svg", - "description": "Set this LED on" - }, - "off": { - "img": "arduino/switch-off.svg", - "description": "Set this LED off" - }, - "toggle": { - "img": "arduino/toggle.svg", - "description": "It will change state from on to off, or off to on" - }, - "blink": { - "img": "arduino/blink.svg", - "parameters": [ - { - "name": "times", - "type": "byte", - "description": "times the number of blinks" - }, - { - "name": "interval", - "type": "unsigned int", - "description": "the time each blink will take" - } - ], - "description": "Bling this led a number of times, with the duration of time each blink" - } - }, - "singletone": false - }, - - "Timer": { - "description": "Программный таймер.", - "img": "arduino/timer.svg", - "signals": { - "timeout": { - "img": "arduino/timeout.svg", - "description": "Время вышло!" - } - }, - "parameters": {}, - "methods": { - "reset": { - "img": "arduino/reset.svg", - "description": "Сбросить таймер, отчет начнется сначала" - }, - "disable": { - "img": "arduino/timer-stop.svg", - "description": "Отключить таймер." - }, - "enable": { - "img": "arduino/timer-start.svg", - "description": "Включить таймер." - }, - "start": { - "img": "arduino/start.svg", - "parameters": [ - { - "name": "interval", - "type": "unsigned long", - "description": "Интервал срабатывания." - } - ], - "description": "Запустить таймер. Будет сигнал раз в интервал." - } - }, - "singletone": false, - "variables": { - "difference": { - "img": "arduino/difference.svg", - "type": "unsigned long", - "description": "Оставшееся время до окончания таймера." - } - } - }, - "Counter": { - "description": "Переменная-счетчик.", - "img": "arduino/counter.svg", - "signals": { - "isEqual": { - "img": "arduino/isEqual.svg", - "description": "Издать сигнал, если значение счетчика равно value", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - }, - "isLess": { - "img": "arduino/isLess.svg", - "description": "Издать сигнал, если значение счетчика меньше value", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - }, - "isGreater": { - "img": "arduino/isGreater.svg", - "description": "Издать сигнал, если значение счетчика больше value", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - } - }, - "parameters": {}, - "methods": { - "add": { - "img": "arduino/add.svg", - "description": "Добавить value к значению счетчика", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - }, - "sub": { - "img": "arduino/sub.svg", - "description": "Вычесть value к значению счетчика", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - }, - "reset": { - "img": "arduino/reset.svg", - "description": "Обнулить значение счетчика." - } - }, - "variables": { - "value": { - "img": "common/value.svg", - "description": "Текущее значение счетчика", - "type": "int" - } - }, - - "singletone": false - }, - "QHsmSerial": { - "description": "Класс-надстройка над Serial. Вызывает сигналы при получении данных.", - "img": "arduino/serial.svg", - "signals": { - "noByteReceived": { - "img": "arduino/noByteReceived.svg", - "description": "Был вызван read, но данные не были получены" - }, - "byteReceived": { - "img": "arduino/byteReceived.svg", - "description": "Были получены данные" - } - }, - "parameters": { - "baud": { - "description": "Установить частоту работы Serial", - "type": "unsigned long" - } - }, - "methods": { - "println": { - "img": "arduino/println.svg", - "description": "Вывести данные в Serial монитор с добавлением \\n в конце", - "parameters": [ - { - "name": "data", - "description": "Данные для вывода", - "type": "int | char[]" - } - ] - }, - "print": { - "img": "arduino/print.svg", - "description": "Вывести данные в Serial монитор с добавлением.", - "parameters": [ - { - "name": "data", - "description": "Данные для вывода", - "type": "int | char[]" - } - ] - }, - "read": { - "img": "arduino/read.svg", - "description": "Запросить данные из Serial." - } - }, - "variables": { - "lastByte": { - "type": "int", - "description": "Последний прочитанный байт.", - "img": "common/value.svg" - } - }, - "singletone": true - }, - "PWM": { - "description": "Класс, реализующий ШИМ", - "img": "arduino/pwm.svg", - "signals": {}, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "Пин, на котором будет установлен ШИМ" - } - }, - "methods": { - "write": { - "img": "arduino/write.svg", - "parameters": [ - { - "name": "value", - "type": "int" - } - ], - "description": "Установить значение на ШИМ" - } - }, - "variables": {}, - "singletone": false - }, - - "DigitalOut": { - "description": "Класс для подачи LOW, HIGH на пин", - "img": "arduino/digitalOut.svg", - "signals": {}, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "Пин, на который будет подаваться сигнал." - } - }, - "methods": { - "low": { - "img": "arduino/switch-off.svg", - "description": "Подать LOW на пин." - }, - "high": { - "img": "arduino/switch-on.svg", - "description": "Подать HIGH на пин." - } - }, - "variables": { - "value": { - "img": "common/value.svg", - "type": "int", - "description": "Текущее значение на пине." - } - }, - "singletone": false - }, - - "DigitalIn": { - "description": "Класс для считывания сигнала с пина", - "img": "arduino/digitalIn.svg", - "signals": { - "isChanged": { - "img": "arduino/toggle.svg", - "description": "Сигнал вызывается, когда меняется значение на пине." - } - }, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "Пин, с которого будут считываться данные." - } - }, - "methods": {}, - "variables": { - "value": { - "img": "common/value.svg", - "type": "int", - "description": "Текущее значение на пине." - } - }, - "singletone": false - }, - - "AnalogOut": { - "description": "Класс для установки значения на аналоговые пины", - "img": "arduino/analogOut.svg", - "signals": {}, - "methods": { - "write": { - "img": "arduino/write.svg", - "parameters": [ - { - "name": "value", - "type": "int" - } - ], - "description": "Установить значение на аналоговый пин" - } - }, - "parameters": {}, - "variables": { - "value": { - "img": "common/value.svg", - "type": "int", - "description": "Текущее значение на пине." - } - }, - "singletone": false - }, - - "AnalogIn": { - "description": "Класс для получения значения с аналогового пина", - "img": "arduino/analogIn.svg", - "signals": {}, - "methods": {}, - "parameters": { - "pin": { - "type": "uint8_t", - "description": "Пин, с которого будут считываться данные." - } - }, - "variables": { - "value": { - "type": "int", - "description": "Данные, считанные с аналогового пина", - "img": "" - } - }, - "singletone": false - }, - - "ShiftRegister": { - "description": "Класс вывода байта информации на порт вход/выхода последовательно (побитно).", - "img": "arduino/shiftRegister.svg", - "signals": {}, - "methods": { - "shift": { - "img": "arduino/shift.svg", - "description": "Выводит байт информации на порт вход/выхода последовательно (побитно).\nВывод может осуществляться как с первого (левого), так и с последнего (правого) бита. \nКаждый бит последовательно подается на заданный порт, после чего подается сигнал на синхронизирующий порт вход/выход, информируя о доступности к считыванию бита.", - "parameters": [ - { - "name": "value", - "type": "int" - } - ] - } - }, - "parameters": { - "dataPin": { - "type": "uint8_t", - "description": "Пин вход/выхода, на который выводятся биты" - }, - "clockPin": { - "type": "uint8_t", - "description": "Пин по которому производится синхронизация " - }, - "bitOrder": { - "type": "uint8_t", - "description": "Порядок битов. MSBFIRST - первый бит самый значимый, LSBFIRST - последний" - } - }, - "variables": {}, - "singletone": false - } - } - } - } -} diff --git a/compiler/types/ide_types.py b/compiler/types/ide_types.py index dfa1b92..a06919a 100644 --- a/compiler/types/ide_types.py +++ b/compiler/types/ide_types.py @@ -2,9 +2,6 @@ from pydantic import BaseModel, model_validator, field_validator from pydantic.dataclasses import dataclass -# Platform: TypeAlias = Literal['BearlogaDefend', -# 'ArduinoUno', -# 'BearlogaDefend-Autoborder'] SupportedCompilers: TypeAlias = Literal['gcc', 'g++', 'arduino-cli'] IncludeStr: TypeAlias = str # include "blabla.h" diff --git a/compiler/types/platform_types.py b/compiler/types/platform_types.py index c8e6aa5..45e0730 100644 --- a/compiler/types/platform_types.py +++ b/compiler/types/platform_types.py @@ -1,55 +1,82 @@ from typing import Dict, TypeAlias, Literal, List, Optional -from pydantic import BaseModel - +from pydantic import BaseModel, Field +from pydantic.dataclasses import dataclass +from compiler.types.ide_types import SupportedCompilers +SupportLanguages: TypeAlias = Literal['C++'] ParameterType: TypeAlias = Literal['int', 'str', 'uint8_t', 'byte', 'unsigned int', 'unsigned long', 'char[]', 'int | char[]'] -class Signal(BaseModel): +@dataclass +class MethodParameter: + name: str + description: Optional[str] = None + type: Optional[ParameterType | List[str]] = None + + +@dataclass +class Signal: img: str description: str + checkMethod: str + parameters: Optional[List[MethodParameter]] = None -class Variable(BaseModel): - img: str +@dataclass +class Variable: description: str + img: str = '' type: Optional[ParameterType] = None -class ClassParameter(BaseModel): +@dataclass +class ClassParameter: type: ParameterType description: str + optional: bool = False -class MethodParameter(BaseModel): - description: Optional[str] = None - name: str - type: Optional[ParameterType | List[str]] = None - - -class Method(BaseModel): +@dataclass +class Method: img: str - parameters: List[MethodParameter] = [] description: str + parameters: List[MethodParameter] = Field(default_factory=list) + static: bool = False -class Component(BaseModel): +@dataclass +class Component: description: str img: str signals: Dict[str, Signal] variables: Dict[str, Variable] methods: Dict[str, Method] - parameters: Dict[str, ClassParameter] + buildFiles: List[str] + importFiles: List[str] + singletone: bool = False + constructorParameters: Dict[str, ClassParameter] = Field( + default_factory=dict) + initializationParameters: Dict[str, ClassParameter] | None = None + initializationFunction: str | None = None + loopActions: List[str] = Field(default_factory=list) + + +@dataclass +class CompilingSettings: + compiler: SupportedCompilers + flags: List[str] class Platform(BaseModel): name: str + description: str = '' + icon: str = '' + id: str = '' + staticComponents: bool + language: str + author: str = '' + visual: bool + compilingSettings: CompilingSettings components: Dict[str, Component] - variables: Dict[str, Variable] = {} - singletone: bool = False - - -class UnprocessedPlatform(BaseModel): - platform: Dict[str, Platform] diff --git a/test/test_cgml.py b/test/test_cgml.py new file mode 100644 index 0000000..75587aa --- /dev/null +++ b/test/test_cgml.py @@ -0,0 +1,50 @@ +"""Module for testing CGML.py file.""" +import json +import pytest +from cyberiadaml_py.cyberiadaml_parser import CGMLParser +from compiler.types.platform_types import Platform + + +@pytest.mark.parametrize( + 'path', + [ + pytest.param('examples/CyberiadaFormat-Autoborder.graphml', + id='parse AutoBorder'), + pytest.param('examples/CyberiadaFormat-Autoborder.graphml', + id='parse ArduinoUno') + ] +) +def test_parse(path: str): + """Test CGML parsing.""" + parser = CGMLParser() + with open(path, 'r') as f: + parser.parseCGML(f.read()) + + +@pytest.mark.parametrize( + 'path', + [ + pytest.param('examples/CyberiadaFormat-Autoborder.graphml', + id='parse AutoBorder'), + pytest.param('examples/CyberiadaFormat-Autoborder.graphml', + id='parse ArduinoUno') + ] +) +def test_parse(path: str): + """Test CGML parsing.""" + parser = CGMLParser() + with open(path, 'r') as f: + parser.parseCGML(f.read()) + + +@pytest.mark.parametrize( + 'path', + [ + pytest.param('compiler/platforms/Arduino.json', + id='create ArduinoUno platform'), + ] +) +def test_new_platform_creation(path: str): + with open(path, 'r') as f: + platform = Platform(**json.loads(f.read())) + print(platform) From d2bff94261bf759015b1242d04332aeaef1a5cc2 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Tue, 26 Mar 2024 12:08:35 +0300 Subject: [PATCH 03/14] WIP: parsing actions --- compiler/CGML.py | 60 +++++++++++++++++++++++- compiler/PlatformManager.py | 13 ++--- compiler/platforms/Arduino.json | 2 + compiler/types/inner_types.py | 14 +++++- compiler/types/platform_types.py | 1 + examples/CyberiadaFormat-Blinker.graphml | 8 ++-- 6 files changed, 85 insertions(+), 13 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 0b97c69..5018a9a 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -1,8 +1,64 @@ """Module for work with CyberiadaMl.""" +import re +from typing import List + +from cyberiadaml_py.types.elements import CGMLElements, CGMLState from cyberiadaml_py.cyberiadaml_parser import CGMLParser -from fullgraphmlparser.stateclasses import StateMachine +from compiler.PlatformManager import PlatformManager +from compiler.types.platform_types import Platform +from compiler.types.inner_types import InnerEvent, InnerTrigger +from fullgraphmlparser.stateclasses import StateMachine, ParserState + + +def __parse_trigger(trigger: str) -> InnerTrigger: + if trigger is None or trigger == '': + raise Exception('Trigger is None!') + + with_condition = re.match( + r'(?P\w+\.\w+)\[(?P.+)\]', trigger) + + if with_condition is not None: + condition: str = with_condition.group('condition') + parsed_trigger: str = with_condition.group('trigger') + return InnerTrigger(parsed_trigger, condition) + + right_trigger_without_condition = re.match( + r'(?P\w+\.\w+)', trigger) + + if right_trigger_without_condition is not None: + parsed_trigger = right_trigger_without_condition.group('trigger') + return InnerTrigger(parsed_trigger, None) + + raise Exception(f'Trigger({trigger}) doesnt match any regex!') + + +def __parse_actions(actions: str) -> List[InnerEvent]: + events: List[InnerEvent] = [] + raw_events = actions.split('\n\n') + + for raw_event in raw_events: + trigger, do = raw_event.split('/') + if trigger is None: + raise Exception('Trigger is None!') + return events + + +def __process_state(cgml_state: CGMLState) -> ParserState: + actions = __parse_actions(cgml_state.actions) + + return ParserState( + name=cgml_state.name, + type='internal') def parse(xml: str) -> StateMachine: parser = CGMLParser() - parser.parseCGML(xml) \ No newline at end of file + cgml_scheme: CGMLElements = parser.parseCGML(xml) + platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) + parsed_states: List[ParserState] = [] + cgml_states = cgml_scheme.states + for state_id in cgml_states: + cgml_state = cgml_states[state_id] + parsed_state = __process_state(cgml_state) + + # sm: StateMachine = StateMachine() diff --git a/compiler/PlatformManager.py b/compiler/PlatformManager.py index 833a766..3188b48 100644 --- a/compiler/PlatformManager.py +++ b/compiler/PlatformManager.py @@ -5,9 +5,9 @@ from aiopath import AsyncPath try: - from .types.platform_types import Platform, UnprocessedPlatform + from .types.platform_types import Platform except ImportError: - from compiler.types.platform_types import Platform, UnprocessedPlatform + from compiler.types.platform_types import Platform class PlatformException(Exception): @@ -34,11 +34,12 @@ async def initPlatform(path_to_schemas_dir: str) -> None: try: async with async_open(file_specifier=path, mode='r') as f: unprocessed_platform_data = await f.read() - platform_data = UnprocessedPlatform( + platform = Platform( **json.loads(unprocessed_platform_data)) - platform_id = list(platform_data.platform.keys())[0] - platform = platform_data.platform[platform_id] - PlatformManager.platforms[platform_id] = platform + if PlatformManager.platforms.get(platform.id, None) is None: + PlatformManager.platforms[platform.id] = platform + else: + print(f'Platform with id {platform.id} is already exists.') except Exception as e: print( f'Во время обработки файла "{path}" произошла ошибка! {e}') diff --git a/compiler/platforms/Arduino.json b/compiler/platforms/Arduino.json index cfbeeec..e77a308 100644 --- a/compiler/platforms/Arduino.json +++ b/compiler/platforms/Arduino.json @@ -1,5 +1,6 @@ { "name": "Arduino Uno", + "id": "ArduinoUno", "description": "Платформа для программирования микроконтроллера Arduino Uno. Включает в себя компоненты для взаимодействия с кнопками, светодиодами, Serial и другими элементами, которые могут понадобиться в процессе.\n Соберите схему, запрограммируйте Arduino Uno и насладитесь результатом вашей работы!", "icon": "путь/до/иконки", "staticComponents": false, @@ -11,6 +12,7 @@ "compiler": "arduino-cli", "flags": ["-b", "avr:arduino:uno"] }, + "delimeter": ";", "components": { "Button": { "description": "Компонент для взаимодействия с физической кнопкой", diff --git a/compiler/types/inner_types.py b/compiler/types/inner_types.py index a3399e5..9e5d362 100644 --- a/compiler/types/inner_types.py +++ b/compiler/types/inner_types.py @@ -1,6 +1,6 @@ """Module implements inner compiler's types.""" -from typing import List, Literal, Dict, TypeAlias +from typing import List, Literal, Dict, Optional, TypeAlias from pydantic import BaseModel from pydantic.dataclasses import dataclass @@ -13,6 +13,18 @@ EventName: TypeAlias = str +@dataclass +class InnerTrigger: + trigger: str + condition: Optional[str] + + +@dataclass +class InnerEvent: + trigger: InnerTrigger + actions: str + + @dataclass class File: filename: str diff --git a/compiler/types/platform_types.py b/compiler/types/platform_types.py index 45e0730..39c4218 100644 --- a/compiler/types/platform_types.py +++ b/compiler/types/platform_types.py @@ -80,3 +80,4 @@ class Platform(BaseModel): visual: bool compilingSettings: CompilingSettings components: Dict[str, Component] + delimeter: str diff --git a/examples/CyberiadaFormat-Blinker.graphml b/examples/CyberiadaFormat-Blinker.graphml index ff05b9e..d6f7aef 100644 --- a/examples/CyberiadaFormat-Blinker.graphml +++ b/examples/CyberiadaFormat-Blinker.graphml @@ -43,8 +43,8 @@ description/ Программный таймер. Включен entry/ -LED1.on() -timer1.start(1000) +LED1.on(); +timer1.start(1000); @@ -53,8 +53,8 @@ timer1.start(1000) Выключен entry/ -LED1.off() -timer1.start(1000) +LED1.off(); +timer1.start(1000); From 8fe39245dcf58ebede37396bc96d86ce0b43edf1 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 27 Mar 2024 22:23:39 +0800 Subject: [PATCH 04/14] parse transitions --- compiler/CGML.py | 153 +++++++++++++++++---- compiler/fullgraphmlparser/stateclasses.py | 13 +- compiler/types/ide_types.py | 4 +- compiler/types/inner_types.py | 3 +- test/test_cgml.py | 56 ++++++-- 5 files changed, 178 insertions(+), 51 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 5018a9a..5fd3ff9 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -1,34 +1,31 @@ """Module for work with CyberiadaMl.""" import re -from typing import List +import random +from typing import Dict, List -from cyberiadaml_py.types.elements import CGMLElements, CGMLState +from cyberiadaml_py.types.elements import CGMLElements, CGMLState, CGMLTransition from cyberiadaml_py.cyberiadaml_parser import CGMLParser from compiler.PlatformManager import PlatformManager +from compiler.types.ide_types import Bounds from compiler.types.platform_types import Platform from compiler.types.inner_types import InnerEvent, InnerTrigger -from fullgraphmlparser.stateclasses import StateMachine, ParserState +from fullgraphmlparser.stateclasses import StateMachine, ParserState, ParserTrigger -def __parse_trigger(trigger: str) -> InnerTrigger: +def __parse_trigger(trigger: str, regexes: List[str]) -> InnerTrigger: if trigger is None or trigger == '': raise Exception('Trigger is None!') - - with_condition = re.match( - r'(?P\w+\.\w+)\[(?P.+)\]', trigger) - - if with_condition is not None: - condition: str = with_condition.group('condition') - parsed_trigger: str = with_condition.group('trigger') + for regex in regexes: + regex_match = re.match(regex, trigger) + if regex_match is None: + continue + + parsed_trigger: str = regex_match.group('trigger') + try: + condition: str | None = regex_match.group('condition') + except IndexError: + condition = None return InnerTrigger(parsed_trigger, condition) - - right_trigger_without_condition = re.match( - r'(?P\w+\.\w+)', trigger) - - if right_trigger_without_condition is not None: - parsed_trigger = right_trigger_without_condition.group('trigger') - return InnerTrigger(parsed_trigger, None) - raise Exception(f'Trigger({trigger}) doesnt match any regex!') @@ -37,28 +34,124 @@ def __parse_actions(actions: str) -> List[InnerEvent]: raw_events = actions.split('\n\n') for raw_event in raw_events: - trigger, do = raw_event.split('/') - if trigger is None: - raise Exception('Trigger is None!') + raw_trigger, do = raw_event.split('/') + inner_trigger = __parse_trigger( + raw_trigger, + [ + r'^(?P\w+\.\w+)\[(?P.+)\]$', + r'^(?P\w+\.[\w()]+)$', + r'^(?P\w+_\w+)$', + r'^(?P\w+)$', + ] + ) + inner_trigger.trigger = inner_trigger.trigger.replace('.', '_') + events.append(InnerEvent( + inner_trigger, + do + )) return events -def __process_state(cgml_state: CGMLState) -> ParserState: - actions = __parse_actions(cgml_state.actions) - +def __create_empty_bounds() -> Bounds: + return Bounds( + x=0, + y=0, + height=0, + width=0 + ) + + +def __gen_id() -> int: + return random.randint(0, 100) + + +def __process_state(state_id: str, cgml_state: CGMLState) -> ParserState: + inner_triggers: List[InnerEvent] = __parse_actions(cgml_state.actions) + parser_triggers: List[ParserTrigger] = [] + entry = '' + exit = '' + for inner in inner_triggers: + trigger = inner.event.trigger + match trigger: + case 'entry': + entry = inner.actions + case 'exit': + exit = inner.actions + case _: + condition = inner.event.condition + parser_triggers.append( + ParserTrigger( + id=__gen_id(), + name=inner.event.trigger, + source=state_id, + target='', + type='internal', + action=inner.actions, + guard=condition if condition is not None else 'true' + ) + ) + bounds = ( + cgml_state.bounds + if cgml_state.bounds is not None + else __create_empty_bounds() + ) return ParserState( + id=state_id, + new_id=[state_id], name=cgml_state.name, - type='internal') + type='internal', + entry=entry, + exit=exit, + parent=None, + bounds=bounds, + actions='', + trigs=parser_triggers, + childs=[] + ) + + +def __process_transition( + transition_id: str, + cgml_transition: CGMLTransition) -> ParserTrigger: + inner_triggers: List[InnerEvent] = __parse_actions(cgml_transition.actions) + + if len(inner_triggers) == 0: + raise Exception('No trigger for transition!') + # TODO: Обработка нескольких условий для триггера + inner_event: InnerEvent = inner_triggers[0] + inner_trigger: InnerTrigger = inner_event.event + inner_trigger.trigger = inner_trigger.trigger.replace('.', '_') + condition = ( + inner_trigger.condition + if inner_trigger.condition is not None + else 'true') + return ParserTrigger( + name=inner_trigger.trigger, + source=cgml_transition.source, + target=cgml_transition.target, + action=inner_event.actions, + id=__gen_id(), + type='external', + guard=condition + ) def parse(xml: str) -> StateMachine: parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) - parsed_states: List[ParserState] = [] - cgml_states = cgml_scheme.states + states: List[ParserState] = [] + transitions: List[ParserTrigger] = [] + + cgml_transitions: Dict[str, CGMLTransition] = cgml_scheme.transitions + for transition_id in cgml_transitions: + cgml_transition = cgml_transitions[transition_id] + transitions.append(__process_transition( + transition_id, cgml_transition)) + + cgml_states: Dict[str, CGMLState] = cgml_scheme.states for state_id in cgml_states: cgml_state = cgml_states[state_id] - parsed_state = __process_state(cgml_state) - + states.append(__process_state(state_id, cgml_state)) + # TODO: Добавить внешние переходы в triggers # sm: StateMachine = StateMachine() diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 7c9ed61..54e5a5c 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import List, Optional, Set, Protocol from pydantic import Field, BaseModel from pydantic.dataclasses import dataclass @@ -6,6 +6,13 @@ from compiler.types.ide_types import Bounds, IdeStateMachine +class GeometryBounds(Protocol): + x: float + y: float + height: Optional[float] + width: Optional[float] + + class ParserNoteNodeContent(BaseModel): text: str = Field(serialization_alias='#text') @@ -70,7 +77,7 @@ class State describes state of uml-diagram and trigslates to qm format. new_id: List[str] parent: Optional['ParserState'] childs: List['ParserState'] - bounds: Bounds + bounds: GeometryBounds def __str__(self) -> str: if self.parent is not None: @@ -86,4 +93,4 @@ class StateMachine: start_action: str notes: List[ParserNote] states: List[ParserState] - signals: List[str] + signals: Set[str] diff --git a/compiler/types/ide_types.py b/compiler/types/ide_types.py index a06919a..30da637 100644 --- a/compiler/types/ide_types.py +++ b/compiler/types/ide_types.py @@ -20,8 +20,8 @@ class Point: class Bounds: x: float y: float - height: float - width: float + height: Optional[float] + width: Optional[float] @dataclass diff --git a/compiler/types/inner_types.py b/compiler/types/inner_types.py index 9e5d362..c8de4ec 100644 --- a/compiler/types/inner_types.py +++ b/compiler/types/inner_types.py @@ -21,7 +21,7 @@ class InnerTrigger: @dataclass class InnerEvent: - trigger: InnerTrigger + event: InnerTrigger actions: str @@ -34,6 +34,7 @@ class File: class CompilerResponse(BaseModel): """Data, that compiler send.""" + result: str return_code: int stdout: str diff --git a/test/test_cgml.py b/test/test_cgml.py index 75587aa..4512741 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -2,7 +2,9 @@ import json import pytest from cyberiadaml_py.cyberiadaml_parser import CGMLParser +from compiler.types.inner_types import InnerEvent, InnerTrigger from compiler.types.platform_types import Platform +from compiler.CGML import __parse_actions @pytest.mark.parametrize( @@ -24,27 +26,51 @@ def test_parse(path: str): @pytest.mark.parametrize( 'path', [ - pytest.param('examples/CyberiadaFormat-Autoborder.graphml', - id='parse AutoBorder'), - pytest.param('examples/CyberiadaFormat-Autoborder.graphml', - id='parse ArduinoUno') + pytest.param('compiler/platforms/Arduino.json', + id='create ArduinoUno platform'), ] ) -def test_parse(path: str): - """Test CGML parsing.""" - parser = CGMLParser() +def test_new_platform_creation(path: str): with open(path, 'r') as f: - parser.parseCGML(f.read()) + platform = Platform(**json.loads(f.read())) + print(platform) @pytest.mark.parametrize( - 'path', + 'raw_trigger, expected', [ - pytest.param('compiler/platforms/Arduino.json', - id='create ArduinoUno platform'), + pytest.param( + """entry/ + LED1.on(); + timer1.start(1000); + """, + [ + InnerEvent( + InnerTrigger( + 'entry', + None + ), + """ + LED1.on(); + timer1.start(1000); + """ + ) + ] + ), + pytest.param( + 'timer1.timeout/', + [ + InnerEvent( + InnerTrigger( + 'timer1_timeout', + None + ), + '' + ) + ] + + ) ] ) -def test_new_platform_creation(path: str): - with open(path, 'r') as f: - platform = Platform(**json.loads(f.read())) - print(platform) +def test_parse_actions(raw_trigger: str, expected: str): + assert __parse_actions(raw_trigger) == expected From 1cc3aea96429506c73ba3feaf640e6009ef76df0 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Mon, 1 Apr 2024 15:16:48 +0800 Subject: [PATCH 05/14] add parents to states, add external transitions to states --- compiler/CGML.py | 129 ++++++++++++++++++--- compiler/CJsonParser.py | 8 +- compiler/fullgraphmlparser/stateclasses.py | 9 +- compiler/types/inner_types.py | 6 + test/test_cgml.py | 30 ++++- 5 files changed, 158 insertions(+), 24 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 5fd3ff9..f1a8443 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -2,19 +2,38 @@ import re import random from typing import Dict, List +from copy import deepcopy -from cyberiadaml_py.types.elements import CGMLElements, CGMLState, CGMLTransition -from cyberiadaml_py.cyberiadaml_parser import CGMLParser from compiler.PlatformManager import PlatformManager from compiler.types.ide_types import Bounds from compiler.types.platform_types import Platform from compiler.types.inner_types import InnerEvent, InnerTrigger -from fullgraphmlparser.stateclasses import StateMachine, ParserState, ParserTrigger +from cyberiadaml_py.cyberiadaml_parser import CGMLParser +from cyberiadaml_py.types.elements import ( + CGMLElements, + CGMLState, + CGMLTransition +) +from fullgraphmlparser.stateclasses import ( + StateMachine, + ParserState, + ParserTrigger +) + +TransitionId = str +StateId = str + + +class CGMLException(Exception): + """Errors occured during CGML processing.""" + + ... def __parse_trigger(trigger: str, regexes: List[str]) -> InnerTrigger: + """Get condition and trigger by regexes.""" if trigger is None or trigger == '': - raise Exception('Trigger is None!') + raise CGMLException('Trigger is None!') for regex in regexes: regex_match = re.match(regex, trigger) if regex_match is None: @@ -26,10 +45,12 @@ def __parse_trigger(trigger: str, regexes: List[str]) -> InnerTrigger: except IndexError: condition = None return InnerTrigger(parsed_trigger, condition) - raise Exception(f'Trigger({trigger}) doesnt match any regex!') + raise CGMLException(f'Trigger({trigger}) doesnt match any regex!') def __parse_actions(actions: str) -> List[InnerEvent]: + """Parse action field of CGMLElements and returns do,\ + triggers, conditions.""" events: List[InnerEvent] = [] raw_events = actions.split('\n\n') @@ -81,7 +102,7 @@ def __process_state(state_id: str, cgml_state: CGMLState) -> ParserState: condition = inner.event.condition parser_triggers.append( ParserTrigger( - id=__gen_id(), + id=str(__gen_id()), name=inner.event.trigger, source=state_id, target='', @@ -113,11 +134,13 @@ def __process_state(state_id: str, cgml_state: CGMLState) -> ParserState: def __process_transition( transition_id: str, cgml_transition: CGMLTransition) -> ParserTrigger: + """Parse CGMLTransition and convert to ParserTrigger\ + - class for fullgraphmlparser.""" inner_triggers: List[InnerEvent] = __parse_actions(cgml_transition.actions) if len(inner_triggers) == 0: raise Exception('No trigger for transition!') - # TODO: Обработка нескольких условий для триггера + # TODO: Обработка нескольких событий для триггера inner_event: InnerEvent = inner_triggers[0] inner_trigger: InnerTrigger = inner_event.event inner_trigger.trigger = inner_trigger.trigger.replace('.', '_') @@ -130,28 +153,104 @@ def __process_transition( source=cgml_transition.source, target=cgml_transition.target, action=inner_event.actions, - id=__gen_id(), + id=transition_id, type='external', guard=condition ) +def __connect_transitions_to_states( + states: Dict[StateId, ParserState], + transitions: List[ParserTrigger] +) -> Dict[StateId, ParserState]: + """Add external triggers to states.""" + states_with_external_trigs = deepcopy(states) + for transition in transitions: + source_state = states_with_external_trigs.get(transition.source) + if source_state is None: + raise CGMLException('Source state is None!') + source_state.trigs.append(transition) + + return states_with_external_trigs + + +def __connect_parents_to_states( + parser_states: Dict[StateId, ParserState], + cgml_states: Dict[StateId, CGMLState], + global_state: ParserState +) -> Dict[StateId, ParserState]: + states_with_parents = deepcopy(parser_states) + + for state_id in cgml_states: + cgml_state = cgml_states[state_id] + parser_state = states_with_parents[state_id] + parent = cgml_state.parent + if parent is None: + parser_state.parent = global_state + global_state.childs.append(parser_state) + else: + parent_state = states_with_parents[parent] + parser_state.parent = parent_state + parent_state.childs.append(parser_state) + + return states_with_parents + + def parse(xml: str) -> StateMachine: parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) - platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) - states: List[ParserState] = [] + # platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) + global_state = ParserState( + name='global', + type='group', + actions='', + trigs=[], + entry='', + exit='', + id='global', + new_id=['global'], + parent=None, + childs=[], + bounds=Bounds( + x=0, + y=0, + height=0, + width=0 + ) + ) + # Parsing external transitions. transitions: List[ParserTrigger] = [] - - cgml_transitions: Dict[str, CGMLTransition] = cgml_scheme.transitions + cgml_transitions: Dict[TransitionId, + CGMLTransition] = cgml_scheme.transitions for transition_id in cgml_transitions: cgml_transition = cgml_transitions[transition_id] transitions.append(__process_transition( transition_id, cgml_transition)) - cgml_states: Dict[str, CGMLState] = cgml_scheme.states + # Parsing state's actions, internal triggers, entry/exit + states: Dict[StateId, ParserState] = {} + cgml_states: Dict[StateId, CGMLState] = cgml_scheme.states for state_id in cgml_states: cgml_state = cgml_states[state_id] - states.append(__process_state(state_id, cgml_state)) + states[state_id] = __process_state(state_id, cgml_state) + + states_with_transitions = __connect_transitions_to_states( + states, + transitions + ) + states_with_parents = __connect_parents_to_states( + states_with_transitions, cgml_states, global_state) # TODO: Добавить внешние переходы в triggers - # sm: StateMachine = StateMachine() + if cgml_scheme.initial_state is None: + raise CGMLException('No initial state!') + + start_node = cgml_scheme.initial_state.target + + return StateMachine( + start_node=start_node, + name='sketch', + start_action='', + notes=[], # TODO: Сгенерировать вставки для кода. + states=[global_state, *list(states_with_parents.values())], + signals=set(), # TODO: Сформировать набор сигналов. + ) diff --git a/compiler/CJsonParser.py b/compiler/CJsonParser.py index 5d0912e..476c5c6 100644 --- a/compiler/CJsonParser.py +++ b/compiler/CJsonParser.py @@ -393,7 +393,7 @@ def _getTransitions( triggers.append(ParserTrigger(name=eventname, source=transition.source, target=transition.target, - id=i, + id=str(i), type='external', guard=condition, action=action)) @@ -461,7 +461,7 @@ def _getEvents( source=state_id, target='', action=actions, - id=id, + id=str(id), ) return Events(events=result, signals=event_signals, @@ -594,8 +594,8 @@ def parseStateMachine(self, data: IdeStateMachine) -> StateMachine: states=[global_state, *list(proccesed_states.values())], notes=notes, start_action='', - signals=[*player_signals.keys(), - *self._addSignals(data.components, player_signals)], + signals=set([*player_signals.keys(), + *self._addSignals(data.components, player_signals)]), start_node=startNode ) diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 54e5a5c..2ab8417 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -1,11 +1,12 @@ -from typing import List, Optional, Set, Protocol +from typing import List, Optional, Set, Protocol, runtime_checkable -from pydantic import Field, BaseModel +from pydantic import Field, BaseModel, ConfigDict from pydantic.dataclasses import dataclass from compiler.types.ide_types import Bounds, IdeStateMachine +@runtime_checkable class GeometryBounds(Protocol): x: float y: float @@ -46,12 +47,12 @@ class ParserTrigger: source: str target: str action: str - id: int + id: str type: str = '' guard: str = 'true' -@dataclass +@dataclass(config=ConfigDict(arbitrary_types_allowed=True)) class ParserState: """ class State describes state of uml-diagram and trigslates to qm format. diff --git a/compiler/types/inner_types.py b/compiler/types/inner_types.py index c8de4ec..d5f785d 100644 --- a/compiler/types/inner_types.py +++ b/compiler/types/inner_types.py @@ -21,6 +21,12 @@ class InnerTrigger: @dataclass class InnerEvent: + """ + Dataclass represents parsed event string. + + event/ actions + """ + event: InnerTrigger actions: str diff --git a/test/test_cgml.py b/test/test_cgml.py index 4512741..08a9ea5 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -1,10 +1,28 @@ """Module for testing CGML.py file.""" import json +import shutil +import time +from pathlib import Path +from contextlib import contextmanager + import pytest from cyberiadaml_py.cyberiadaml_parser import CGMLParser +from compiler.fullgraphmlparser.graphml_to_cpp import CppFileWriter from compiler.types.inner_types import InnerEvent, InnerTrigger from compiler.types.platform_types import Platform -from compiler.CGML import __parse_actions +from compiler.CGML import __parse_actions, parse + +pytest_plugins = ('pytest_asyncio',) + + +@contextmanager +def create_test_folder(path: str, wait_time: int): + try: + Path(path).mkdir() + yield + finally: + time.sleep(wait_time) + shutil.rmtree(path) @pytest.mark.parametrize( @@ -74,3 +92,13 @@ def test_new_platform_creation(path: str): ) def test_parse_actions(raw_trigger: str, expected: str): assert __parse_actions(raw_trigger) == expected + + +@pytest.mark.asyncio +async def test_generating_code(): + with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: + data = f.read() + path = './test/test_folder/' + with create_test_folder(path, 10): + sm = parse(data) + await CppFileWriter(sm).write_to_file(path, 'ino') \ No newline at end of file From 3111f5ba5e1858f8bfb53bd8896b3a0eef9ccdfb Mon Sep 17 00:00:00 2001 From: L140-beep Date: Mon, 1 Apr 2024 19:40:41 +0800 Subject: [PATCH 06/14] generate signals set --- compiler/CGML.py | 40 ++++-- compiler/fullgraphmlparser/stateclasses.py | 4 +- compiler/types/inner_types.py | 1 + compiler/types/statemachinevalidator.py | 154 ++++++++++----------- 4 files changed, 112 insertions(+), 87 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index f1a8443..2c4a6dc 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -1,7 +1,7 @@ """Module for work with CyberiadaMl.""" import re import random -from typing import Dict, List +from typing import Dict, List, Set from copy import deepcopy from compiler.PlatformManager import PlatformManager @@ -65,10 +65,15 @@ def __parse_actions(actions: str) -> List[InnerEvent]: r'^(?P\w+)$', ] ) - inner_trigger.trigger = inner_trigger.trigger.replace('.', '_') + check_function: str | None = None + if '.' in inner_trigger.trigger: + check_function = inner_trigger.trigger + inner_trigger.trigger = inner_trigger.trigger.replace('.', '_') + events.append(InnerEvent( inner_trigger, - do + do, + check_function )) return events @@ -108,7 +113,8 @@ def __process_state(state_id: str, cgml_state: CGMLState) -> ParserState: target='', type='internal', action=inner.actions, - guard=condition if condition is not None else 'true' + guard=condition if condition is not None else 'true', + check_function=inner.check ) ) bounds = ( @@ -155,7 +161,8 @@ def __process_transition( action=inner_event.actions, id=transition_id, type='external', - guard=condition + guard=condition, + check_function=inner_event.check ) @@ -196,6 +203,20 @@ def __connect_parents_to_states( return states_with_parents +def __get_signals_set( + states: List[ParserState], + transitions: List[ParserTrigger]) -> Set[str]: + signals = set() + for state in states: + for internal_trig in state.trigs: + signals.add(internal_trig.name) + + for transition in transitions: + signals.add(transition.name) + + return signals + + def parse(xml: str) -> StateMachine: parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) @@ -244,13 +265,16 @@ def parse(xml: str) -> StateMachine: if cgml_scheme.initial_state is None: raise CGMLException('No initial state!') - start_node = cgml_scheme.initial_state.target - + start_node: str = cgml_scheme.initial_state.target + signals = __get_signals_set( + list(states_with_parents.values()), + transitions + ) return StateMachine( start_node=start_node, name='sketch', start_action='', notes=[], # TODO: Сгенерировать вставки для кода. states=[global_state, *list(states_with_parents.values())], - signals=set(), # TODO: Сформировать набор сигналов. + signals=signals ) diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 2ab8417..5fd54e1 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -3,8 +3,6 @@ from pydantic import Field, BaseModel, ConfigDict from pydantic.dataclasses import dataclass -from compiler.types.ide_types import Bounds, IdeStateMachine - @runtime_checkable class GeometryBounds(Protocol): @@ -41,6 +39,7 @@ class ParserTrigger: dx, dy: first relative movement of trigger visual path points: other relative movements of trigger visual path action_x, action_y, action_width: coordinates of trigger label + check_function: function, that check this signal """ name: str @@ -50,6 +49,7 @@ class ParserTrigger: id: str type: str = '' guard: str = 'true' + check_function: str | None = None @dataclass(config=ConfigDict(arbitrary_types_allowed=True)) diff --git a/compiler/types/inner_types.py b/compiler/types/inner_types.py index d5f785d..052ffe2 100644 --- a/compiler/types/inner_types.py +++ b/compiler/types/inner_types.py @@ -29,6 +29,7 @@ class InnerEvent: event: InnerTrigger actions: str + check: str | None = None @dataclass diff --git a/compiler/types/statemachinevalidator.py b/compiler/types/statemachinevalidator.py index 719a996..a0720b0 100644 --- a/compiler/types/statemachinevalidator.py +++ b/compiler/types/statemachinevalidator.py @@ -1,92 +1,92 @@ -"""Module implements validation Lapki IDE's scheme.""" -from typing import Dict +# """Module implements validation Lapki IDE's scheme.""" +# from typing import Dict -try: - from .ide_types import ( - IdeStateMachine, - Component, - Argument - ) - from .platform_types import Platform -except ImportError: - from compiler.types.ide_types import ( - IdeStateMachine, - Component, - Argument - ) - from compiler.types.platform_types import Platform +# try: +# from .ide_types import ( +# IdeStateMachine, +# Component, +# Argument +# ) +# from .platform_types import Platform +# except ImportError: +# from compiler.types.ide_types import ( +# IdeStateMachine, +# Component, +# Argument +# ) +# from compiler.types.platform_types import Platform -class StateMachineValidatorException(Exception): - """Validation error.""" +# class StateMachineValidatorException(Exception): +# """Validation error.""" - ... +# ... -class StateMachineValidator: - """ - Класс для валидации схемы формата Lapki IDE. +# class StateMachineValidator: +# """ +# Класс для валидации схемы формата Lapki IDE. - TODO: - - Проверка аргументов методов - - Проверка параметров компонентов - - Проверка типов компонентов - - Проверка методов (что вызывается метод, который прописан в платформе) - - Проверка указанной платформы на наличие - """ +# TODO: +# - Проверка аргументов методов +# - Проверка параметров компонентов +# - Проверка типов компонентов +# - Проверка методов (что вызывается метод, который прописан в платформе) +# - Проверка указанной платформы на наличие +# """ - def __init__(self, data: IdeStateMachine, platform: Platform) -> None: - self.data = data - self.platform = platform +# def __init__(self, data: IdeStateMachine, platform: Platform) -> None: +# self.data = data +# self.platform = platform - def _validateStates(self) -> bool: - ... +# def _validateStates(self) -> bool: +# ... - def _validateTransitions(self) -> bool: - for transition in self.data.transitions: - try: - if (self.data.states[transition.source] and - self.data.states[transition.target]): - ... - except KeyError: - raise StateMachineValidatorException( - 'Transition validate error!' - f'Unknown source {transition.source}!' - ) +# def _validateTransitions(self) -> bool: +# for transition in self.data.transitions: +# try: +# if (self.data.states[transition.source] and +# self.data.states[transition.target]): +# ... +# except KeyError: +# raise StateMachineValidatorException( +# 'Transition validate error!' +# f'Unknown source {transition.source}!' +# ) - return True +# return True - def _validateComponents(self, components: Dict[str, Component]) -> bool: - """Функция проверяет соответствие компонентов указанной платформе.""" - component_types = list(self.platform.components.keys()) - for component_id in self.data.components: - component = self.data.components[component_id] - if component.type in component_types: - parameters = list( - self.platform.components[component.type].parameters.keys()) - for parameter_id in component.parameters: - if parameter_id in parameters: - continue - raise StateMachineValidatorException( - f'Component({component_id}):' - f'unknown parameter {parameter_id}' - f'in platform {self.platform.name}' - ) - raise StateMachineValidatorException( - f'Component({component_id}):' - f'unknown component {component.type}' - f'in platform {self.platform.name}' - ) +# def _validateComponents(self, components: Dict[str, Component]) -> bool: +# """Функция проверяет соответствие компонентов указанной платформе.""" +# component_types = list(self.platform.components.keys()) +# for component_id in self.data.components: +# component = self.data.components[component_id] +# if component.type in component_types: +# parameters = list( +# self.platform.components[component.type].parameters.keys()) +# for parameter_id in component.parameters: +# if parameter_id in parameters: +# continue +# raise StateMachineValidatorException( +# f'Component({component_id}):' +# f'unknown parameter {parameter_id}' +# f'in platform {self.platform.name}' +# ) +# raise StateMachineValidatorException( +# f'Component({component_id}):' +# f'unknown component {component.type}' +# f'in platform {self.platform.name}' +# ) - return True +# return True - def _validateArgs( - self, - component: Component, - method: str, - args: Dict[str, Argument | str]) -> bool: - ... +# def _validateArgs( +# self, +# component: Component, +# method: str, +# args: Dict[str, Argument | str]) -> bool: +# ... - def validate(self) -> bool: - """Validate scheme.""" - return self._validateComponents(self.data.components) +# def validate(self) -> bool: +# """Validate scheme.""" +# return self._validateComponents(self.data.components) From 2eec2aaff7b099d627a9dbb5dd5e07c86634830d Mon Sep 17 00:00:00 2001 From: L140-beep Date: Mon, 1 Apr 2024 21:00:26 +0800 Subject: [PATCH 07/14] parsing components parameters, wip: code generation --- compiler/CGML.py | 66 +++++++++++++++++++++++++++++++++-- compiler/types/inner_types.py | 8 ++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 2c4a6dc..d3b6fa4 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -7,21 +7,24 @@ from compiler.PlatformManager import PlatformManager from compiler.types.ide_types import Bounds from compiler.types.platform_types import Platform -from compiler.types.inner_types import InnerEvent, InnerTrigger +from compiler.types.inner_types import InnerComponent, InnerEvent, InnerTrigger from cyberiadaml_py.cyberiadaml_parser import CGMLParser from cyberiadaml_py.types.elements import ( CGMLElements, CGMLState, - CGMLTransition + CGMLTransition, + CGMLComponent ) from fullgraphmlparser.stateclasses import ( StateMachine, ParserState, - ParserTrigger + ParserTrigger, + ParserNote ) TransitionId = str StateId = str +ComponentId = str class CGMLException(Exception): @@ -186,6 +189,7 @@ def __connect_parents_to_states( cgml_states: Dict[StateId, CGMLState], global_state: ParserState ) -> Dict[StateId, ParserState]: + """""" states_with_parents = deepcopy(parser_states) for state_id in cgml_states: @@ -206,6 +210,7 @@ def __connect_parents_to_states( def __get_signals_set( states: List[ParserState], transitions: List[ParserTrigger]) -> Set[str]: + """Get signals set from all states and transitions.""" signals = set() for state in states: for internal_trig in state.trigs: @@ -217,6 +222,56 @@ def __get_signals_set( return signals +def __parse_components( + components: List[CGMLComponent] +) -> Dict[ComponentId, InnerComponent]: + """Parse component's parameters.""" + inner_components: Dict[ComponentId, InnerComponent] = {} + + for component in components: + parameters: List[str] = component.parameters.split('\n') + type = '' + parsed_parameters: Dict[str, str] = {} + for parameter in parameters: + parameter_name, value = list(map( + lambda val: val.strip(), parameter.split('/'))) + if parameter_name is None or value is None: + raise CGMLException( + 'No name parameter or no value of parameter.') + match parameter_name: + case 'type': + type = value + case 'labelColor' | 'label' | 'name' | 'description': + ... + case _: + parsed_parameters[parameter_name] = value + inner_components[component.id] = InnerComponent( + type, + parsed_parameters + ) + + return inner_components + + +def __generate_init_components_code( + components: Dict[ComponentId, InnerComponent], + platform: Platform) -> List[ParserNote]: + notes: List[ParserNote] = [] + for component_id in components: + component: InnerComponent = components[component_id] + type = component.type + platform_component = platform.components[type] + const_parameters = platform_component.constructorParameters + + return notes + + +def __generate_code( + platform: Platform, + components: List[CGMLComponent]) -> List[ParserNote]: + return [] + + def parse(xml: str) -> StateMachine: parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) @@ -270,6 +325,11 @@ def parse(xml: str) -> StateMachine: list(states_with_parents.values()), transitions ) + + parsed_components = __parse_components(cgml_scheme.components) + notes: List[ParserNote] = [] + # notes.extend() + return StateMachine( start_node=start_node, name='sketch', diff --git a/compiler/types/inner_types.py b/compiler/types/inner_types.py index 052ffe2..bd8c73a 100644 --- a/compiler/types/inner_types.py +++ b/compiler/types/inner_types.py @@ -1,6 +1,6 @@ """Module implements inner compiler's types.""" -from typing import List, Literal, Dict, Optional, TypeAlias +from typing import List, Literal, Dict, Optional, TypeAlias, Any from pydantic import BaseModel from pydantic.dataclasses import dataclass @@ -13,6 +13,12 @@ EventName: TypeAlias = str +@dataclass +class InnerComponent: + type: str + parameters: Dict[str, Any] + + @dataclass class InnerTrigger: trigger: str From 69d0c5749ea7655ffffd77cd0547620ded6fb60c Mon Sep 17 00:00:00 2001 From: L140-beep Date: Tue, 2 Apr 2024 21:02:42 +0800 Subject: [PATCH 08/14] generating component's variables creation --- compiler/CGML.py | 56 +++- compiler/CJsonParser.py | 45 +-- compiler/PlatformManager.py | 26 +- compiler/config.py | 4 +- compiler/fullgraphmlparser/graphml_to_cpp.py | 59 ++-- compiler/fullgraphmlparser/stateclasses.py | 41 ++- compiler/main.py | 6 +- compiler/platforms/berlogaScheme.json | 278 ------------------- pyproject.toml | 2 +- test/test_cgml.py | 11 +- 10 files changed, 167 insertions(+), 361 deletions(-) delete mode 100644 compiler/platforms/berlogaScheme.json diff --git a/compiler/CGML.py b/compiler/CGML.py index d3b6fa4..091cf57 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -19,7 +19,9 @@ StateMachine, ParserState, ParserTrigger, - ParserNote + ParserNote, + Labels, + create_note ) TransitionId = str @@ -189,7 +191,13 @@ def __connect_parents_to_states( cgml_states: Dict[StateId, CGMLState], global_state: ParserState ) -> Dict[StateId, ParserState]: - """""" + """ + Fill parent field for states. + + We can't fill it during first iteration,\ + because not everyone state is ready. + So we can't add parent, that doesn't exist yet. + """ states_with_parents = deepcopy(parser_states) for state_id in cgml_states: @@ -253,16 +261,44 @@ def __parse_components( return inner_components -def __generate_init_components_code( +def __generate_create_components_code( components: Dict[ComponentId, InnerComponent], platform: Platform) -> List[ParserNote]: + """ + Generate code, that create component's variables in h-file. + + Generated code example: + ```cpp + LED led1 = LED(12); + Timer timer1 = Timer(); + ``` + """ notes: List[ParserNote] = [] for component_id in components: component: InnerComponent = components[component_id] - type = component.type + type: str = component.type platform_component = platform.components[type] - const_parameters = platform_component.constructorParameters + if platform_component.singletone: + continue + + construct_parameters = platform_component.constructorParameters + # Порядок вставки аргументов определяется по позиции ключа в платформе + construct_keys = list(construct_parameters.keys()) + args: List[str] = [] + for parameter_name in construct_keys: + parameter = component.parameters[parameter_name] + if parameter is None: + if construct_parameters[parameter_name].optional: + continue + else: + raise CGMLException( + f'No arg {parameter_name} for component\ + {component_id}!') + args.append(str(parameter)) + ', '.join(args) + code_to_insert = f'{type} {component_id} = {type}({args});\n' + notes.append(create_note(Labels.H, code_to_insert)) return notes @@ -275,7 +311,7 @@ def __generate_code( def parse(xml: str) -> StateMachine: parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) - # platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) + platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) global_state = ParserState( name='global', type='group', @@ -327,14 +363,16 @@ def parse(xml: str) -> StateMachine: ) parsed_components = __parse_components(cgml_scheme.components) - notes: List[ParserNote] = [] - # notes.extend() + notes: List[ParserNote] = [ + *__generate_create_components_code(parsed_components, platform) + ] + print(notes) return StateMachine( start_node=start_node, name='sketch', start_action='', - notes=[], # TODO: Сгенерировать вставки для кода. + notes=notes, # TODO: Сгенерировать вставки для кода. states=[global_state, *list(states_with_parents.values())], signals=signals ) diff --git a/compiler/CJsonParser.py b/compiler/CJsonParser.py index 476c5c6..a6a4b57 100644 --- a/compiler/CJsonParser.py +++ b/compiler/CJsonParser.py @@ -1,6 +1,4 @@ """Legacy module that implements parsing Lapki IDE's internal JSON scheme.""" - -from enum import Enum from typing import Dict, Iterable, List, Set from compiler.types.ide_types import Bounds @@ -13,8 +11,8 @@ StateMachine, ParserState, ParserNote, - ParserNoteNodeLabel, - ParserNoteNodeContent + Labels, + create_note ) from .types.ide_types import ( IdeStateMachine, @@ -46,8 +44,8 @@ StateMachine, ParserState, ParserNote, - ParserNoteNodeLabel, - ParserNoteNodeContent + Labels, + create_note ) from compiler.types.ide_types import ( IdeStateMachine, @@ -69,20 +67,6 @@ class ParserException(Exception): ... -class Labels(Enum): - """В fullgraphmlparser для определения, \ - куда вставлять код используют метки.""" - - H_INCLUDE = 'Code for h-file' - H = 'Declare variable in h-file' - CPP = 'Code for cpp-file' - CTOR = 'Constructor code' - USER_VAR_H = 'User variables for h-file' - USER_VAR_C = 'User variables for c-file' - USER_FUNC_H = 'User methods for h-file' - USER_FUNC_C = 'User methods for c-file' - - class CJsonParser: """Class for parsing Lapki IDE's internal JSON scheme.""" @@ -151,15 +135,6 @@ def _specificCheckComponentSignal( ] ) + '\n\t}' - def _getNote(self, label: Labels, content: str) -> ParserNote: - """Создать ParserNote на основе метки вставки, и кода для вставки.""" - return ParserNote( - umlNote=ParserNoteNodeLabel( - nodeLabel=ParserNoteNodeContent( - text=f'{label.value}: {content}') - ) - ) - def getLibraries(self, components: List[Component]) -> Set[str]: """Получить используемые типы компонентов.""" libraries: Set[str] = set() @@ -260,9 +235,9 @@ def _createNotes( '}']) + '\n}' notes.extend( [ - self._getNote(Labels.H, ''.join(variables)), - self._getNote(Labels.H_INCLUDE, ''.join(includes)), - self._getNote(Labels.CPP, '\n\n'.join( + create_note(Labels.H, ''.join(variables)), + create_note(Labels.H_INCLUDE, ''.join(includes)), + create_note(Labels.CPP, '\n\n'.join( [setup_function, loop_function, main_function] ) ), @@ -281,9 +256,9 @@ def _createNotes( notes.extend( [ - self._getNote(Labels.H, ''.join(variables)), - self._getNote(Labels.H_INCLUDE, ''.join(includes)), - self._getNote(Labels.CPP, '\n\n'.join( + create_note(Labels.H, ''.join(variables)), + create_note(Labels.H_INCLUDE, ''.join(includes)), + create_note(Labels.CPP, '\n\n'.join( [setup_function, loop_function] ) ), diff --git a/compiler/PlatformManager.py b/compiler/PlatformManager.py index 3188b48..4f4c525 100644 --- a/compiler/PlatformManager.py +++ b/compiler/PlatformManager.py @@ -27,22 +27,28 @@ class PlatformManager: platforms: dict[str, Platform] = {} @staticmethod - async def initPlatform(path_to_schemas_dir: str) -> None: - """Find platforms in path and add it to Dict.""" - print(f'Поиск схем в папке "{path_to_schemas_dir}"...') - async for path in AsyncPath(path_to_schemas_dir).glob('*json'): - try: - async with async_open(file_specifier=path, mode='r') as f: - unprocessed_platform_data = await f.read() + async def load_platform(path_to_platform: str | AsyncPath) -> None: + """Load platform from file and add it to dict.""" + try: + async with async_open(path_to_platform, 'r') as f: + unprocessed_platform_data: str = await f.read() platform = Platform( **json.loads(unprocessed_platform_data)) if PlatformManager.platforms.get(platform.id, None) is None: PlatformManager.platforms[platform.id] = platform else: print(f'Platform with id {platform.id} is already exists.') - except Exception as e: - print( - f'Во время обработки файла "{path}" произошла ошибка! {e}') + except Exception as e: + print( + f'Во время обработки файла "{path_to_platform}"' + f'произошла ошибка! {e}') + + @staticmethod + async def init_platforms(path_to_schemas_dir: str) -> None: + """Find platforms in path and add it to Dict.""" + print(f'Поиск схем в папке "{path_to_schemas_dir}"...') + async for path in AsyncPath(path_to_schemas_dir).glob('*json'): + await PlatformManager.load_platform(path) print( f'Были найдены платформы: {list(PlatformManager.platforms.keys())}' diff --git a/compiler/config.py b/compiler/config.py index 3cd69c3..ca5b8d6 100644 --- a/compiler/config.py +++ b/compiler/config.py @@ -9,6 +9,6 @@ BASE_DIRECTORY = MODULE_PATH + '/' # "server/" BUILD_DIRECTORY = '/tmp/lapki-compiler/' LIBRARY_PATH = os.path.join(MODULE_PATH, 'library/') -SCHEMA_DIRECTORY = os.path.join(MODULE_PATH, 'schemas/') +PLATFORM_DIRECTORY = os.path.join(MODULE_PATH, 'platforms/') LOG_PATH = 'logs.log' # Замените на нужную папку -MAX_MSG_SIZE = 1024 * 50 # Максимальный размер сообщения от клиента. +MAX_MSG_SIZE = 1024 * 50 # Максимальный размер сообщения от клиента. \ No newline at end of file diff --git a/compiler/fullgraphmlparser/graphml_to_cpp.py b/compiler/fullgraphmlparser/graphml_to_cpp.py index 7376efe..8aa8c3c 100644 --- a/compiler/fullgraphmlparser/graphml_to_cpp.py +++ b/compiler/fullgraphmlparser/graphml_to_cpp.py @@ -3,13 +3,17 @@ import re from collections import defaultdict -from typing import List, Tuple +from typing import List, Tuple, Dict from aiofile import async_open try: from .stateclasses import ParserState, ParserTrigger, StateMachine from .graphml import * except ImportError: - from compiler.fullgraphmlparser.stateclasses import ParserState, ParserTrigger, StateMachine + from compiler.fullgraphmlparser.stateclasses import ( + ParserState, + ParserTrigger, + StateMachine + ) from compiler.fullgraphmlparser.graphml import * MODULE_PATH = os.path.dirname(os.path.abspath(inspect.stack()[0][1])) @@ -39,28 +43,51 @@ class CppFileWriter: f = None all_signals = [] userFlag = False # Флаг на наличие кода для класса User + list_notes_dict: Dict[str, List[str]] = {} def __init__(self, state_machine: StateMachine) -> None: self.sm_name = state_machine.name self.player_signal = state_machine.signals - notes_mapping = [('Code for h-file', 'raw_h_code'), - ('Declare variable in h-file', 'declare_h_code'), - ('Code for cpp-file', 'raw_cpp_code'), - ('Constructor fields', 'constructor_fields'), - ('State fields', 'state_fields'), - ('Constructor code', 'constructor_code'), - ('Event fields', 'event_fields'), - ('User variables for h-file', 'user_variables_h'), - ('User methods for h-file', 'user_methods_h'), - ('User variables for c-file', 'user_variables_c'), - ('User methods for c-file', 'user_methods_c')] - - self.notes_dict = {key: '' for _, key in notes_mapping} + notes_mapping: List[Tuple[str, str]] = [ + ('Code for h-file', 'raw_h_code'), + ('Declare variable in h-file', + 'declare_h_code'), + ('Code for cpp-file', + 'raw_cpp_code'), + ('Constructor fields', + 'constructor_fields'), + ('State fields', 'state_fields'), + ('Constructor code', + 'constructor_code'), + ('Event fields', 'event_fields'), + ('User variables for h-file', + 'user_variables_h'), + ('User methods for h-file', + 'user_methods_h'), + ('User variables for c-file', + 'user_variables_c'), + ('User methods for c-file', 'user_methods_c') + ] + + # TODO: Заставить это ***** работать со списками + self.list_notes_dict: Dict[str, List[str]] = {key: [''] for _, key + in notes_mapping} + for note in state_machine.notes: dict_note = note.model_dump(by_alias=True) for prefix, key in notes_mapping: + # Делаем так, чтобы при повторении меток, их содержимое + # объединялось, а не перезаписывалось if dict_note['y:UMLNoteNode']['y:NodeLabel']['#text'].startswith(prefix): - self.notes_dict[key] = dict_note['y:UMLNoteNode']['y:NodeLabel']['#text'] + if self.list_notes_dict != []: + self.list_notes_dict[key].append( + '\n'.join(dict_note['y:UMLNoteNode']['y:NodeLabel']['#text'].split('\n')[1:])) + else: + self.list_notes_dict[key].append( + dict_note['y:UMLNoteNode']['y:NodeLabel']['#text']) + self.notes_dict = {key: '\n'.join( + self.list_notes_dict[key]) for _, key in notes_mapping} + self.start_node = state_machine.start_node self.start_action = state_machine.start_action self.states = state_machine.states diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 5fd54e1..193b41b 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -1,9 +1,39 @@ from typing import List, Optional, Set, Protocol, runtime_checkable +from enum import Enum from pydantic import Field, BaseModel, ConfigDict from pydantic.dataclasses import dataclass +def create_note(label: 'Labels', content: str) -> 'ParserNote': + """ + Создать ParserNote на основе метки вставки, и кода для вставки. + + Между label и контентом добавляется \\n, так как по этому символу\ + сплитится строка в функции write_to_file. + """ + return ParserNote( + umlNote=_ParserNoteNodeLabel( + nodeLabel=_ParserNoteNodeContent( + text=f'{label.value}:\n {content}') + ) + ) + + +class Labels(Enum): + """В fullgraphmlparser для определения, \ + куда вставлять код используют метки.""" + + H_INCLUDE = 'Code for h-file' + H = 'Declare variable in h-file' + CPP = 'Code for cpp-file' + CTOR = 'Constructor code' + USER_VAR_H = 'User variables for h-file' + USER_VAR_C = 'User variables for c-file' + USER_FUNC_H = 'User methods for h-file' + USER_FUNC_C = 'User methods for c-file' + + @runtime_checkable class GeometryBounds(Protocol): x: float @@ -12,16 +42,19 @@ class GeometryBounds(Protocol): width: Optional[float] -class ParserNoteNodeContent(BaseModel): +class _ParserNoteNodeContent(BaseModel): text: str = Field(serialization_alias='#text') -class ParserNoteNodeLabel(BaseModel): - nodeLabel: ParserNoteNodeContent = Field(serialization_alias='y:NodeLabel') +class _ParserNoteNodeLabel(BaseModel): + nodeLabel: _ParserNoteNodeContent = Field( + serialization_alias='y:NodeLabel') class ParserNote(BaseModel): - umlNote: ParserNoteNodeLabel = Field(serialization_alias='y:UMLNoteNode') + """Class for code inserting.""" + + umlNote: _ParserNoteNodeLabel = Field(serialization_alias='y:UMLNoteNode') @dataclass diff --git a/compiler/main.py b/compiler/main.py index e0ffcd1..bc41062 100644 --- a/compiler/main.py +++ b/compiler/main.py @@ -6,12 +6,12 @@ try: from .routes import setup_routes - from .config import SERVER_PORT, SERVER_HOST, SCHEMA_DIRECTORY + from .config import SERVER_PORT, SERVER_HOST, PLATFORM_DIRECTORY from .Logger import Logger from .PlatformManager import PlatformManager except ImportError: from compiler.routes import setup_routes - from compiler.config import SERVER_PORT, SERVER_HOST, SCHEMA_DIRECTORY + from compiler.config import SERVER_PORT, SERVER_HOST, PLATFORM_DIRECTORY from compiler.PlatformManager import PlatformManager from .Logger import Logger @@ -25,7 +25,7 @@ async def main() -> NoReturn: site = web.TCPSite(runner, host=SERVER_HOST, port=SERVER_PORT) await Logger.init_logger() - await PlatformManager.initPlatform(SCHEMA_DIRECTORY) + await PlatformManager.init_platforms(PLATFORM_DIRECTORY) await site.start() print('Модуль компилятора запущен...') while True: diff --git a/compiler/platforms/berlogaScheme.json b/compiler/platforms/berlogaScheme.json deleted file mode 100644 index 4db654c..0000000 --- a/compiler/platforms/berlogaScheme.json +++ /dev/null @@ -1,278 +0,0 @@ -{ - "states": { - "n0": { - "name": "Бой", - "events": [ - { - "trigger": { - "component": "System", - "method": "onEnter" - }, - "do": [] - }, - { - "trigger": { - "component": "System", - "method": "onExit" - }, - "do": [] - } - ], - "bounds": { - "x": 1337, - "y": 30, - "width": 515, - "height": 772 - } - }, - "n1": { - "name": "Сближение", - "events": [ - { - "trigger": { - "component": "System", - "method": "onEnter" - }, - "do": [ - { - "component": "МодульДвижения", - "method": "ДвигатьсяКЦели", - "args": {} - } - ] - }, - { - "trigger": { - "component": "System", - "method": "onExit" - }, - "do": [] - } - ], - "bounds": { - "x": 198, - "y": 445, - "width": 411, - "height": 194 - }, - "parent": "n0" - }, - "n2": { - "name": "Атака", - "events": [ - { - "trigger": { - "component": "System", - "method": "onEnter" - }, - "do": [ - { - "component": "ОружиеЦелевое", - "method": "АтаковатьЦель", - "args": {} - } - ] - }, - { - "trigger": { - "component": "System", - "method": "onExit" - }, - "do": [] - } - ], - "bounds": { - "x": 202, - "y": 111, - "width": 411, - "height": 194 - }, - "parent": "n0" - }, - "n3": { - "name": "Скан", - "events": [ - { - "trigger": { - "component": "System", - "method": "onEnter" - }, - "do": [ - { - "component": "Сенсор", - "method": "ПоискВрагаПоДистанции", - "args": { - "Направление поиска": "мин" - } - } - ] - }, - { - "trigger": { - "component": "System", - "method": "onExit" - }, - "do": [ - { - "component": "Сенсор", - "method": "ОстановкаПоиска", - "args": {} - } - ] - } - ], - "bounds": { - "x": 255, - "y": 290, - "width": 411, - "height": 304 - } - } - }, - "initialState": { - "target": "n3", - "position": { - "x": 155, - "y": 190 - } - }, - "transitions": [ - { - "source": "n0", - "target": "n3", - "trigger": { - "component": "АнализаторЦели", - "method": "ЦельПотеряна" - }, - "condition": null, - "position": { - "x": -1327, - "y": 630 - }, - "do": [], - "color": "#49F5FD" - }, - { - "source": "n0", - "target": "n3", - "trigger": { - "component": "АнализаторЦели", - "method": "ЦельУничтожена" - }, - "condition": { - "type": "less", - "value": [ - { - "type": "component", - "value": { - "component": "Таймер", - "method": "ТекущееЗначениеТаймера", - "args": {} - } - }, - { - "type": "value", - "value": "123" - } - ] - }, - "position": { - "x": -1177, - "y": 780 - }, - "do": [ - { - "component": "АнализаторЦели", - "method": "СбросЦели", - "args": {} - } - ], - "color": "#2A7778" - }, - { - "source": "n3", - "target": "n1", - "trigger": { - "component": "Сенсор", - "method": "ЦельПолучена" - }, - "condition": null, - "position": { - "x": -1328, - "y": 702 - }, - "do": [], - "color": "#FEEF0B" - }, - { - "source": "n1", - "target": "n2", - "trigger": { - "component": "ОружиеЦелевое", - "method": "ЦельВошлаВЗонуАтаки" - }, - "condition": null, - "position": { - "x": -786, - "y": 478 - }, - "do": [], - "color": "#C741C5" - }, - { - "source": "n2", - "target": "n1", - "trigger": { - "component": "ОружиеЦелевое", - "method": "ЦельВышлаИзЗоныАтаки" - }, - "condition": null, - "position": { - "x": -636, - "y": 628 - }, - "do": [], - "color": "#4799C3" - } - ], - "components": { - "Сенсор": { - "type": "Сенсор", - "parameters": {} - }, - "АнализаторЦели": { - "type": "АнализаторЦели", - "parameters": {} - }, - "МодульДвижения": { - "type": "МодульДвижения", - "parameters": {} - }, - "Самодиагностика": { - "type": "Самодиагностика", - "parameters": {} - }, - "СвязьСБазой": { - "type": "СвязьСБазой", - "parameters": {} - }, - "Таймер": { - "type": "Таймер", - "parameters": {} - }, - "Счётчик": { - "type": "Счётчик", - "parameters": {} - }, - "ОружиеЦелевое": { - "type": "ОружиеЦелевое", - "parameters": {} - }, - "СпособностьПочинка": { - "type": "СпособностьПочинка", - "parameters": {} - } - }, - "platform": "BearlogaDefend", - "parameters": {} -} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e9ccfc5..de65b54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ flake8-pyproject = "^1.2.3" [tool.flake8] import-order-style="pep8" inline-quotes = "single" -ignore=["D107", "W504"] +ignore=["D107", "W504", "D301"] include = ["compiler"] exclude=[ "**/__pycache__", diff --git a/test/test_cgml.py b/test/test_cgml.py index 08a9ea5..ef0b5ff 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -11,10 +11,15 @@ from compiler.types.inner_types import InnerEvent, InnerTrigger from compiler.types.platform_types import Platform from compiler.CGML import __parse_actions, parse +from compiler.PlatformManager import PlatformManager pytest_plugins = ('pytest_asyncio',) +@pytest.fixture +def init_platform(): + return PlatformManager.load_platform('compiler/platforms/Arduino.json') + @contextmanager def create_test_folder(path: str, wait_time: int): try: @@ -40,7 +45,6 @@ def test_parse(path: str): with open(path, 'r') as f: parser.parseCGML(f.read()) - @pytest.mark.parametrize( 'path', [ @@ -95,10 +99,11 @@ def test_parse_actions(raw_trigger: str, expected: str): @pytest.mark.asyncio -async def test_generating_code(): +async def test_generating_code(init_platform): + await init_platform with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: data = f.read() path = './test/test_folder/' with create_test_folder(path, 10): sm = parse(data) - await CppFileWriter(sm).write_to_file(path, 'ino') \ No newline at end of file + await CppFileWriter(sm).write_to_file(path, 'ino') From 3a07611c8d10347fdde5ef76a5d398aceecb90c4 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 3 Apr 2024 11:41:03 +0800 Subject: [PATCH 09/14] generating setup function code --- compiler/CGML.py | 97 +++++++++++++++----- compiler/fullgraphmlparser/graphml_to_cpp.py | 20 +++- compiler/fullgraphmlparser/stateclasses.py | 3 +- test/test_cgml.py | 2 +- 4 files changed, 95 insertions(+), 27 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 091cf57..4f20b81 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -1,12 +1,13 @@ """Module for work with CyberiadaMl.""" import re import random -from typing import Dict, List, Set +from typing import Dict, List, Set, Any from copy import deepcopy from compiler.PlatformManager import PlatformManager from compiler.types.ide_types import Bounds -from compiler.types.platform_types import Platform +from string import Template +from compiler.types.platform_types import ClassParameter, Platform from compiler.types.inner_types import InnerComponent, InnerEvent, InnerTrigger from cyberiadaml_py.cyberiadaml_parser import CGMLParser from cyberiadaml_py.types.elements import ( @@ -28,6 +29,8 @@ StateId = str ComponentId = str +CALL_FUNCTION_TEMPLATE = Template('$id$delimeter($args);') + class CGMLException(Exception): """Errors occured during CGML processing.""" @@ -283,29 +286,80 @@ def __generate_create_components_code( continue construct_parameters = platform_component.constructorParameters - # Порядок вставки аргументов определяется по позиции ключа в платформе - construct_keys = list(construct_parameters.keys()) - args: List[str] = [] - for parameter_name in construct_keys: - parameter = component.parameters[parameter_name] - if parameter is None: - if construct_parameters[parameter_name].optional: - continue - else: - raise CGMLException( - f'No arg {parameter_name} for component\ - {component_id}!') - args.append(str(parameter)) - ', '.join(args) - code_to_insert = f'{type} {component_id} = {type}({args});\n' + args: str = __create_parameters_sequence( + component.parameters, construct_parameters) + code_to_insert = (f'{type} {component_id} =' + f'{type}({args});\n') notes.append(create_note(Labels.H, code_to_insert)) return notes -def __generate_code( +def __create_parameters_sequence( + component_parameters: Dict[str, Any], + platform_parameters: Dict[str, ClassParameter]) -> str: + """ + Create args sequence from component's parameters and platform parameters. + + Order of parameters in sequence depends on order platform parameters. + Return example: 'arg1, arg2, arg3' + """ + args: List[str] = [] + for parameter_name in platform_parameters: + parameter = component_parameters[parameter_name] + if parameter is None: + if platform_parameters[parameter_name].optional: + continue + else: + raise CGMLException( + f'No arg {parameter_name} for component!') + args.append(str(parameter)) + return ', '.join(args) + + +def __generate_function_call( platform: Platform, - components: List[CGMLComponent]) -> List[ParserNote]: - return [] + component_type: str, + component_id: str, + method: str, + args: str) -> str: + """ + Generate function call code using CALL_FUNCTION_TEMPLATE. + + Check component's static or platform's static. + """ + delimeter = '.' + if (platform.staticComponents or + platform.components[component_type].singletone): + delimeter = '::' + return CALL_FUNCTION_TEMPLATE.substitute( + { + 'id': component_id, + 'method': method, + 'args': args, + 'delimeter': delimeter + } + ) + + +def __generate_setup_function_code( + components: Dict[ComponentId, InnerComponent], + platform: Platform) -> List[ParserNote]: + notes: List[ParserNote] = [] + for component_id, component in components.items(): + type = component.type + platform_component = platform.components[type] + init_func = platform_component.initializationFunction + if init_func is None: + continue + init_parameters = platform_component.initializationParameters + args = '' + if init_parameters is not None: + args = __create_parameters_sequence( + component.parameters, init_parameters) + code_to_insert = __generate_function_call( + platform, type, component_id, init_func, args) + notes.append(create_note(Labels.SETUP, code_to_insert)) + return notes def parse(xml: str) -> StateMachine: @@ -364,7 +418,8 @@ def parse(xml: str) -> StateMachine: parsed_components = __parse_components(cgml_scheme.components) notes: List[ParserNote] = [ - *__generate_create_components_code(parsed_components, platform) + *__generate_create_components_code(parsed_components, platform), + *__generate_setup_function_code(parsed_components, platform), ] print(notes) diff --git a/compiler/fullgraphmlparser/graphml_to_cpp.py b/compiler/fullgraphmlparser/graphml_to_cpp.py index 8aa8c3c..eda5981 100644 --- a/compiler/fullgraphmlparser/graphml_to_cpp.py +++ b/compiler/fullgraphmlparser/graphml_to_cpp.py @@ -6,13 +6,14 @@ from typing import List, Tuple, Dict from aiofile import async_open try: - from .stateclasses import ParserState, ParserTrigger, StateMachine + from .stateclasses import ParserState, ParserTrigger, StateMachine, Labels from .graphml import * except ImportError: from compiler.fullgraphmlparser.stateclasses import ( ParserState, ParserTrigger, - StateMachine + StateMachine, + Labels ) from compiler.fullgraphmlparser.graphml import * @@ -45,7 +46,10 @@ class CppFileWriter: userFlag = False # Флаг на наличие кода для класса User list_notes_dict: Dict[str, List[str]] = {} - def __init__(self, state_machine: StateMachine) -> None: + def __init__(self, + state_machine: StateMachine, + create_setup=False) -> None: + self.create_setup = create_setup self.sm_name = state_machine.name self.player_signal = state_machine.signals notes_mapping: List[Tuple[str, str]] = [ @@ -66,7 +70,8 @@ def __init__(self, state_machine: StateMachine) -> None: 'user_methods_h'), ('User variables for c-file', 'user_variables_c'), - ('User methods for c-file', 'user_methods_c') + ('User methods for c-file', 'user_methods_c'), + (Labels.SETUP.value, 'setup') ] # TODO: Заставить это ***** работать со списками @@ -105,6 +110,13 @@ async def write_to_file(self, folder: str, extension: str): await self._write_initial() await self._write_states_definitions_recursively(self.states[0], 'SMs::%s::SM' % self._sm_capitalized_name()) await self._insert_file_template('footer_c.txt') + if self.notes_dict['setup'] or self.create_setup: + await self._insert_string('\nvoid setup() {') + await self._insert_string('\n\tsketch_ctor();') + await self._insert_string('\n\tQEvt event;') + await self._insert_string('\n\tQMsm_init(the_sketch, &event);') + await self._insert_string('\n\t' + '\n\t'.join(self.notes_dict['setup'].split('\n')[1:])) + await self._insert_string('\n}') if self.notes_dict['raw_cpp_code']: await self._insert_string('\n//Start of c code from diagram\n') await self._insert_string('\n'.join(self.notes_dict['raw_cpp_code'].split('\n')[1:]) + '\n') diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 193b41b..5b89cae 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -15,7 +15,7 @@ def create_note(label: 'Labels', content: str) -> 'ParserNote': return ParserNote( umlNote=_ParserNoteNodeLabel( nodeLabel=_ParserNoteNodeContent( - text=f'{label.value}:\n {content}') + text=f'{label.value}:\n{content}') ) ) @@ -28,6 +28,7 @@ class Labels(Enum): H = 'Declare variable in h-file' CPP = 'Code for cpp-file' CTOR = 'Constructor code' + SETUP = 'Setup function in cpp-file' USER_VAR_H = 'User variables for h-file' USER_VAR_C = 'User variables for c-file' USER_FUNC_H = 'User methods for h-file' diff --git a/test/test_cgml.py b/test/test_cgml.py index ef0b5ff..fbc6fa5 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -106,4 +106,4 @@ async def test_generating_code(init_platform): path = './test/test_folder/' with create_test_folder(path, 10): sm = parse(data) - await CppFileWriter(sm).write_to_file(path, 'ino') + await CppFileWriter(sm, True).write_to_file(path, 'ino') From f017fcee94e99a6f42a5d3e11e34ee4762f69a77 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 3 Apr 2024 13:48:58 +0800 Subject: [PATCH 10/14] generating loop function code, change Timer library --- compiler/CGML.py | 143 ++++++++++++++----- compiler/CJsonParser.py | 3 - compiler/fullgraphmlparser/graphml_to_cpp.py | 36 +++-- compiler/fullgraphmlparser/stateclasses.py | 4 + compiler/library/ino/source/Timer.h | 6 +- compiler/library/ino/source/Timer.ino | 9 +- test/test_cgml.py | 10 +- 7 files changed, 147 insertions(+), 64 deletions(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index 4f20b81..bfb0e68 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -3,11 +3,11 @@ import random from typing import Dict, List, Set, Any from copy import deepcopy +from string import Template from compiler.PlatformManager import PlatformManager from compiler.types.ide_types import Bounds -from string import Template -from compiler.types.platform_types import ClassParameter, Platform +from compiler.types.platform_types import ClassParameter, Component, Platform, Signal from compiler.types.inner_types import InnerComponent, InnerEvent, InnerTrigger from cyberiadaml_py.cyberiadaml_parser import CGMLParser from cyberiadaml_py.types.elements import ( @@ -25,11 +25,18 @@ create_note ) -TransitionId = str -StateId = str -ComponentId = str +_TransitionId = str +_StateId = str +_ComponentId = str -CALL_FUNCTION_TEMPLATE = Template('$id$delimeter($args);') +_CALL_FUNCTION_TEMPLATE = Template('$id$delimeter$method($args);') +_CHECK_SIGNAL_TEMPLATE = Template( + """ +if($condition) { + SIMPLE_DISPATCH(the_sketch, $signal); +} +""" +) class CGMLException(Exception): @@ -100,6 +107,7 @@ def __gen_id() -> int: def __process_state(state_id: str, cgml_state: CGMLState) -> ParserState: + """Process internal triggers and actions of state.""" inner_triggers: List[InnerEvent] = __parse_actions(cgml_state.actions) parser_triggers: List[ParserTrigger] = [] entry = '' @@ -175,9 +183,9 @@ def __process_transition( def __connect_transitions_to_states( - states: Dict[StateId, ParserState], + states: Dict[_StateId, ParserState], transitions: List[ParserTrigger] -) -> Dict[StateId, ParserState]: +) -> Dict[_StateId, ParserState]: """Add external triggers to states.""" states_with_external_trigs = deepcopy(states) for transition in transitions: @@ -190,10 +198,10 @@ def __connect_transitions_to_states( def __connect_parents_to_states( - parser_states: Dict[StateId, ParserState], - cgml_states: Dict[StateId, CGMLState], + parser_states: Dict[_StateId, ParserState], + cgml_states: Dict[_StateId, CGMLState], global_state: ParserState -) -> Dict[StateId, ParserState]: +) -> Dict[_StateId, ParserState]: """ Fill parent field for states. @@ -218,26 +226,32 @@ def __connect_parents_to_states( return states_with_parents -def __get_signals_set( - states: List[ParserState], - transitions: List[ParserTrigger]) -> Set[str]: - """Get signals set from all states and transitions.""" - signals = set() +def __get_all_triggers(states: List[ParserState], + transitions: List[ParserTrigger] + ) -> List[ParserTrigger]: + """Get all triggers from states and transitions.""" + triggers: List[ParserTrigger] = [] for state in states: - for internal_trig in state.trigs: - signals.add(internal_trig.name) + triggers.extend(state.trigs) + triggers.extend(transitions) + return triggers - for transition in transitions: - signals.add(transition.name) + +def __get_signals_set( + triggers: List[ParserTrigger]) -> Set[str]: + """Get signals set from triggers.""" + signals = set() + for trig in triggers: + signals.add(trig.name) return signals def __parse_components( components: List[CGMLComponent] -) -> Dict[ComponentId, InnerComponent]: +) -> Dict[_ComponentId, InnerComponent]: """Parse component's parameters.""" - inner_components: Dict[ComponentId, InnerComponent] = {} + inner_components: Dict[_ComponentId, InnerComponent] = {} for component in components: parameters: List[str] = component.parameters.split('\n') @@ -265,7 +279,7 @@ def __parse_components( def __generate_create_components_code( - components: Dict[ComponentId, InnerComponent], + components: Dict[_ComponentId, InnerComponent], platform: Platform) -> List[ParserNote]: """ Generate code, that create component's variables in h-file. @@ -288,7 +302,7 @@ def __generate_create_components_code( construct_parameters = platform_component.constructorParameters args: str = __create_parameters_sequence( component.parameters, construct_parameters) - code_to_insert = (f'{type} {component_id} =' + code_to_insert = (f'{type} {component_id} = ' f'{type}({args});\n') notes.append(create_note(Labels.H, code_to_insert)) return notes @@ -323,15 +337,15 @@ def __generate_function_call( method: str, args: str) -> str: """ - Generate function call code using CALL_FUNCTION_TEMPLATE. + Generate function call code using _CALL_FUNCTION_TEMPLATE. - Check component's static or platform's static. + Check component's static and platform's static. """ delimeter = '.' if (platform.staticComponents or platform.components[component_type].singletone): delimeter = '::' - return CALL_FUNCTION_TEMPLATE.substitute( + return _CALL_FUNCTION_TEMPLATE.substitute( { 'id': component_id, 'method': method, @@ -341,9 +355,65 @@ def __generate_function_call( ) +def __generate_signal_checker( + platform: Platform, + component_type: str, + component_id: str, + method: str, + signal_name: str +) -> str: + """Generate code part for checking and emitting signals using\ + _CHECK_SIGNAL_TEMPLATE.""" + platform_component: Component = platform.components[component_type] + signal: Signal = platform_component.signals[method] + call_method = signal.checkMethod + print(call_method) + condition = __generate_function_call( + platform, component_type, component_id, call_method, '') + return _CHECK_SIGNAL_TEMPLATE.substitute({ + 'signal': signal_name, + 'condition': condition.rstrip(';') + }) + + +def __generate_loop_function_code( + platform: Platform, + triggers: List[ParserTrigger], + components: Dict[_ComponentId, InnerComponent] +) -> List[ParserNote]: + checked_signals: Set[str] = set() + notes: List[ParserNote] = [] + + for trigger in triggers: + if trigger.name in checked_signals: + continue + # Предполагается, что в check_function лежит строка вида + # component.method + condition = trigger.check_function + if condition is None: + continue + component_id, method = condition.split('.') + type = components[component_id].type + code_to_insert = __generate_signal_checker( + platform, type, component_id, method, trigger.name) + notes.append(create_note(Labels.LOOP, code_to_insert)) + checked_signals.add(trigger.name) + return notes + + def __generate_setup_function_code( - components: Dict[ComponentId, InnerComponent], + components: Dict[_ComponentId, InnerComponent], platform: Platform) -> List[ParserNote]: + """ + Generate code for initialization components in setup function. + + Base of setup function generates in CppWriter! + + Generated code example: + ```cpp + QHsmSerial::init(9600); + ``` + """ notes: List[ParserNote] = [] for component_id, component in components.items(): type = component.type @@ -386,7 +456,7 @@ def parse(xml: str) -> StateMachine: ) # Parsing external transitions. transitions: List[ParserTrigger] = [] - cgml_transitions: Dict[TransitionId, + cgml_transitions: Dict[_TransitionId, CGMLTransition] = cgml_scheme.transitions for transition_id in cgml_transitions: cgml_transition = cgml_transitions[transition_id] @@ -394,8 +464,8 @@ def parse(xml: str) -> StateMachine: transition_id, cgml_transition)) # Parsing state's actions, internal triggers, entry/exit - states: Dict[StateId, ParserState] = {} - cgml_states: Dict[StateId, CGMLState] = cgml_scheme.states + states: Dict[_StateId, ParserState] = {} + cgml_states: Dict[_StateId, CGMLState] = cgml_scheme.states for state_id in cgml_states: cgml_state = cgml_states[state_id] states[state_id] = __process_state(state_id, cgml_state) @@ -411,17 +481,20 @@ def parse(xml: str) -> StateMachine: raise CGMLException('No initial state!') start_node: str = cgml_scheme.initial_state.target - signals = __get_signals_set( + # Мы получаем список триггеров для того, чтобы потом: + # 1) Сформировать набор всех сигналов + # 2) Сгенерировать проверки для вызова сигналов + all_triggers = __get_all_triggers( list(states_with_parents.values()), - transitions - ) + transitions) + signals = __get_signals_set(all_triggers) parsed_components = __parse_components(cgml_scheme.components) notes: List[ParserNote] = [ *__generate_create_components_code(parsed_components, platform), *__generate_setup_function_code(parsed_components, platform), + *__generate_loop_function_code(platform, all_triggers, parsed_components) ] - print(notes) return StateMachine( start_node=start_node, diff --git a/compiler/CJsonParser.py b/compiler/CJsonParser.py index a6a4b57..790c851 100644 --- a/compiler/CJsonParser.py +++ b/compiler/CJsonParser.py @@ -92,9 +92,6 @@ def _initComponent(self, component_name: str, component: Component) -> str: """Функция, которая в зависимости от типа компонента\ возвращает код его инициализации в h-файле.""" match component.type: - case 'Timer': - return (f'\nTimer {component_name} = Timer' - f'(the_sketch,{component_name}_timeout_SIG);') case 'QHsmSerial': return '' case _: diff --git a/compiler/fullgraphmlparser/graphml_to_cpp.py b/compiler/fullgraphmlparser/graphml_to_cpp.py index eda5981..40aa78e 100644 --- a/compiler/fullgraphmlparser/graphml_to_cpp.py +++ b/compiler/fullgraphmlparser/graphml_to_cpp.py @@ -48,33 +48,35 @@ class CppFileWriter: def __init__(self, state_machine: StateMachine, - create_setup=False) -> None: + create_setup=False, + create_loop=False) -> None: + self.create_loop = create_loop self.create_setup = create_setup self.sm_name = state_machine.name self.player_signal = state_machine.signals notes_mapping: List[Tuple[str, str]] = [ - ('Code for h-file', 'raw_h_code'), - ('Declare variable in h-file', + (Labels.H_INCLUDE.value, 'raw_h_code'), + (Labels.H.value, 'declare_h_code'), - ('Code for cpp-file', + (Labels.CPP.value, 'raw_cpp_code'), - ('Constructor fields', + (Labels.CTOR_FIELDS.value, 'constructor_fields'), - ('State fields', 'state_fields'), - ('Constructor code', + (Labels.STATE_FIELDS.value, 'state_fields'), + (Labels.CTOR.value, 'constructor_code'), - ('Event fields', 'event_fields'), - ('User variables for h-file', + (Labels.EVENT_FIELDS.value, 'event_fields'), + (Labels.USER_VAR_H.value, 'user_variables_h'), - ('User methods for h-file', + (Labels.USER_FUNC_H.value, 'user_methods_h'), - ('User variables for c-file', + (Labels.USER_VAR_C.value, 'user_variables_c'), - ('User methods for c-file', 'user_methods_c'), - (Labels.SETUP.value, 'setup') + (Labels.USER_FUNC_C.value, 'user_methods_c'), + (Labels.SETUP.value, 'setup'), + (Labels.LOOP.value, 'loop') ] - # TODO: Заставить это ***** работать со списками self.list_notes_dict: Dict[str, List[str]] = {key: [''] for _, key in notes_mapping} @@ -112,11 +114,15 @@ async def write_to_file(self, folder: str, extension: str): await self._insert_file_template('footer_c.txt') if self.notes_dict['setup'] or self.create_setup: await self._insert_string('\nvoid setup() {') - await self._insert_string('\n\tsketch_ctor();') + await self._insert_string('\n\tSketch_ctor();') await self._insert_string('\n\tQEvt event;') await self._insert_string('\n\tQMsm_init(the_sketch, &event);') await self._insert_string('\n\t' + '\n\t'.join(self.notes_dict['setup'].split('\n')[1:])) await self._insert_string('\n}') + if self.notes_dict['loop'] or self.create_loop: + await self._insert_string('\nvoid loop() {') + await self._insert_string('\n\t' + '\n\t'.join(self.notes_dict['loop'].split('\n')[1:])) + await self._insert_string('\n}') if self.notes_dict['raw_cpp_code']: await self._insert_string('\n//Start of c code from diagram\n') await self._insert_string('\n'.join(self.notes_dict['raw_cpp_code'].split('\n')[1:]) + '\n') diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 5b89cae..2473852 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -29,10 +29,14 @@ class Labels(Enum): CPP = 'Code for cpp-file' CTOR = 'Constructor code' SETUP = 'Setup function in cpp-file' + LOOP = 'Loop function in cpp-file' USER_VAR_H = 'User variables for h-file' USER_VAR_C = 'User variables for c-file' USER_FUNC_H = 'User methods for h-file' USER_FUNC_C = 'User methods for c-file' + CTOR_FIELDS = 'Constructor fields' + STATE_FIELDS = 'State fields' + EVENT_FIELDS = 'Event fields' @runtime_checkable diff --git a/compiler/library/ino/source/Timer.h b/compiler/library/ino/source/Timer.h index a07f937..7a090eb 100644 --- a/compiler/library/ino/source/Timer.h +++ b/compiler/library/ino/source/Timer.h @@ -24,20 +24,18 @@ class Timer { public: unsigned long difference; - Timer(QHsm* qhsm, QSignal signal); + Timer(); void reset(); void disable(); void enable(); - void timeout(); + bool timeout(); void setInterval(unsigned long interval); void start(unsigned long interval); private: bool _active; unsigned long _previous; unsigned long _interval; - QHsm* _qhsm; - QSignal _signal; bool _oneshot; }; diff --git a/compiler/library/ino/source/Timer.ino b/compiler/library/ino/source/Timer.ino index fd84df3..e8854e1 100644 --- a/compiler/library/ino/source/Timer.ino +++ b/compiler/library/ino/source/Timer.ino @@ -26,12 +26,10 @@ || @parameter oneshot if true, the timer will be disabled after the timeout || @parameter signal signal, that will be emmited by timeout */ -Timer::Timer(QHsm* qhsm, QSignal signal) +Timer::Timer() { _active = false; _previous = 0; - _qhsm = qhsm; - _signal = signal; } void Timer::reset() @@ -64,14 +62,15 @@ void Timer::enable() || | Check if it is time for this Timer to call the function || # */ -void Timer::timeout() +bool Timer::timeout() { difference -= millis() - _previous; if (_active && (millis() - _previous >= _interval)) { _previous = millis(); - SIGNAL_DISPATCH(_qhsm, _signal); + return true } + return false } /* diff --git a/test/test_cgml.py b/test/test_cgml.py index fbc6fa5..0257958 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -20,6 +20,7 @@ def init_platform(): return PlatformManager.load_platform('compiler/platforms/Arduino.json') + @contextmanager def create_test_folder(path: str, wait_time: int): try: @@ -45,6 +46,7 @@ def test_parse(path: str): with open(path, 'r') as f: parser.parseCGML(f.read()) + @pytest.mark.parametrize( 'path', [ @@ -105,5 +107,9 @@ async def test_generating_code(init_platform): data = f.read() path = './test/test_folder/' with create_test_folder(path, 10): - sm = parse(data) - await CppFileWriter(sm, True).write_to_file(path, 'ino') + try: + sm = parse(data) + await CppFileWriter(sm, True).write_to_file(path, 'ino') + print('Code generated!') + except Exception as e: + print(e) From b63c7ac15c47073aba4840cc017bc4dc31c7d303 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 3 Apr 2024 14:16:12 +0800 Subject: [PATCH 11/14] remove unused classes from fullgraphmlparser, generating tick actions in loop function. --- compiler/CGML.py | 51 +- .../.idea/fullgraphmlparser.iml | 17 - .../inspectionProfiles/Project_Default.xml | 6 - .../inspectionProfiles/profiles_settings.xml | 6 - compiler/fullgraphmlparser/.idea/misc.xml | 4 - compiler/fullgraphmlparser/.idea/modules.xml | 8 - .../runConfigurations/All_unit_tests.xml | 19 - compiler/fullgraphmlparser/.idea/vcs.xml | 6 - compiler/fullgraphmlparser/__init__.py | 3 - .../circular_consistency_test.py | 60 - compiler/fullgraphmlparser/cpp_to_graphml.py | 495 -------- .../fullgraphmlparser/cpp_to_graphml_test.py | 67 -- compiler/fullgraphmlparser/create_graphml.py | 515 -------- .../graphml_templates/choice_template.xml | 19 - .../graphml_templates/comment_template.xml | 6 - .../graphml_templates/start_template.xml | 20 - compiler/fullgraphmlparser/graphmltoqm.py | 92 -- compiler/fullgraphmlparser/logger.py | 4 - compiler/fullgraphmlparser/qm.py | 529 --------- compiler/fullgraphmlparser/qm_test.py | 117 -- .../samek_consistency_test.py | 65 - compiler/fullgraphmlparser/service.cpp | 0 compiler/fullgraphmlparser/service_files.py | 82 -- compiler/fullgraphmlparser/stateclasses.py | 8 +- compiler/fullgraphmlparser/test.graphml | 234 ---- compiler/fullgraphmlparser/test_utils.py | 24 - .../fullgraphmlparser/testdata/ability.cpp | 217 ---- .../testdata/ability.graphml | 227 ---- compiler/fullgraphmlparser/testdata/ability.h | 76 -- .../testdata/character.graphml | 1058 ----------------- .../fullgraphmlparser/testdata/cheetcodes.txt | 4 - .../fullgraphmlparser/testdata/choice1.cpp | 212 ---- .../testdata/choice1.graphml | 211 ---- compiler/fullgraphmlparser/testdata/choice1.h | 61 - .../testdata/eventHadlers.cpp | 26 - .../testdata/eventHandlers.h | 24 - .../fullgraphmlparser/testdata/health.cpp | 0 .../fullgraphmlparser/testdata/health.graphml | 441 ------- compiler/fullgraphmlparser/testdata/health.h | 91 -- .../fullgraphmlparser/testdata/kaCounter.cpp | 236 ---- .../testdata/kaCounter.graphml | 269 ----- .../fullgraphmlparser/testdata/kaCounter.h | 63 - compiler/fullgraphmlparser/testdata/kaTet.cpp | 264 ---- .../fullgraphmlparser/testdata/kaTet.graphml | 309 ----- compiler/fullgraphmlparser/testdata/kaTet.h | 64 - compiler/fullgraphmlparser/testdata/main.cpp | 76 -- .../testdata/oregonPlayer.cpp | 639 ---------- .../testdata/oregonPlayer.graphml | 152 --- .../fullgraphmlparser/testdata/oregonPlayer.h | 112 -- .../testdata/player_type.cpp | 424 ------- .../testdata/player_type.graphml | 468 -------- .../fullgraphmlparser/testdata/player_type.h | 89 -- compiler/fullgraphmlparser/testdata/qhsm.h | 98 -- .../fullgraphmlparser/testdata/service.cpp | 14 - compiler/types/platform_types.py | 1 + 55 files changed, 55 insertions(+), 8328 deletions(-) delete mode 100644 compiler/fullgraphmlparser/.idea/fullgraphmlparser.iml delete mode 100644 compiler/fullgraphmlparser/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 compiler/fullgraphmlparser/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 compiler/fullgraphmlparser/.idea/misc.xml delete mode 100644 compiler/fullgraphmlparser/.idea/modules.xml delete mode 100644 compiler/fullgraphmlparser/.idea/runConfigurations/All_unit_tests.xml delete mode 100644 compiler/fullgraphmlparser/.idea/vcs.xml delete mode 100644 compiler/fullgraphmlparser/__init__.py delete mode 100644 compiler/fullgraphmlparser/circular_consistency_test.py delete mode 100644 compiler/fullgraphmlparser/cpp_to_graphml.py delete mode 100644 compiler/fullgraphmlparser/cpp_to_graphml_test.py delete mode 100644 compiler/fullgraphmlparser/create_graphml.py delete mode 100644 compiler/fullgraphmlparser/graphml_templates/choice_template.xml delete mode 100644 compiler/fullgraphmlparser/graphml_templates/comment_template.xml delete mode 100644 compiler/fullgraphmlparser/graphml_templates/start_template.xml delete mode 100644 compiler/fullgraphmlparser/graphmltoqm.py delete mode 100644 compiler/fullgraphmlparser/logger.py delete mode 100644 compiler/fullgraphmlparser/qm.py delete mode 100644 compiler/fullgraphmlparser/qm_test.py delete mode 100644 compiler/fullgraphmlparser/samek_consistency_test.py delete mode 100644 compiler/fullgraphmlparser/service.cpp delete mode 100644 compiler/fullgraphmlparser/service_files.py delete mode 100644 compiler/fullgraphmlparser/test.graphml delete mode 100644 compiler/fullgraphmlparser/test_utils.py delete mode 100644 compiler/fullgraphmlparser/testdata/ability.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/ability.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/ability.h delete mode 100644 compiler/fullgraphmlparser/testdata/character.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/cheetcodes.txt delete mode 100644 compiler/fullgraphmlparser/testdata/choice1.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/choice1.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/choice1.h delete mode 100644 compiler/fullgraphmlparser/testdata/eventHadlers.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/eventHandlers.h delete mode 100644 compiler/fullgraphmlparser/testdata/health.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/health.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/health.h delete mode 100644 compiler/fullgraphmlparser/testdata/kaCounter.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/kaCounter.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/kaCounter.h delete mode 100644 compiler/fullgraphmlparser/testdata/kaTet.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/kaTet.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/kaTet.h delete mode 100644 compiler/fullgraphmlparser/testdata/main.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/oregonPlayer.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/oregonPlayer.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/oregonPlayer.h delete mode 100644 compiler/fullgraphmlparser/testdata/player_type.cpp delete mode 100644 compiler/fullgraphmlparser/testdata/player_type.graphml delete mode 100644 compiler/fullgraphmlparser/testdata/player_type.h delete mode 100644 compiler/fullgraphmlparser/testdata/qhsm.h delete mode 100644 compiler/fullgraphmlparser/testdata/service.cpp diff --git a/compiler/CGML.py b/compiler/CGML.py index bfb0e68..b807ff9 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -7,8 +7,13 @@ from compiler.PlatformManager import PlatformManager from compiler.types.ide_types import Bounds -from compiler.types.platform_types import ClassParameter, Component, Platform, Signal from compiler.types.inner_types import InnerComponent, InnerEvent, InnerTrigger +from compiler.types.platform_types import ( + ClassParameter, + Component, + Platform, + Signal +) from cyberiadaml_py.cyberiadaml_parser import CGMLParser from cyberiadaml_py.types.elements import ( CGMLElements, @@ -376,11 +381,21 @@ def __generate_signal_checker( }) -def __generate_loop_function_code( +def __generate_loop_signal_checks_code( platform: Platform, triggers: List[ParserTrigger], components: Dict[_ComponentId, InnerComponent] ) -> List[ParserNote]: + """ + Generate code for checking signals in loop function. + + Generated code example: + ```cpp + if(timer1.timeout()) { + SIMPLE_DISPATCH(the_sketch, timer1_timeout); + } + ``` + """ checked_signals: Set[str] = set() notes: List[ParserNote] = [] @@ -401,6 +416,21 @@ def __generate_loop_function_code( return notes +def __generate_loop_tick_actions_code( + platform: Platform, + components: Dict[_ComponentId, InnerComponent] +) -> List[ParserNote]: + notes: List[ParserNote] = [] + for component_id, component in components.items(): + platform_component: Component = platform.components[component.type] + loop_actions: List[str] = platform_component.loopActions + for method in loop_actions: + code_to_insert = __generate_function_call( + platform, component.type, component_id, method, '') + notes.append(create_note(Labels.LOOP, code_to_insert)) + return notes + + def __generate_setup_function_code( components: Dict[_ComponentId, InnerComponent], platform: Platform) -> List[ParserNote]: @@ -433,9 +463,21 @@ def __generate_setup_function_code( def parse(xml: str) -> StateMachine: + """ + Parse XML with cyberiadaml-py library and convert it\ + to StateMachine for CppWriter class. + + Generate code: + - creating component's variables; + - initialization components in setup function; + - signal checks in loop function; + """ parser = CGMLParser() cgml_scheme: CGMLElements = parser.parseCGML(xml) platform: Platform = PlatformManager.getPlatform(cgml_scheme.platform) + if not platform.compile: + raise CGMLException( + f'Platform {platform.name} not supporting compiling!') global_state = ParserState( name='global', type='group', @@ -493,7 +535,10 @@ def parse(xml: str) -> StateMachine: notes: List[ParserNote] = [ *__generate_create_components_code(parsed_components, platform), *__generate_setup_function_code(parsed_components, platform), - *__generate_loop_function_code(platform, all_triggers, parsed_components) + *__generate_loop_tick_actions_code(platform, parsed_components), + *__generate_loop_signal_checks_code(platform, + all_triggers, + parsed_components) ] return StateMachine( diff --git a/compiler/fullgraphmlparser/.idea/fullgraphmlparser.iml b/compiler/fullgraphmlparser/.idea/fullgraphmlparser.iml deleted file mode 100644 index 38a9dd6..0000000 --- a/compiler/fullgraphmlparser/.idea/fullgraphmlparser.iml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/inspectionProfiles/Project_Default.xml b/compiler/fullgraphmlparser/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 9940ce4..0000000 --- a/compiler/fullgraphmlparser/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/inspectionProfiles/profiles_settings.xml b/compiler/fullgraphmlparser/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/compiler/fullgraphmlparser/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/misc.xml b/compiler/fullgraphmlparser/.idea/misc.xml deleted file mode 100644 index 47df7d1..0000000 --- a/compiler/fullgraphmlparser/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/modules.xml b/compiler/fullgraphmlparser/.idea/modules.xml deleted file mode 100644 index abac899..0000000 --- a/compiler/fullgraphmlparser/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/runConfigurations/All_unit_tests.xml b/compiler/fullgraphmlparser/.idea/runConfigurations/All_unit_tests.xml deleted file mode 100644 index cb08ef2..0000000 --- a/compiler/fullgraphmlparser/.idea/runConfigurations/All_unit_tests.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/.idea/vcs.xml b/compiler/fullgraphmlparser/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/compiler/fullgraphmlparser/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/__init__.py b/compiler/fullgraphmlparser/__init__.py deleted file mode 100644 index 0d9f729..0000000 --- a/compiler/fullgraphmlparser/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import sys -sys.path.append("./compiler/fullgraphmlparser") -sys.path.append("..") \ No newline at end of file diff --git a/compiler/fullgraphmlparser/circular_consistency_test.py b/compiler/fullgraphmlparser/circular_consistency_test.py deleted file mode 100644 index 02367bf..0000000 --- a/compiler/fullgraphmlparser/circular_consistency_test.py +++ /dev/null @@ -1,60 +0,0 @@ -# import os -# import shutil -# import unittest - -# import cpp_to_graphml -# import graphmltoqm -# import test_utils - -# # Does full conversion cycle (C++ --> graphml --> qm --> C++) -# class CircularConsistencyTest(unittest.TestCase): -# def setUp(self): -# test_utils.removeOutputFolder() -# os.makedirs('./testdata/test_output') - -# def tearDown(self): -# test_utils.removeOutputFolder() - -# def testFullCycle(self): -# parser = cpp_to_graphml.StateMachineParser(cpp_file_path='./testdata/oregonPlayer.cpp') -# sm1 = parser.Parse() -# cpp_to_graphml.StateMachineWriter(sm1).WriteToFile('./testdata/test_output/oregonPlayer.graphml', -# './testdata/oregonPlayer.graphml') -# graphmltoqm.main('./testdata/test_output/oregonPlayer.graphml') -# shutil.copy('./testdata/qhsm.h', './testdata/test_output') -# shutil.copy('./testdata/eventHandlers.h', './testdata/test_output') -# parser2 = cpp_to_graphml.StateMachineParser(cpp_file_path='./testdata/test_output/oregonPlayer.cpp') -# sm2 = parser2.Parse() - -# self.assertEqual(len(sm1.states), len(sm2.states)) -# self.assertEqual(sm1.state_fields, sm2.state_fields) -# self.assertEqual(sm1.event_fields, sm2.event_fields) -# self.assertEqual(sm1.constructor_fields, sm2.constructor_fields) -# self.assertEqual(sm1.constructor_code, sm2.constructor_code) -# self.assertEqual(sm1.raw_h_code, sm2.raw_h_code) -# self.assertEqual(sm1.initial_state, sm2.initial_state) -# self.assertEqual(sm1.initial_code, sm2.initial_code) -# for state_name in sorted(sm1.states.keys()): -# s1 = sm1.states[state_name] -# self.assertIn(state_name, sm2.states) -# s2 = sm2.states[state_name] -# self.assertEqual(s1.state_name, s2.state_name) -# self.assertEqual(s1.parent_state_name, s2.parent_state_name, s1.state_name) - -# def names(state_list): -# return [s.state_name for s in state_list] - -# self.assertEqual(names(s1.child_states), names(s2.child_states)) -# self.assertCountEqual(s1.event_handlers, s2.event_handlers) - -# self.maxDiff = None - -# # This one is quite fragile as literally any change in the output will break it. Not sure if it's actually needed. -# with open('./testdata/oregonPlayer.cpp', 'r') as f: -# sm1_cpp_content = f.read() -# with open('./testdata/test_output/oregonPlayer.cpp', 'r') as f: -# sm2_cpp_content = f.read() -# self.assertEqual(sm1_cpp_content, sm2_cpp_content) - -# if __name__ == '__main__': -# unittest.main() diff --git a/compiler/fullgraphmlparser/cpp_to_graphml.py b/compiler/fullgraphmlparser/cpp_to_graphml.py deleted file mode 100644 index 346b71a..0000000 --- a/compiler/fullgraphmlparser/cpp_to_graphml.py +++ /dev/null @@ -1,495 +0,0 @@ -import os -import re -import sys -from dataclasses import dataclass, field -from typing import Dict, List, Optional - -import clang.cindex -from lxml import etree - -import create_graphml -import graphmltoqm -import qm - -try: - clang_index = clang.cindex.Index.create() -except: - # Hack to support linux (e.g. Github Actions) - clang.cindex.Config.set_library_file('/usr/lib/llvm-8/lib/libclang.so.1') - clang_index = clang.cindex.Index.create() - -# Зависимости: -# - clang/llvm -# Можно установить через 'choco install llvm'. -# - clang python bindings -# Можно установить через 'pip install clang'. -# -# Запуск: -# py -3 cpp_to_graphml.py <путь к cpp-файлу диаграммы> - - -@dataclass -class EventHandler: - state_from: str - state_to: str - event_type: str - condition: Optional[str] - statements: List[str] - - -@dataclass -class State: - state_name: str - parent_state_name: Optional[str] = None - event_handlers: List[EventHandler] = field(default_factory=list) - child_states: List['State'] = field(default_factory=list) - - -@dataclass -class StateMachineCpp: - constructor_code: str = '' - initial_code: str = '' - initial_state: str = '' - states: Dict[str, State] = field(default_factory=dict) - - -@dataclass -class StateMachineHeader: - raw_h_code: str = '' - state_fields: str = '' - event_fields: str = '' - constructor_fields: str = '' - - -@dataclass -class StateMachine(StateMachineCpp, StateMachineHeader): - pass - - -class ParsingContext: - state_machine_name: str - file_path: str - _file_content: str - - def __init__(self, file_path: str): - filename = os.path.splitext(os.path.basename(file_path))[0] - self.state_machine_name = filename[:1].upper() + filename[1:] - self.file_path = file_path - with open(file_path, 'r', newline='') as f: - self._file_content = ''.join(f.readlines()) - - def GetNodeText(self, node: clang.cindex.Cursor) -> str: - source_range = node.extent - return self._file_content[source_range.start.offset:source_range.end.offset + 1] - - def RemoveStateMachinNamePrefix(self, s: str) -> str: - return s[(len(self.state_machine_name) + 1):] - - def CamelCaseStateMachinName(self) -> str: - return self.state_machine_name[0].lower() + self.state_machine_name[1:] - - -class StateMachineParser: - def __init__(self, cpp_file_path: str): - self.cpp_parser = CppParser(cpp_file_path = cpp_file_path) - self.header_parser = HeaderParser(header_file_path = os.path.splitext(cpp_file_path)[0]+'.h') - - def Parse(self): - cpp_parse_result = self.cpp_parser.Parse() - header_parse_result = self.header_parser.Parse() - return StateMachine(constructor_code=cpp_parse_result.constructor_code, states=cpp_parse_result.states, - initial_code=cpp_parse_result.initial_code, initial_state=cpp_parse_result.initial_state, - raw_h_code=header_parse_result.raw_h_code, state_fields=header_parse_result.state_fields, - event_fields=header_parse_result.event_fields, - constructor_fields=header_parse_result.constructor_fields) - - -class CppParser: - def __init__(self, cpp_file_path: str): - translationUnit = clang_index.parse(cpp_file_path) - self.ctx = ParsingContext(cpp_file_path) - self.root_node = translationUnit.cursor - self.result = StateMachineCpp() - - def Parse(self) -> StateMachineCpp: - self._TraverseAST(self.root_node) - self._UpdateChilds() - return self.result - - def _UpdateChilds(self): - for state_name in self.result.states: - state = self.result.states[state_name] - if state.parent_state_name: - self.result.states[state.parent_state_name].child_states.append(state) - - def _TraverseAST(self, node): - if self._IsStateFunction(node): - state = StateParser(self.ctx, node).Parse() - self.result.states[state.state_name] = state -# print(''' -# State discovered: -# name = %s, parent = %s, handlers = %s -# ''' % (state.state_name, state.parent_state_name, state.handlers.keys())) - - if self._IsCtorFunction(node): - for childNode in node.get_children(): - if childNode.kind == clang.cindex.CursorKind.COMPOUND_STMT: - constructor_statements = [] - for childChildNode in childNode.get_children(): - node_text = self.ctx.GetNodeText(childChildNode) - if '\n' in node_text: - offset = childChildNode.extent.start.column - 1 - unindent = lambda s: s[offset:] - lines = node_text.split('\n') - lines = [lines[0]] + [unindent(l) for l in lines[1:]] - node_text = '\n'.join(lines) - constructor_statements.append(node_text) - - # We skip the very first statement as it always 'OregonPlayer *me = &oregonPlayer;' - # which added automatically - # We also skip the last as it's parent constructor call which is also added automatically - self.result.constructor_code = '\n'.join(constructor_statements[1:-1]).rstrip() - - break - - # Only 1/2-line functions are supported at the moment - if self._IsInitialFunction(node): - body_node = list(node.get_children())[-1] - child_nodes = list(body_node.get_children()) - assert len(child_nodes) in [1, 2] - self.result.initial_code = self.ctx.GetNodeText(child_nodes[0]) - r = r'Q_TRAN\(&%s_([a-z_]*)\);' % self.ctx.state_machine_name - self.result.initial_state = re.search(r, self.ctx.GetNodeText(child_nodes[-1]))[1] - - for childNode in node.get_children(): - self._TraverseAST(childNode) - - def _IsCtorFunction(self, node): - return (node.kind == clang.cindex.CursorKind.FUNCTION_DECL and - node.spelling == self.ctx.state_machine_name + '_ctor') - - def _IsInitialFunction(self, node): - return (node.kind == clang.cindex.CursorKind.FUNCTION_DECL and - node.spelling == self.ctx.state_machine_name + '_initial' and - list(node.get_children())[-1].kind == clang.cindex.CursorKind.COMPOUND_STMT) - - def _IsStateFunction(self, node): - return (node.kind == clang.cindex.CursorKind.FUNCTION_DECL and - node.spelling.startswith(self.ctx.state_machine_name + '_') and - not node.spelling.endswith('_ctor')) - - -class HeaderParser: - def __init__(self, header_file_path: str): - self.header_file_path = header_file_path - self.ctx = ParsingContext(header_file_path) - self.root_node = clang_index.parse(header_file_path).cursor - self.result = StateMachineHeader() - - def Parse(self) -> str: - self._ExtractHCode() - for node in self.root_node.get_children(): - if node.kind == clang.cindex.CursorKind.STRUCT_DECL: - attributes = list(node.get_children()) - if node.displayname == self.ctx.CamelCaseStateMachinName() + 'QEvt': - assert self.ctx.GetNodeText(attributes[0]) == 'QEvt super;' - self.result.event_fields = '\n'.join([self.ctx.GetNodeText(attr) for attr in attributes[1:]]) - - if attributes and attributes[0].type.spelling == 'QHsm': - self.result.state_fields = '\n'.join([self.ctx.GetNodeText(attr) for attr in attributes[1:]]) - - if node.kind == clang.cindex.CursorKind.FUNCTION_DECL \ - and node.spelling == self.ctx.state_machine_name + '_ctor': - # In function declaration last symbol is either ',' or ' - convert = lambda attr: '%s %s;' % (attr.type.spelling, attr.spelling) - self.result.constructor_fields = '\n'.join([convert(attr) for attr in node.get_children()]) - - return self.result - - def _ExtractHCode(self): - with open(self.header_file_path, 'r') as f: - lines = f.readlines() - begin = None - end = None - for i, line in enumerate(lines): - # TODO: Deduplicate those lines with ones in graphml_to_cpp.py - if '//Start of h code from diagram' in line: - begin = i + 1 - if '//End of h code from diagram' in line: - end = i - self.result.raw_h_code = ''.join(lines[begin:end]) if (begin and end) else '' - - -class StateParser: - def __init__(self, ctx: ParsingContext, root_node): - self.ctx = ctx - self.root_node = root_node - self.result = State(state_name=self.ctx.RemoveStateMachinNamePrefix( - root_node.spelling)) - - def Parse(self): - self._TraverseAST(self.root_node) - return self.result - - def _TraverseAST(self, node): - if node.kind == clang.cindex.CursorKind.CASE_STMT: - h = EventHandlerParser(self.ctx, node, self.result.state_name).Parse() -# print('''EventHandler: -# Event: %s, direction: %s --> %s, Code: -# %s -# ''' % (h.event_type, h.state_name, h.target_state_name, '\n'.join(h.statements))) - self.result.event_handlers.extend(h.handlers) - - if node.kind == clang.cindex.CursorKind.DEFAULT_STMT: - # That's how subtree of such node is expected to look like (generated by 'clang -Xclang -ast-dump .cpp') - # `-DefaultStmt 0x7ffff3a84a08 - # `-CompoundStmt 0x7ffff3a849e8 - # |-BinaryOperator 0x7ffff3a849b8 'QState':'int' lvalue '=' - # | |-DeclRefExpr 0x7ffff3a84628 'QState':'int' lvalue Var 0x7ffff3a82dd0 'status_' 'QState':'int' - # | `-ParenExpr 0x7ffff3a84998 <./qhsm.h:71:5, line:72:26> 'QState':'int' - # | `-BinaryOperator 0x7ffff3a84970 'QState':'int' ',' - # | |-BinaryOperator 0x7ffff3a84880 'QStateHandler':'QState (*)(void *const, const QEvt *const)' lvalue '=' - # | | |-MemberExpr 0x7ffff3a84758 'QStateHandler':'QState (*)(void *const, const QEvt *const)' lvalue ->effective_ 0x7ffff3a1b3a8 - # | | | `-ParenExpr 0x7ffff3a84738 'QHsm *' - # | | | `-ParenExpr 0x7ffff3a84718 'QHsm *' - # | | | `-CStyleCastExpr 0x7ffff3a846f0 'QHsm *' - # | | | `-ImplicitCastExpr 0x7ffff3a846d8 'OregonPlayer *' - # | | | `-ParenExpr 0x7ffff3a846b8 'OregonPlayer *const' lvalue - # | | | `-DeclRefExpr 0x7ffff3a84650 'OregonPlayer *const' lvalue ParmVar 0x7ffff3a82c10 'me' 'OregonPlayer *const' - # | | `-ParenExpr 0x7ffff3a84860 'QStateHandler':'QState (*)(void *const, const QEvt *const)' - # | | `-CStyleCastExpr 0x7ffff3a84838 'QStateHandler':'QState (*)(void *const, const QEvt *const)' - # | | `-ParenExpr 0x7ffff3a84818 'QState (*)(OregonPlayer *const, const QEvt *const)' - # | | `-UnaryOperator 0x7ffff3a847b8 'QState (*)(OregonPlayer *const, const QEvt *const)' prefix '&' - # | | `-DeclRefExpr 0x7ffff3a84790 'QState (OregonPlayer *const, const QEvt *const)' lvalue Function 0x7ffff3a692b0 'OregonPlayer_global' 'QState (OregonPlayer *const, const QEvt *const)' - # | `-CStyleCastExpr 0x7ffff3a84948 <./qhsm.h:72:5, col:25> 'QState':'int' - # | `-ImplicitCastExpr 0x7ffff3a84930 'QState':'int' - # | `-ParenExpr 0x7ffff3a84910 '(anonymous enum at ./qhsm.h:46:1)' - # | `-DeclRefExpr 0x7ffff3a848a8 '(anonymous enum at ./qhsm.h:46:1)' EnumConstant 0x7ffff3a1b090 'Q_RET_SUPER' '(anonymous enum at ./qhsm.h:46:1) - # `-BreakStmt 0x7ffff3a849e0 - compound_stmt = list(node.get_children())[0] - assert compound_stmt.kind == clang.cindex.CursorKind.COMPOUND_STMT, self.ctx.GetNodeText( - compound_stmt) - binary_op = list(compound_stmt.get_children())[0] - assert binary_op.kind == clang.cindex.CursorKind.BINARY_OPERATOR, self.ctx.GetNodeText( - binary_op) - rhs = list(binary_op.get_children())[1] - assert rhs.kind == clang.cindex.CursorKind.PAREN_EXPR, self.ctx.GetNodeText( - rhs) - # GetText(rhs) should look like Q_SUPER(&OregonPlayer_global); - self.result.parent_state_name = self.ctx.GetNodeText( - rhs)[len('Q_SUPER(&'):-len(');')] - if self.result.parent_state_name == 'QHsm_top': - self.result.parent_state_name = None - else: - self.result.parent_state_name = self.ctx.RemoveStateMachinNamePrefix( - self.result.parent_state_name) - - for childNode in node.get_children(): - self._TraverseAST(childNode) - - -class EventHandlerParser: - handlers: List[EventHandler] - root_node: clang.cindex.Cursor - event_type: str - state_from: str - - def __init__(self, ctx: ParsingContext, root_node, state_from): - self.ctx = ctx - assert root_node.kind == clang.cindex.CursorKind.CASE_STMT, root_node.kind - # That's how subtree of such node is expected to look like (generated by 'clang -Xclang -ast-dump .cpp') - # |-CaseStmt 0x7ffff3a83de8 - # | |-ImplicitCastExpr 0x7ffff3a84a80 'QSignal':'int' - # | | `-DeclRefExpr 0x7ffff3a83dc0 'PlayerSignals' EnumConstant 0x7ffff3a28b28 'PILL_RESET_SIG' 'PlayerSignals' - # | `-CompoundStmt 0x7ffff3a84318 - children = list(root_node.get_children()) - self.handlers = [] - self.event_type = list(children[0].get_children())[0].spelling - self.root_node = children[1] - assert self.root_node.kind == clang.cindex.CursorKind.COMPOUND_STMT, self.root_node.kind - self.state_from = state_from - - def Parse(self): - self.handlers = self._HandlersFromCompountStmt(self.root_node) - return self - - def _HandlersFromCompountStmt(self, compount_stmt_node): - assert compount_stmt_node.kind == clang.cindex.CursorKind.COMPOUND_STMT, compount_stmt_node.kind - statements = [] - condition = None - state_to = None - - for node in compount_stmt_node.get_children(): - # There is no support for other statements / flow control (e.g. for (...)). - # So let's fail fast if something unexpected was encountered. - assert (node.kind == clang.cindex.CursorKind.CALL_EXPR or - node.kind == clang.cindex.CursorKind.BINARY_OPERATOR or - node.kind == clang.cindex.CursorKind.UNARY_OPERATOR or - node.kind == clang.cindex.CursorKind.BREAK_STMT or - node.kind == clang.cindex.CursorKind.IF_STMT), self.ctx.GetNodeText(node) - - if node.kind == clang.cindex.CursorKind.IF_STMT: - children = list(node.get_children()) - assert len(children) == 3 - condition, if_branch, else_branch = children - if_handler = self._HandlersFromCompountStmt(if_branch)[0] - if_handler.condition = self.ctx.GetNodeText(condition)[:-1] # cut out last ')' - else_handler = self._HandlersFromCompountStmt(else_branch)[0] - else_handler.condition = 'else' - return [if_handler, else_handler] - - if node.kind == clang.cindex.CursorKind.BREAK_STMT: - return [EventHandler(state_from=self.state_from, state_to=state_to, condition=condition, statements=statements)] - - # It's a bit hacky: - # 1) BINARY_OPERATOR doesn't necessarily mean equality operator. Can be some weird dangling statement like 'a < Foo(5);' - # 2) It would be better to check if it is a status_ assignment by checking first child, which should be DECL_REF_EXPR node - if node.kind == clang.cindex.CursorKind.BINARY_OPERATOR and self.ctx.GetNodeText(node).startswith('status_ = '): - # That's how subtree of such node is expected to look like (generated by 'clang -Xclang -ast-dump .cpp') - # |-BinaryOperator 0x7ffff3a845d0 'QState':'int' lvalue '=' - # | |-DeclRefExpr 0x7ffff3a844c0 'QState':'int' lvalue Var 0x7ffff3a82dd0 'status_' 'QState':'int' - # | `-ParenExpr 0x7ffff3a845b0 <./qhsm.h:66:21, col:45> 'QState':'int' - # | `-CStyleCastExpr 0x7ffff3a84588 'QState':'int' - # | `-ImplicitCastExpr 0x7ffff3a84570 'QState':'int' - # | `-ParenExpr 0x7ffff3a84550 '(anonymous enum at ./qhsm.h:46:1)' - # | `-DeclRefExpr 0x7ffff3a844e8 '(anonymous enum at ./qhsm.h:46:1)' EnumConstant 0x7ffff3a1b120 'Q_RET_HANDLED' '(anonymous enum at ./qhsm.h:46:1)' - rhs = list(node.get_children())[1] - if self.ctx.GetNodeText(rhs) == 'Q_HANDLED();': - state_to = self.state_from - else: - # Cut state name from a string like 'Q_TRAN(&OregonPlayer_ghoul_wounded);' - state_to = self.ctx.RemoveStateMachinNamePrefix( - self.ctx.GetNodeText(rhs)[len('Q_TRAN(&'):-len(');')] - ) - return [EventHandler(state_from=self.state_from, state_to=state_to, condition=condition, statements=statements, event_type=self.event_type)] - else: - statements.append(self.ctx.GetNodeText(node)) - - -class StateMachineWriter: - state_name_to_node_name: Dict[str, str] = field(default_factory=dict) - edge_id: int - - # TODO(aeremin) Pass some data object instead of whole StateMachineParser - def __init__(self, state_machine: StateMachine): - self.state_machine = state_machine - - def WriteToFile(self, filename: str, previous_filename: Optional[str] = None): - previous_filename = previous_filename or filename - previous_states = [] - if os.path.isfile(previous_filename): - # previous_filename = os.path.splitext(previous_filename)[0] - previous_states, minx, miny = graphmltoqm.get_states_from_graphml(previous_filename) - - graphml_root_node = create_graphml.prepare_graphml() - self.graph = create_graphml.create_graph(graphml_root_node, 'G') - create_graphml.add_start_state(self.graph, "n0") - self.state_name_to_node_name = {} - self.edge_id = 1 - - child_index = 1 - for state in self.state_machine.states['global'].child_states: - self._OutputState(state, child_index, self.graph, previous_states) - child_index += 1 - - create_graphml.add_edge(self.graph, "e0", - "n0", self.state_name_to_node_name[self.state_machine.initial_state], - self.state_machine.initial_code, - 0, 0, 0, 0, []) - - for state_name in self.state_machine.states: - state = self.state_machine.states[state_name] - for h in state.event_handlers: - if not h.state_to: - continue - if h.state_from == h.state_to: - continue - self._OutputEdge(h) - - create_graphml.get_constructor_code_comment(self.graph, 'constructor_code', self.state_machine.constructor_code) - create_graphml.get_constructor_fields_comment(self.graph, 'constructor_fields', self.state_machine.constructor_fields) - create_graphml.get_event_fields_comment(self.graph, 'event_fields', self.state_machine.event_fields) - create_graphml.get_h_code_comment(self.graph, "raw_h_code", self.state_machine.raw_h_code) - create_graphml.get_state_fields_comment(self.graph, "state_fields", self.state_machine.state_fields) - - create_graphml.finish_graphml(graphml_root_node) - xml_tree = etree.ElementTree(graphml_root_node) - xml_tree.write( - filename, xml_declaration=True, encoding="UTF-8") - - def _OutputEdge(self, h: EventHandler): - link_caption = h.event_type - assert link_caption.endswith('_SIG') - link_caption = link_caption[:-len('_SIG')] - if h.condition: - link_caption = link_caption + '[%s]' % h.condition - - if h.statements: - link_caption = link_caption + '/' + '\n'.join(h.statements) - create_graphml.add_edge(self.graph, "e%d" % self.edge_id, - self.state_name_to_node_name[h.state_from], - self.state_name_to_node_name[h.state_to], - link_caption, - 0, 0, 0, 0, []) - self.edge_id += 1 - - def _OutputState(self, state, index_as_child, graph_parent, previous_states): - state_content = list() - for h in state.event_handlers: - if h.state_from != h.state_to: - continue - event_type = h.event_type - if event_type == 'Q_ENTRY_SIG': - event_type = 'entry' - elif event_type == 'Q_EXIT_SIG': - event_type = 'exit' - else: - assert event_type.endswith('_SIG') - event_type = event_type[:-len('_SIG')] - - state_content.append( - ('%s' % event_type) + ('[%s]' % h.condition if h.condition else '') + '/') - for statement in h.statements: - for line in statement.split('\n'): - state_content.append(' ' + line) - state_content.append('') - - full_node_name = (self.state_name_to_node_name[state.parent_state_name] + ':' if state.parent_state_name != 'global' - else '') + 'n%d' % index_as_child - self.state_name_to_node_name[state.state_name] = full_node_name - h = 100 - w = 200 - x0 = 259 - y0 = 255 - previous_states_with_name = [s for s in previous_states if s.name == state.state_name] - if previous_states_with_name: - print('For state %s using cached coordinates' % state.state_name) - h = previous_states_with_name[0].height * qm.divider - w = previous_states_with_name[0].width * qm.divider - x0 = previous_states_with_name[0].x * qm.divider - y0 = previous_states_with_name[0].y * qm.divider - else: - print('For state %s using DUMB coordinates' % state.state_name) - - if state.child_states: - group_node = create_graphml.add_group_node(graph_parent, state.state_name, '\n'.join( - state_content), full_node_name, h, w, x0, y0) - parent = create_graphml.create_graph( - group_node, full_node_name + ':') - - child_index = 0 - for child_state in state.child_states: - self._OutputState(child_state, child_index, parent, previous_states) - child_index += 1 - else: - create_graphml.add_simple_node(graph_parent, state.state_name, '\n'.join( - state_content), full_node_name, h, w, x0, y0) - - -if __name__ == '__main__': - file_path = sys.argv[1] - assert file_path.endswith( - '.cpp'), 'First command line argument should be a *.cpp file!' - parser = StateMachineParser(file_path) - StateMachineWriter(parser.Parse()).WriteToFile( - file_path.replace('.cpp', '.graphml'), file_path.replace('.cpp', '1.graphml')) diff --git a/compiler/fullgraphmlparser/cpp_to_graphml_test.py b/compiler/fullgraphmlparser/cpp_to_graphml_test.py deleted file mode 100644 index 537e107..0000000 --- a/compiler/fullgraphmlparser/cpp_to_graphml_test.py +++ /dev/null @@ -1,67 +0,0 @@ -# from collections import OrderedDict -# import os -# from pathlib import Path -# import sys -# import unittest - -# import xmltodict - -# import cpp_to_graphml - - -# class StateMachineParserTest(unittest.TestCase): - -# def testNumberOfStates(self): -# parser = cpp_to_graphml.StateMachineParser(cpp_file_path = './testdata/oregonPlayer.cpp') -# sm = parser.Parse() -# self.assertEqual(len(sm.states), 15) - -# def testHeaderParsed(self): -# parser = cpp_to_graphml.StateMachineParser(cpp_file_path = './testdata/oregonPlayer.cpp') -# sm = parser.Parse() -# self.assertTrue(sm.raw_h_code) -# self.assertTrue(sm.raw_h_code.startswith('#define')) -# self.assertTrue(sm.raw_h_code.endswith('(DEFAULT_HP/3)\n')) - -# self.assertEqual(sm.event_fields, 'unsigned int value;') -# self.assertEqual(sm.state_fields, '''unsigned int CharHP; -# QStateHandler StartState; -# unsigned int TimerAgony;''') -# self.assertEqual(sm.constructor_fields, '''unsigned int HP; -# unsigned int State; -# unsigned int TimerAgony;''') - -# self.assertTrue(sm.constructor_code) -# self.assertTrue(sm.constructor_code.startswith('me->CharHP = HP;'), sm.constructor_code) -# self.assertTrue(sm.constructor_code.endswith('}')) - -# self.assertEqual(sm.initial_code, 'return Q_TRAN(me->StartState);') -# self.assertEqual(sm.initial_state, 'healthy') - -# class StateMachineWriterTest(unittest.TestCase): -# OUTPUT_FILE = './testdata/output.graphml' -# def removeOutputFile(self): -# if (os.path.exists(self.OUTPUT_FILE)): -# os.remove(self.OUTPUT_FILE) - -# def setUp(self): -# self.removeOutputFile() - -# def tearDown(self): -# self.removeOutputFile() - -# def testValidGraphml(self): -# parser = cpp_to_graphml.StateMachineParser(cpp_file_path = './testdata/oregonPlayer.cpp') -# cpp_to_graphml.StateMachineWriter(parser.Parse()).WriteToFile(self.OUTPUT_FILE) -# output_file = Path(self.OUTPUT_FILE) -# # Test that output file is present ... -# self.assertTrue(output_file.is_file()) - -# # ... but in addition test that it's a valid XML containing something graphml-looking. -# with open(self.OUTPUT_FILE, 'r') as f: -# xml_dict = xmltodict.parse(f.read()) -# self.assertTrue(xml_dict) -# self.assertIsInstance(xml_dict['graphml'], OrderedDict) - -# if __name__ == '__main__': -# unittest.main() diff --git a/compiler/fullgraphmlparser/create_graphml.py b/compiler/fullgraphmlparser/create_graphml.py deleted file mode 100644 index 67525f1..0000000 --- a/compiler/fullgraphmlparser/create_graphml.py +++ /dev/null @@ -1,515 +0,0 @@ -from lxml import etree -import xmltodict -from typing import List, Tuple - -Tag = etree._Element - -namespace_dict = {None: "http://graphml.graphdrawing.org/xmlns", - 'java': "http://www.yworks.com/xml/yfiles-common/1.0/java", - 'sys': "http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0", - 'x': "http://www.yworks.com/xml/yfiles-common/markup/2.0", - 'xsi': "http://www.w3.org/2001/XMLSchema-instance", - 'y': "http://www.yworks.com/xml/graphml", - 'yed': "http://www.yworks.com/xml/yed/3"} - -scheme = "http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd" -scheme_loc = "http://www.w3.org/2001/XMLSchema-instance" - -prepare_dict = {'d0': {'attr.name': "Description", 'attr.type': "string", 'for': 'graph'}, - 'd1': {'for': 'port', 'yfiles.type': 'portgraphics'}, - 'd2': {'for': 'port', 'yfiles.type': 'portgeometry'}, - 'd3': {'for': 'port', 'yfiles.type': 'portuserdata'}, - 'd4': {'attr.name': "url", 'attr.type': "string", 'for': 'node'}, - 'd5': {'attr.name': "description", 'attr.type': "string", 'for': 'node'}, - 'd6': {'for': 'node', 'yfiles.type': 'nodegraphics'}, - 'd7': {'for': 'graphml', 'yfiles.type': 'resources'}, - 'd8': {'attr.name': "url", 'attr.type': "string", 'for': 'edge'}, - 'd9': {'attr.name': "description", 'attr.type': "string", 'for': 'edge'}, - 'd10': {'for': 'edge', 'yfiles.type': 'edgegraphics'}, - } - -graph_dict = {'edgedefault': 'directed', - 'id': 'G'} - -simple_node_color_dict = {'color': '#E8EEF7', - 'color2': '#B7C9E3', - 'transparent': "false"} - -configuration = 'com.yworks.entityRelationship.big_entity' - -node_border_dict = {'color': "#000000", - 'type': "line", - 'width': "1.0"} - -node_label_dict = {'alignment': 'center', - 'autoSizePolicy': "node_width", - 'backgroundColor': "#B7C9E3", - 'configuration': 'com.yworks.entityRelationship.label.name', - 'fontFamily': 'Consolas', - 'fontSize': '12', - 'fontStyle': 'bold', - 'hasLineColor': 'false', - 'height': '18.7', - 'horizontalTextPosition': 'center', - 'iconTextGap': '4', - 'modelName': 'internal', - 'modelPosition': 't', - 'textColor': "#000000", - "verticalTextPosition": 'bottom', - 'visible': 'true', - 'width': '200', - 'x': '0.0', - 'y': '4.0'} - -node_content_dict = {'alignment': 'left', - 'autoSizePolicy': 'content', - 'hasBackgroundColor': "false", - 'configuration': 'com.yworks.entityRelationship.label.attributes', - 'fontFamily': 'Consolas', - 'fontSize': '12', - 'fontStyle': 'plane', - 'hasLineColor': 'false', - 'height': '40', - 'horizontalTextPosition': 'center', - 'iconTextGap': '4', - 'modelName': 'custom', - # 'modelPosition':'tl', - 'textColor': "#000000", - "verticalTextPosition": 'bottom', - 'visible': 'true', - 'width': '43.5', - 'x': '0.0', - 'y': '4.0'} - -group_node_label_dict = {'alignment': "center", - 'autoSizePolicy': "node_width", - 'backgroundColor': "#EBEBEB", - 'borderDistance': "0.0", - 'fontFamily': "Consolas", - 'fontSize': "15", - 'fontStyle': "plain", - 'hasLineColor': "false", - 'height': "22.5", - 'horizontalTextPosition': "center", - 'iconTextGap': "4", - 'modelName': "internal", - 'modelPosition': "t", - 'textColor': "#000000", - 'verticalTextPosition': "bottom", - 'visible': "true", - 'width': "252.7", - 'x': "0.0", - 'y': "0.0"} - -group_node_dict = {'alignment': "left", - 'autoSizePolicy': "node_size", - 'fontFamily': "Consolas", - 'fontSize': "12", - 'fontStyle': "plain", - 'hasBackgroundColor': "false", - 'hasLineColor': "false", - 'height': "223.75", - 'horizontalTextPosition': "center", - 'iconTextGap': "4", - 'modelName': "custom", - # 'modelPosition': "t", - 'textColor': "#000000", - 'verticalTextPosition': "bottom", - 'visible': "true", - 'width': "252.68", - 'x': "0.0", - 'y': "4.0"} - -style1_dict = {'class': "java.lang.Boolean", - "name": "y.view.ShadowNodePainter.SHADOW_PAINTING", - "value": "true"} - -style2_dict = {'class': "java.lang.Boolean", - "name": "doubleBorder", - "value": "false"} - -group_node_color_dict = {'color': '#F5F5F5', - 'transparent': "false"} - -group_node_state_dict = {'closed': "false", - 'closedHeight': "50.0", - 'closedWidth': "50.0", - 'innerGraphDisplayEnabled': "false"} - -group_node_inset_dict = {'bottom': "15", - 'bottomF': "15.0", - 'left': "15", - 'leftF': "15.0", - 'right': "15", - 'rightF': "15.0", - 'top': "15", - 'topF': "15.0"} - -group_node_borders_dict = {'bottom': "47", - 'bottomF': "46.9", - 'left': "11", - 'leftF': "11.35", - 'right': "11", - 'rightF': "11.35", - 'top': "25", - 'topF': "24.5"} - -linestyle_dict = {'color': '#000000', - 'type': 'line', - 'width': '1.0'} - -arrows_dict = {'source': 'none', - 'target': 'standart'} - -edge_dict = {'alignment': "left", - 'backgroundColor': "#FFFFFF", - 'configuration': "AutoFlippingLabel", - 'distance': "2.0", - 'fontFamily': "Consolas", - 'fontSize': "12", - 'fontStyle': "plain", - 'hasLineColor': "false", - 'height': "18.7", - 'horizontalTextPosition': "center", - 'iconTextGap': "4", - 'modelName': "free", - 'modelPosition': "anywhere", - 'preferredPlacement': "anywhere", - 'ratio': "0.5", - 'textColor': "#000000", - 'verticalTextPosition': "bottom", - 'visible': "true", - 'width': "58.66", - 'x': "45.64", - 'y': "-9.35"} - -placement_dict = {'angle': "0.0", - 'angleOffsetOnRightSide': "0", - 'angleReference': "absolute", - 'angleRotationOnRightSide': "co", - 'distance': "-1.0", - 'frozen': "true", - 'placement': "anywhere", - 'side': "anywhere", - 'sideReference': "relative_to_edge_flow"} - - -def prepare_graphml() -> Tag: - """ - prepares graphml tag with parameters and all tags before graph tag - :return: root element - """ - attr_qname = etree.QName(scheme_loc, "schemaLocation") - graphml_root = etree.Element("graphml", - {attr_qname: scheme}, - nsmap=namespace_dict) - for key in prepare_dict.keys(): - _ = etree.SubElement(graphml_root, 'key', id=key, **prepare_dict[key]) - return graphml_root - - -def create_graph(tree_root: Tag, param: str) -> Tag: - """ - adds graph tag to root - :param tree_root: root element of graphml - :param param: graphparameter, - :return: graph element - """ - graph_dict['id'] = param - graph_node = etree.SubElement(tree_root, 'graph', **graph_dict) - _ = etree.SubElement(graph_node, 'data', key='d0') - return graph_node - - -def add_simple_node(parent: Tag, node_text: str, content: str, node_id: str, - h: int, w: int, x0: float, y0: float): - """ - creates simple node with parameters - :param parent: - :param node_text: node labes - :param content: node content - :param node_id: node id - :param h: height - :param w: width - :param x0: x of left upper cornet - :param y0: y of lest upper cornet - :return: - """ - node = etree.SubElement(parent, "node", id=node_id) - - data = etree.SubElement(node, "data", key="d4") - data.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - - data_full = etree.SubElement(node, "data", key="d6") - nmspc_y = namespace_dict['y'] - - generic_node = etree.SubElement(data_full, etree.QName(nmspc_y, "GenericNode"), configuration=configuration) - _ = etree.SubElement(generic_node, etree.QName(nmspc_y, "Geometry"), - height=str(h), width=str(w), x=str(x0), y=str(y0)) - _ = etree.SubElement(generic_node, etree.QName(nmspc_y, 'Fill'), **simple_node_color_dict) - _ = etree.SubElement(generic_node, etree.QName(nmspc_y, 'BorderStyle'), **node_border_dict) - - nodelabel = etree.SubElement(generic_node, etree.QName(nmspc_y, 'NodeLabel'), **node_label_dict) - nodelabel.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - nodelabel.text = node_text - - nodecontent = etree.SubElement(generic_node, etree.QName(nmspc_y, 'NodeLabel'), **node_content_dict) - nodecontent.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - nodecontent.text = content - - label_model = etree.SubElement(nodecontent, etree.QName(nmspc_y, "LabelModel")) - _ = etree.SubElement(label_model, etree.QName(nmspc_y, "ErdAttributesNodeLabelModel")) - model_param = etree.SubElement(nodecontent, etree.QName(nmspc_y, "ModelParameter")) - _ = etree.SubElement(model_param, etree.QName(nmspc_y, "ErdAttributesNodeLabelModelParameter")) - - nodestyle = etree.SubElement(generic_node, etree.QName(nmspc_y, 'StyleProperties')) - _ = etree.SubElement(nodestyle, etree.QName(nmspc_y, 'Property'), **style1_dict) - _ = etree.SubElement(nodestyle, etree.QName(nmspc_y, 'Property'), **style2_dict) - - -def add_group_node(parent: Tag, node_text: str, content: str, node_id: str, - h: int, w: int, x0: float, y0: float) -> Tag: - """ - creates group node with parameters - :param parent: - :param node_text: node labes - :param content: node content - :param node_id: node id - :param h: height - :param w: width - :param x0: x of left upper cornet - :param y0: y of lest upper cornet - :return: group node tag - """ - node_dict = {'id': node_id, "yfiles.foldertype": "group"} - nmspc_y = namespace_dict['y'] - - node = etree.SubElement(parent, "node", **node_dict) - data = etree.SubElement(node, 'data', key="d6") - proxy = etree.SubElement(data, etree.QName(nmspc_y, "ProxyAutoBoundsNode")) - realizers = etree.SubElement(proxy, etree.QName(nmspc_y, "Realizers"), active='0') - - group_node = etree.SubElement(realizers, etree.QName(nmspc_y, "GroupNode")) - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "Geometry"), - height=str(h), width=str(w), x=str(x0), y=str(y0)) - _ = etree.SubElement(group_node, etree.QName(nmspc_y, 'Fill'), **group_node_color_dict) - _ = etree.SubElement(group_node, etree.QName(nmspc_y, 'BorderStyle'), **node_border_dict) - - nodelabel = etree.SubElement(group_node, etree.QName(nmspc_y, "NodeLabel"), **group_node_label_dict) - nodelabel.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - nodelabel.text = node_text - - nodecontent = etree.SubElement(group_node, etree.QName(nmspc_y, 'NodeLabel'), **group_node_dict) - nodecontent.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - nodecontent.text = content - - label_model = etree.SubElement(nodecontent, etree.QName(nmspc_y, "LabelModel")) - _ = etree.SubElement(label_model, etree.QName(nmspc_y, "ErdAttributesNodeLabelModel")) - model_param = etree.SubElement(nodecontent, etree.QName(nmspc_y, "ModelParameter")) - _ = etree.SubElement(model_param, etree.QName(nmspc_y, "ErdAttributesNodeLabelModelParameter")) - - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "Shape"), type="roundrectangle") - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "State"), **group_node_state_dict) - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "NodeBounds"), considerNodeLabelSize='true') - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "Insets"), **group_node_inset_dict) - _ = etree.SubElement(group_node, etree.QName(nmspc_y, "BorderInsets"), **group_node_borders_dict) - return node - - -def add_edge(parent: Tag, edge_id: str, source: str, target: str, text: str, - x1: float, y1: float, x2: float, y2: float, points: List[Tuple[int, int]]): - """ - adds edge to xml - :param points: list of trigger points - :param parent: parent tag - :param edge_id: edge id - :param source: source node id - :param target: target node id - :param text: edge label - :param x1: start edge x - :param y1: start edge y - :param x2: finish edge x - :param y2: finish edge y - :return: - """ - edge = etree.SubElement(parent, "edge", id=edge_id, source=source, target=target) - _ = etree.SubElement(edge, "data", key="d9") - data = etree.SubElement(edge, "data", key="d10") - nmspc_y = namespace_dict['y'] - polyline_edge = etree.SubElement(data, etree.QName(nmspc_y, 'PolyLineEdge')) - path = etree.SubElement(polyline_edge, etree.QName(nmspc_y, 'Path'), sx=str(x1), sy=str(y1), tx=str(x2), ty=str(y2)) - if points: - for point in points: - _ = etree.SubElement(path, etree.QName(nmspc_y, 'Point'), x=point[0], y=point[1]) - _ = etree.SubElement(polyline_edge, etree.QName(nmspc_y, 'LineStyle'), **linestyle_dict) - _ = etree.SubElement(polyline_edge, etree.QName(nmspc_y, 'Arrows'), **arrows_dict) - edgelabel = etree.SubElement(polyline_edge, etree.QName(nmspc_y, 'EdgeLabel'), **edge_dict) - edgelabel.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - edgelabel.text = text - _ = etree.SubElement(edgelabel, etree.QName(nmspc_y, 'PreferredPlacementDescriptor'), **placement_dict) - _ = etree.SubElement(polyline_edge, etree.QName(nmspc_y, "BendStyle"), smoothed="false") - - -def add_start_state(parent: Tag, node_id: str): - """ - adds start state from template - :param node_id: node_id - :param parent: parent tag - :return: - """ - data = xmltodict.parse(open(r'graphml_templates/start_template.xml').read()) - node = etree.SubElement(parent, "node", id=node_id) - data_tag = etree.SubElement(node, "data", key="d6") - get_tags_from_template(data_tag, data, "") - - -def add_choice_state(parent: Tag, node_id: str): - """ - adds start state from template - :param node_id: node_id - :param parent: parent tag - :return: - """ - data = xmltodict.parse(open(r'graphml_templates/choice_template.xml').read()) - node = etree.SubElement(parent, "node", id=node_id) - data_tag = etree.SubElement(node, "data", key="d6") - get_tags_from_template(data_tag, data, "") - - -def add_comment_state_with_text(parent: Tag, node_id: str, text: str): - """ - adds comment node from template with added text to parent Node - :param parent: parent node - :param node_id: node id - :param text: text to add - :return: - """ - data = xmltodict.parse(open(r'graphml_templates/comment_template.xml').read()) - node = etree.SubElement(parent, "node", id=node_id) - data_tag = etree.SubElement(node, "data", key="d6") - node.set("{http://www.w3.org/XML/1998/namespace}space", "preserve") - get_tags_from_template(data_tag, data, text) - - -def get_state_fields_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for state fields - :param node_id: od of node - :param parent: tag to add comment - :param text: text to add to states - :return: - """ - add_comment_state_with_text(parent, node_id, "State fields: (do not delete this caption):\n" + text) - - -def get_constructor_code_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for constructor code - :param parent: tag to add comment - :param node_id: od of node - :param text: text to add to constructor code - :return: - """ - add_comment_state_with_text(parent, node_id, "Constructor code: (do not delete this caption):\n" + text) - - -def get_h_code_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for code for h-file - :param parent: tag to add comment - :param node_id: od of node - :param text: text to add to h-file - :return: - """ - add_comment_state_with_text(parent, node_id, "Code for h-file: (do not delete this caption):\n" + text) - - -def get_c_code_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for code for cpp-file - :param parent: tag to add comment - :param node_id: od of node - :param text: text to add to cpp-file - :return: - """ - add_comment_state_with_text(parent, node_id, "Code for cpp-file: (do not delete this caption):\n" + text) - - -def get_constructor_fields_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for additional constructor fields - :param parent: tag to add comment - :param node_id: od of node - :param text: list of constructor fields - :return: - """ - add_comment_state_with_text(parent, node_id, "Constructor fields: (do not delete this caption):\n" + text) - - -def get_event_fields_comment(parent: Tag, node_id: str, text: str): - """ - gets comment for additional event fields - :param parent: tag to add comment - :param node_id: od of node - :param text: list of event fields - :return: - """ - add_comment_state_with_text(parent, node_id, "Event fields: (do not delete this caption):\n" + text) - - -def get_tags_from_template(parent: Tag, data: dict, text: str): - """ - gets tag structure from template and adds it to tag structure, adding text to nodelabel - :param parent: parent tag - :param data: data with tags template - :param text: text to add to node label - :return: - """ - for tag in data.keys(): - if isinstance(data[tag], dict): - attributes = {key.replace("@", ""): data[tag][key] for key in data[tag].keys() if - not isinstance(data[tag][key], dict) and not isinstance(data[tag][key], list)} - new_tag = etree.SubElement(parent, etree.QName(namespace_dict['y'], tag.replace("y:", "")), **attributes) - if tag == 'y:NodeLabel': - new_tag.text = text - - get_tags_from_template(new_tag, data[tag], text) - if isinstance(data[tag], list): - for i in range(len(data[tag])): - if isinstance(data[tag][i], dict): - get_tags_from_template(parent, {tag: data[tag][i]}, text) - - -def finish_graphml(root: Tag): - """ - creates finish tag - :param root: root node - :return: - """ - data = etree.SubElement(root, 'data', key='d7') - _ = etree.SubElement(data, etree.QName(namespace_dict['y'], 'Resources')) - - -if __name__ == '__main__': - root_node = prepare_graphml() - graph = create_graph(root_node, 'G') - add_start_state(graph, "n2") - group_node = add_group_node(graph, "parent", "parent_text", 'n0', 223, 252, 347, 152) - group_graph = create_graph(group_node, 'n0:') - add_simple_node(group_graph, 'idle', 'lorem ipsum', 'n0::n0', 100, 200, 374, 214) - add_simple_node(graph, 'not_idle', 'lorem ipsum', 'n1', 100, 200, 734, 213) - add_choice_state(graph, "n3") - add_edge(graph, "e0", "n0::n0", "n1", 'TEST TRIGGER', 0, 0, 0, 0) - add_edge(graph, "e1", "n2", "n1", "initial", 0, 0, 0, 0) - add_edge(graph, "e2", "n1", "n3", "choice_trigger", 0, 0, 0, 0) - add_edge(graph, "e3", "n3", "n0::n0", "guard1", 0, 0, 0, 0) - add_edge(graph, "e4", "n3", "n0", "guard2", 0, 0, 0, 0) - get_c_code_comment(graph, "n4", "some code here") - get_constructor_code_comment(graph, 'n5', "me->test_field = test") - get_constructor_fields_comment(graph, 'n6', "unsigned int: test_constructor") - get_event_fields_comment(graph, 'n7', "unsigned int: test_event_field") - get_h_code_comment(graph, "n8", "some code for h file here") - get_state_fields_comment(graph, "n9", "unsigned int test_state_field") - finish_graphml(root_node) - xml_tree = etree.ElementTree(root_node) - xml_tree.write("test.graphml", xml_declaration=True, pretty_print=True, encoding="UTF-8") diff --git a/compiler/fullgraphmlparser/graphml_templates/choice_template.xml b/compiler/fullgraphmlparser/graphml_templates/choice_template.xml deleted file mode 100644 index 11c4321..0000000 --- a/compiler/fullgraphmlparser/graphml_templates/choice_template.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/graphml_templates/comment_template.xml b/compiler/fullgraphmlparser/graphml_templates/comment_template.xml deleted file mode 100644 index 2160a6d..0000000 --- a/compiler/fullgraphmlparser/graphml_templates/comment_template.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/graphml_templates/start_template.xml b/compiler/fullgraphmlparser/graphml_templates/start_template.xml deleted file mode 100644 index cf20121..0000000 --- a/compiler/fullgraphmlparser/graphml_templates/start_template.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/compiler/fullgraphmlparser/graphmltoqm.py b/compiler/fullgraphmlparser/graphmltoqm.py deleted file mode 100644 index 6eb387f..0000000 --- a/compiler/fullgraphmlparser/graphmltoqm.py +++ /dev/null @@ -1,92 +0,0 @@ -import xmltodict -import qm -import graphml as gr -import service_files -from graphml_to_cpp import CppFileWriter -from logger import logging -import sys -import os -from typing import Union, List - - -def get_states_from_graphml(filename: str): - """ - creates state list - :return: - """ - try: - data = xmltodict.parse(open(filename).read()) - except FileNotFoundError: - logging.error('File %s does not exist' % filename) - return list(), 0, 0 - # get nodes from file - flat_nodes = gr.get_flat_nodes(data) - state_nodes = [node for node in flat_nodes if - gr.is_node_a_state(node) or gr.is_node_a_choice(node) or gr.is_node_a_group(node)] - state_nodes.sort(key=lambda st: len(st['id'])) - gr.update_qroup_nodes(state_nodes) - state_nodes.sort(key=gr.coord_sort) - coords = gr.get_minmax_coord(state_nodes) # get min and max coord and height and widt of scheme - # create states from nodes and add internal triggers to list of signals and all functions to function list - qm_states, player_signal = qm.create_states_from_nodes(state_nodes, coords, [], []) - # get edges for external triggers - flat_edges = gr.get_flat_edges(data) - try: - start, start_node, start_action = gr.get_start_node_data(flat_nodes, flat_edges) - except ValueError: - logging.error('UML-diagram %s.graphml does not have start node' % filename) - return list(), 0, 0 - # add external trigger and update list of signals with them - _ = qm.update_states_with_edges(qm_states, flat_edges, start, player_signal, coords[0], coords[1]) - return qm_states, coords[0], coords[1] - -# test2 - -def main(filenames: Union[List[str], str]): - - player_signal = list() - if not isinstance(filenames, list): - filenames = [filenames] - modelnames: List[str] = list() - for filename in filenames: - try: - data = xmltodict.parse(open(filename).read()) - modelname = os.path.basename(filename) - modelname = modelname.split('.')[0] - modelname = modelname[0].lower() + modelname[1:] - modelnames.append(modelname) - except FileNotFoundError: - logging.error('File %s does not exist' % filename) - continue - # get nodes from file - flat_nodes = gr.get_flat_nodes(data) - state_nodes = [node for node in flat_nodes if - gr.is_node_a_state(node) or gr.is_node_a_choice(node) or gr.is_node_a_group(node)] - state_nodes.sort(key=lambda st: len(st['id'])) - gr.update_qroup_nodes(state_nodes) - state_nodes.sort(key=gr.coord_sort) - - coords = gr.get_minmax_coord(state_nodes) # get min and max coord and height and widt of scheme - # create states from nodes and add internal triggers to list of signals and all functions to function list - functions: List[str] = list() - qm_states, player_signal = qm.create_states_from_nodes(state_nodes, coords, player_signal, functions) - # get edges for external triggers - flat_edges = gr.get_flat_edges(data) - try: - start, start_node, start_action = gr.get_start_node_data(flat_nodes, flat_edges) - except ValueError: - logging.error('UML-diagram %s.graphml does not have start node' % filename) - continue - # add external trigger and update list of signals with them - player_signal = qm.update_states_with_edges(qm_states, flat_edges, start, player_signal, coords[0], coords[1]) - # get notes - notes = [node for node in flat_nodes if gr.is_node_a_note(node)] - # TODO(aeremin) Extract to separate file. - CppFileWriter(modelname, start_node, start_action, qm_states, notes, player_signal).write_to_file(os.path.dirname(filename), "cpp") - - service_files.create_files(os.path.dirname(filenames[0]), player_signal, modelname, functions) - - -if __name__ == '__main__': - states = get_states_from_graphml(sys.argv[1:][0]) - main(sys.argv[1:]) diff --git a/compiler/fullgraphmlparser/logger.py b/compiler/fullgraphmlparser/logger.py deleted file mode 100644 index 92eb249..0000000 --- a/compiler/fullgraphmlparser/logger.py +++ /dev/null @@ -1,4 +0,0 @@ -import logging - -logging.basicConfig(format=u'%(filename)s[LINE:%(lineno)d]# %(levelname)-8s [%(asctime)s] %(message)s', - level=logging.DEBUG) \ No newline at end of file diff --git a/compiler/fullgraphmlparser/qm.py b/compiler/fullgraphmlparser/qm.py deleted file mode 100644 index 468541a..0000000 --- a/compiler/fullgraphmlparser/qm.py +++ /dev/null @@ -1,529 +0,0 @@ -""" -this is special module for creating objects for qm file. Module contains description of class State (namedtiple) -for states and class Trigger for trigsitions between states and functions for theis analyze and creation - --State namedtuple with State data --Trigger namedtuple with trigger data --get_state_by_id(states: [State], id:int, type:str) -> State gets state by its id --def create_actions(raw_triggers: str, source: int) -> [Trigger] creates trigger list from actions string --create_state_from_node(id: int, node: dict) -> State: creates single qm state --create_choice_from_node(node: dict, new_id: int, min_x: int, min_y: int) -> State: - creates choice state from node --create_states_from_nodes(nodes: [dict], min_x: int, min_y: int) -> [State]: function gets node data from node dict - and returns State object with all data --update_states_with_edges(states: [State], flattened_edges: [dict]): updates states with external transitions --is_state_a_child(child: State, parent: State) -> bool: detects if one node is a parent to other --is_state_a_child_by_coord(x, y, width, height, parent: State) -> bool: detects if one node is a parent to other - (using coordinates) --get_parent(child: State, states: [State]) -> State: gets id of parent of a child --get_parent_by_coord(x, y, w, h, states: [State]) -> State: gets id of parent of a child --def get_childs(parent: State, states: [State]) ->[str]: gets list of childs -""" - -from graphml import * -import re -from typing import List, Optional, Tuple -from stateclasses import State, Trigger - -divider = 10 # we divide graphml coordinates by that value -action_delta = 5 # addition to action box -internal_trigger_height = 5 # height of space for internal trigger -internal_trigger_delta = 10 # addition to trigger name length -global_h_delta = 10 # addition to global height -global_w_delta = 10 # addition to global width -terminal_w = 10 -terminal_h = 10 - - -def get_state_by_id(states: [State], state_id: str, id_type: str) -> State: - """ - gets state by its id - :param id_type: for "old" we search for state with id = id, for "new" we search state with new_id = id - :param states: list of states - :param state_id: id for search - :return: state with searched id - """ - if id_type == 'new': - for state in states: - if state.new_id == state_id: - return state - if id_type == 'old': - for state in states: - if state.id == state_id: - return state - return states[0] - - -def get_functions(actions: str, functions: List[str]): - """ - gets functions from code - :param actions: text of node - :param functions: list of sunctions to add new - :return: - """ - f_regexp = r'([A-Z]\w+)\([^\)]*\)' - new_functions = re.findall(f_regexp, actions) - for func in new_functions: - if func not in functions: - functions.append(func) - return - - -def create_actions(raw_triggers: str, source: str, player_signal: List[str], functions: List[str]) -> List[Trigger]: - """ - parses raw label text with events and their actions to get a list of Triggers ("exit" and "entry" events ignored) - we use regexp to split raw data string - regexp is some non-space symbols, then some space symbols, than "/" symbol - Example: - >>>create_actions("entry/ - BUTTON2_PRESSED/ - flash(get_color(rgb_table)); - play_sound(get_random_sound(BLASTER)); - BUTTON2_PRESSED_FOR_THREE_SECOND/ - play_sound(get_random_sound(FORCE); - BOTH_BUTTONS_PRESSED/ - change_color(get_color(rgb_table)); - play_sound(get_sound(BOOT), 5);") - - [Trigger(name="BUTTON2_PRESSED", action="flash(get_color(rgb_table)); - play_sound(get_random_sound(BLASTER));", source=5) - Trigger(name="BUTTON2_PRESSED_FOR_THREE_SECOND"), action="play_sound(get_random_sound(FORCE);", source=5), - Trigger(name="BOTH_BUTTONS_PRESSED"), action="change_color(get_color(rgb_table)); - play_sound(get_sound(BOOT));", source=5)] - :param functions: list of fucntions - :param raw_triggers: string with events and reactions - :param source: id of source node - :param player_signal - list of all sygnals - :return: list of Triggers, list of sygnals - """ - # regexp takes beginnig of string, than some a-zA-Z0-9_ symbols tnan spaces, than [guard] then / - trigger_regexp: str = r"^ *\w+ *(?:\[.+?\])?\/" - trigger_list = re.findall(trigger_regexp, raw_triggers, re.MULTILINE) - trigger_data = re.split(trigger_regexp, raw_triggers, flags=re.MULTILINE) - triggers: Dict[str, str] = dict(list(zip(trigger_list, trigger_data[1:]))) - actions: List[Trigger] = list() - for (trigger_id, (trigger, action)) in enumerate(triggers.items(), start=1): - guard: str = "" - i = trigger.index(r'/') - trigger_name: str = trigger[:i].strip() - if '[' in trigger_name: - guard_regexp: str = r"\[.*\]" - res = re.search(guard_regexp, trigger_name) - guard = res.group(0)[1:-1] - trigger_name = re.split(guard_regexp, trigger_name)[0].strip() - # if guard != 'else': - # logging.warning("Internal trigger %s[%s] can't contain guard" % (trigger_name, guard)) - - if trigger_name not in player_signal and trigger_name and trigger_name != "entry" and trigger_name != 'exit': - player_signal.append(trigger_name) - # Un-indent each line in the (potentially multiline) action by the indent of the first line. - lines = action.split('\n')[1:] # discard 0, as 0-th line is the whitespace after 'SOME_SIG/' - if lines: - indent = len(lines[0]) - len(lines[0].lstrip()) - action = '\n'.join(line[indent:] for line in lines) - action = action.rstrip() - actions.append(Trigger(name=trigger_name, action=action, source=source, type="internal", guard=guard, - target="", id=trigger_id, x=0, y=internal_trigger_height * trigger_id, - dx=len(trigger_name) + internal_trigger_delta, dy=0, points=[], action_x=0, - action_y=5 * trigger_id - 2, - action_width=len(trigger_name) + action_delta)) - # add functions to function list - get_functions(raw_triggers, functions) - return actions, player_signal - - -def create_state_from_node(node: dict, node_type: str, min_x: int, min_y: int, states: [State], - player_signal: List[str], functions: List[str]) -> Tuple[State, List[str]]: - """ - creates state from mode with node_type type (state or group) - :param functions: list with functions - :param node: dict with node data - :param node_type: state or group - :param min_x - min x coordinate to add to state coordinate to excluse negative coordinates - :param min_y - min y coordinate to add to state coordinate to excluse negative coordinates - :param states - list of created states - :param player_signal - list of triggers - :return State - """ - name: str = get_state_label(node) if node_type == 'state' else get_group_label(node) - actions: str = get_state_actions(node) if node_type == 'state' else get_group_actions(node) - node_id = node['id'] - (triggers, player_signal) = create_actions(actions, node_id, player_signal, functions) - state_entry: List[str] = [trig.action for trig in triggers if trig.name == 'entry'] - state_exit: List[str] = [trig.action for trig in triggers if trig.name == 'exit'] - state_entry_str: str = '#ifdef DESKTOP\nprintf("Entered state %s");\n#endif /* def DESKTOP */\n' % name - state_entry_str += state_entry[0] if state_entry else "" - state_exit_str: str = '#ifdef DESKTOP\nprintf("Exited state %s");\n#endif /* def DESKTOP */\n' % name - state_exit_str += state_exit[0] if state_exit else "" - triggers: List[Trigger] = [trig for trig in triggers if trig.name != 'entry' and trig.name != 'exit'] - x, y, width, height = get_coordinates(node) - x = x // divider - min_x // divider + 2 - y = y // divider - min_y // divider + 2 - width: int = width // divider - height: int = height // divider - parent: State = get_parent_by_label(node_id, states) - new_id: List[str] = [(parent.new_id[0] + "/" + str(len(parent.childs) + len(parent.trigs)))] - state: State = State(name=name, type=node_type, id=node_id, new_id=new_id, actions=actions, - entry=state_entry_str, exit=state_exit_str, trigs=triggers, x=x, - y=y, width=width, height=height, parent=parent, childs=list()) - return state, player_signal - - -def create_choice_from_node(node: dict, min_x: int, min_y: int, states: [State]) -> State: - """ - creates choice state from node - :param node: dict with node data - :param min_x - min x coordinate to add to state coordinate to excluse negative coordinates - :param min_y - min y coordinate to add to state coordinate to excluse negative coordinates - :param states - list of already creates states - :return State - """ - node_id = node['id'] - x, y, width, height = get_coordinates(node) - x: int = x // divider - min_x // divider + 1 - y: int = y // divider - min_y // divider + 1 - width: int = width // divider - height: int = height // divider - parent: State = get_parent_by_label(node_id, states) - new_id: List[str] = [parent.new_id[0] + "/" + str(len(parent.childs) + len(parent.trigs))] - state: State = State(name=get_state_label(node), type="choice", id=node_id, new_id=new_id, actions="", - entry="", exit="", trigs=[], x=x, y=y, - width=width, height=height, parent=parent, childs=list()) - return state - - -def create_global_state(w: int, h: int) -> State: - """ - creates global parent state of all states - :param w: width between states - :param h: height of all states - :return: global parent state - """ - state = State(name="global", type="group", id="", new_id=["1"], actions="", - entry="", exit="", trigs=[], - x=1, y=1, width=w // divider + global_w_delta, height=h // divider + global_h_delta, parent=None, - childs=[]) - return state - - -def create_states_from_nodes(nodes: [dict], coords: tuple, player_signal, functions: [str]) -> [State]: - """ - function gets node data from node dict and returns State object with all necessary data - :param functions: list of functions - :param player_signal: list of signals - :param coords: min x coordinate to calibrate others, min y coordinate to calibrate others, - global wigth for global state, global height global state - :param nodes: list of dicts with data - :return: State list - """ - min_x, min_y, w, h = coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1] - states: List[State] = [create_global_state(w, h)] - states.append(create_terminate_state(states)) - add_terminal_trigger(states) - for node in nodes: - if is_node_a_group(node): - state, player_signal = create_state_from_node(node, "group", min_x, min_y, states, player_signal, functions) - states.append(state) - for node in nodes: - if is_node_a_state(node): - state, player_signal = create_state_from_node(node, "state", min_x, min_y, states, player_signal, functions) - states.append(state) - for node in nodes: - if is_node_a_choice(node): - state = create_choice_from_node(node, min_x, min_y, states) - states.append(state) - return states, player_signal - - -def update_states_with_edges(states: [State], flat_edges: [dict], start_state: str, player_signal: [str], min_x: int, - min_y: int): - """ - function parses events on edges and adds them as external triggers to corresponding state (excluding start_edge) - and recognizes and adds special labels to a choice edgea - :param min_x: minimum value of x - :param min_y: minimum value of y - :param states: list of states - :param flat_edges: list with edges - :param start_state - id for start state for exclude start edge - :param player_signal - list of already created signals - :return: - """ - for edge in flat_edges: - for edge_type in edge_types: - try: - old_source: str = edge['source'] - if old_source != start_state and len(edge.keys()) > 3: - old_target: str = edge['target'] - source_state: State = get_state_by_id(states, old_source, "old") - target_state: State = get_state_by_id(states, old_target, "old") - if is_edge_correct(edge, edge_type) and "#text" in edge[edge_type]['y:EdgeLabel'].keys(): - action: str = edge[edge_type]['y:EdgeLabel']["#text"].split('/') - trigger_name: str = action[0].strip() - guard: str = "" - if '[' in trigger_name and ']' in trigger_name: - guard_regexp: str = r"\[.*\]" - res = re.search(guard_regexp, trigger_name) - guard: str = res.group(0)[1:-1] - trigger_name: str = re.split(guard_regexp, trigger_name)[0].strip() - # if guard == 'else': - # logging.warning("External trigger %s[%s] can't contain 'else'" % (trigger_name, guard)) - trigger_action: str = action[1].strip() if len(action) > 1 else "" - else: - trigger_name = "" - trigger_action = "" - guard = "" - x, y, dx, dy, points = get_edge_coordinates(edge) - new_points = [] - for point in points: - new_points.append(((point[0] - min_x) // divider, (point[1] - min_y) // divider)) - action_x, action_y, action_width = get_edge_label_coordinates(edge) - trig_type = "external" - if source_state.type == "choice": - trig_type = "choice_result" - if target_state.type == "choice": - trig_type = "choice_start" - trigger = Trigger(name=trigger_name, type=trig_type, guard=guard, source=old_source, - target=old_target, action=trigger_action, - id=0, - x=x // divider, y=y // divider, dx=dx // divider, dy=dy // divider, - points=new_points, action_x=action_x // divider, action_y=action_y // divider, - action_width=action_width // divider + 2) - source_state.trigs.append(trigger) - if trigger_name and trigger_name not in player_signal: - player_signal.append(trigger_name) - except KeyError: - continue - update_state_ids(states) - return player_signal - - -def create_terminate_state(states: [State]) -> State: - """ - creates state for terminate state machine on desktop - :param states: list of states - :return: global parent state - """ - global_state: State = get_state_by_id(states, '', 'old') - state: State = State(name="final?def DESKTOP", type="state", id="last", new_id=["2"], actions="", - entry="""printf("\nBye! Bye!\n"); exit(0);""", exit="", trigs=[], - x=global_state.x + global_state.width // 2 - terminal_w // 2, - y=states[0].y + states[0].height + 5, width=terminal_w, height=terminal_h, parent=None, - childs=[]) - return state - - -def add_terminal_trigger(states): - terminate: State = get_state_by_id(states, "last", "old") - first: State = get_state_by_id(states, "", "old") - trigger: Trigger = Trigger(name="TERMINATE?def DESKTOP", type="external", guard="", source=first.id, - target=terminate.id, action="", id=0, x=0, y=first.height // 2, - dx=0, dy=-terminal_h // 2, points=[], action_x=-5, action_y=2, action_width=10) - first.trigs.append(trigger) - - -def update_state_ids(states: [State]): - """ - updates state ids to get path in ids - :param states: list of states - :return: - """ - states.sort(key=lambda st: st.x) - for i in range(0, len(states)): - if states[i].new_id[0] == '1': - states[i].new_id.append("1") - else: - if states[i].new_id[0] == '2': - states[i].new_id.append("2") - else: - len_brothers: int = len(states[i].parent.childs) - trigs = states[i].parent.trigs - len_trigs = len(set([trig.name for trig in trigs])) - states[i].new_id.append(states[i].parent.new_id[1] + "/" + str(len_brothers + len_trigs)) - if states[i].type != 'choice': - states[i].parent.childs.append(states[i]) - - -def get_start_state_data(start_state: int, states: [State]) -> tuple: - """ - function finds start state and gets it's id and coordinates - :param start_state: id of start state - :param states: list of states - :return: id, x and y of start state - """ - first_node = 0 - for state in states: - if state.trigs: - for trig in state.trigs: - if trig.source == start_state: - first_node = trig.target - return (get_state_by_id(states, first_node, "new").new_id, get_state_by_id(states, first_node, "old").y, - (get_state_by_id(states, first_node, "new").x - 2)) - - -def is_state_a_child(child: State, parent: State) -> bool: - """ - detects if one node is a parent to other (using coordinates) - :param child: child? - :param parent: parent? - :return: True if is a child else false - """ - if parent.x <= child.x <= parent.x + parent.width and parent.y <= child.y <= parent.y + parent.height: - return True - return False - - -def is_state_a_child_by_coord(x, y, width, height, parent: State) -> bool: - """ - detects if one node is a parent to other (using coordinates) - :param x: x coord of a child - :param y: y coord of a child - :param width: width of a child - :param height: height of a child - :param parent: parent? - :return: true if child else false - """ - if x + 1 >= parent.x and y + 1 >= parent.y and x + width - 1 <= parent.x + parent.width: - if y + height - 1 <= parent.y + parent.height: - return True - return False - - -def is_state_a_child_by_label(parent: State, label: str)-> bool: - """ - ckecks if parent state is really parent for child state - :param parent: is a parent state? - :param label: child label - :return: is a child? - """ - pass - return label.startswith(parent.id) - - -def get_parent_by_label(label: str, states: List[State]) -> Optional[State]: - """ - gets nearest parent using node id - :param label: child label - :param states: list of States - :return: - """ - parents: List[State] = [state for state in states if is_state_a_child_by_label(state, label)] - if not parents: - return None - parents.sort(key=lambda st: len(st.id)) - return parents[-1] - - -def get_parent(child: State, states: [State]) -> Optional[State]: - """ - gets id of parent of a child - :param child: state to get parent - :param states: all states - :return: parent - """ - parents = [state for state in states if is_state_a_child(child, state)] - if not parents: - return None - parents.sort(key=lambda st: st.x, reverse=True) - return parents[0] - - -def get_parent_by_coord(x, y, w, h, states: [State]) -> Optional[State]: - """ - gets id of parent of a child - :param x: x coord of a child - :param y: y coord of a child - :param w: width of a child - :param h: height of a child - - :param states: all states - :return: parent - """ - parents: List[State] = [state for state in states if is_state_a_child_by_coord(x, y, w, h, state)] - if not parents: - return None - parents.sort(key=lambda st: st.x, reverse=True) - return parents[0] - - -def get_parent_list(state: State) -> List[State]: - """ - get list of parent states - :param state: current state - :return: list of parent states - """ - curr_state: State = state.parent - parents: List[State] = list() - while curr_state: - parents.append(curr_state) - curr_state = curr_state.parent - return parents - - -def get_path(state1: str, state2: str, states) -> str: - """ - gets path from state1 to state2 as for folders: - EXAMPLE: "../../1/2" - :param state1: first state - :param state2: second state - :param states: list of states - :return: - """ - state1 = get_state_by_id(states, state1, "old") - state2 = get_state_by_id(states, state2, "old") - if state1.id == "" and state2.id == "last": - return "../../2" - if state1 == state2: - return ".." - parents1 = get_parent_list(state1) - parents2 = get_parent_list(state2) - for parent in parents1: - if parent in parents2: - level = parents1.index(parent) + 2 - path = "../" * level - path2 = list(reversed(state2.new_id[1].split('/'))) - path2 = path2[:parents2.index(parent) + 1] - path += "/".join(list(reversed(path2))) - return path - - -def get_graphml_coords_by_state_name(states: List[State], name: str, minx: float, miny: float) -> \ - Tuple[float, float, float, float]: - """ - gets coords for graphml by name - :param states: list of states - :param name: name of needed state - :param minx: min x - :param miny: min y - :return: x, y, width, height - """ - for state in states: - if state.name == name: - return (state.x - 2) * divider + minx, (state.y - 2) * divider + miny, \ - state.width * divider, state.height * divider - return 0, 0, 0, 0 - - -def get_edge_coords_by_state_and_name(states: List[State], name_state: str, name_edge: str, minx: int, miny: int) -> \ - Tuple[int, int, int, int, List[Tuple[int, int]]]: - """ - get coords of edge by edge name and source name - :param miny: min y of scheme - :param minx: min x of scheme - :param states: list of states - :param name_state: name of state - :param name_edge: name of edge - :return: - """ - for state in states: - if state.name == name_state: - for trig in state.trigs: - if trig.name == name_edge: - sx = trig.x * divider - sy = trig.y * divider - tx = trig.dx * divider - ty = trig.dy * divider - points = list() - for point in trig.points: - points.append((point[0]*divider + minx, point[1]*divider + miny)) - return sx, sy, tx, ty, points - return 0, 0, 0, 0, [] diff --git a/compiler/fullgraphmlparser/qm_test.py b/compiler/fullgraphmlparser/qm_test.py deleted file mode 100644 index 686c4f2..0000000 --- a/compiler/fullgraphmlparser/qm_test.py +++ /dev/null @@ -1,117 +0,0 @@ -import unittest - -from qm import * - - -class TriggersCreateTest(unittest.TestCase): - - def testEmptyTriggers(self): - res, _ = create_actions(" ", "test", [], []) - self.assertEqual(len(res), 0) - - def testEntryOnly(self): - res, _ = create_actions("entry/", "test", [], []) - self.assertEqual(len(res), 1) - - def testEntryOnlyBody(self): - res, _ = create_actions("entry/", "test", [], []) - self.assertEqual(res[0].name, "entry") - - def testEmptyTrigger(self): - res, _ = create_actions("TIME_TICK_10S/", "test", [], []) - self.assertEqual(res[0].name, "TIME_TICK_10S") - - def testMoreSpacers(self): - res, _ = create_actions(" \n \nTIME_TICK_10S/ \n ", "test", [], []) - self.assertEqual(res[0].name, "TIME_TICK_10S") - - def testSeveralTriggers(self): - res, _ = create_actions(""" - entry/ - BeepForPeriod(LONG_BEEP_MS); - SaveState(AGONY); - UpdateHP(me, 1); - me->TimerAgony = 0; - - TIME_TICK_1S[else]/ - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); - - TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS);""", "test", [], []) - - self.assertEqual(len(res), 3) - - def testSeveralTriggersName(self): - res, _ = create_actions(""" - entry/ - BeepForPeriod(LONG_BEEP_MS); - SaveState(AGONY); - UpdateHP(me, 1); - me->TimerAgony = 0; - - TIME_TICK_1S[else]/ - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); - - TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS);""", "test", [], []) - - self.assertEqual(res[1].name, 'TIME_TICK_1S') - - def testSeveralTriggersBody(self): - res, _ = create_actions(""" - entry/ - BeepForPeriod(LONG_BEEP_MS); - SaveState(AGONY); - UpdateHP(me, 1); - me->TimerAgony = 0; - - TIME_TICK_1S[else]/ - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); - - TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS);""", "test", [], []) - - self.assertEqual(res[1].action, 'me->TimerAgony++;\nFlash(RED, 0, 0, FLASH_MS);') - self.assertEqual(res[2].action, 'BeepForPeriod(SHORT_BEEP_MS);') - - def testGuard(self): - res, _ = create_actions('RAD_RCVD[((((oregonPlayerQEvt*)e)->value+me->CharHP )CharHP + ((oregonPlayerQEvt*)e)->value);;', "test", [], []) - self.assertEqual(res[0].guard, "((((oregonPlayerQEvt*)e)->value+me->CharHP )value+me->CharHP )CharHP + ((oregonPlayerQEvt*)e)->value);;', "test", [], []) - self.assertEqual(res[0].guard, "((((oregonPlayerQEvt*)e)->value+me->CharHP )value+me->CharHP )CharHP + ((oregonPlayerQEvt*)e)->value);;', "test", [], []) - self.assertEqual(res[0].action, "UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value);;") - - def testElseGuard(self): - res, _ = create_actions(""" - entry/ - BeepForPeriod(LONG_BEEP_MS); - SaveState(AGONY); - UpdateHP(me, 1); - me->TimerAgony = 0; - - TIME_TICK_1S[else]/ - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); - - TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS);""", "test", [], []) - self.assertEqual(res[1].guard, "else") - - def testNoTrigger(self): - res, _ = create_actions("a = b / c", "test", [], []) - self.assertEqual(len(res), 0) - - -if __name__ == '__main__': - unittest.main() diff --git a/compiler/fullgraphmlparser/samek_consistency_test.py b/compiler/fullgraphmlparser/samek_consistency_test.py deleted file mode 100644 index 0a2f5e9..0000000 --- a/compiler/fullgraphmlparser/samek_consistency_test.py +++ /dev/null @@ -1,65 +0,0 @@ -import os -import shutil -import unittest - -import graphmltoqm -import test_utils - - -class SamekConsistencyTest(unittest.TestCase): - - def setUp(self): - test_utils.removeOutputFolder() - os.makedirs('./testdata/test_output') - - def tearDown(self): - test_utils.removeOutputFolder() - - def checkConsistency(self, test_case_name: str): - shutil.copy('./testdata/%s.graphml' % test_case_name, './testdata/test_output/%s.graphml' % test_case_name) - graphmltoqm.main('./testdata/test_output/%s.graphml' % test_case_name) - self.maxDiff = None - - # Compare Samek's vs home-brewn implementation of the generator - with open('./testdata/%s.cpp' % test_case_name, 'r') as f: - sm1_cpp_content = test_utils.remove_boring_lines(f.read()) - with open('./testdata/test_output/%s.cpp' % test_case_name, 'r') as f: - sm2_cpp_content = test_utils.remove_boring_lines(f.read()) - self.assertEqual(sm1_cpp_content, sm2_cpp_content) - - with open('./testdata/%s.h' % test_case_name, 'r') as f: - sm1_h_content = test_utils.remove_boring_lines(f.read()) - with open('./testdata/test_output/%s.h' % test_case_name, 'r') as f: - sm2_h_content = test_utils.remove_boring_lines(f.read()) - self.assertEqual(sm1_h_content, sm2_h_content) - - def testOregonPlayer(self): - self.checkConsistency('oregonPlayer') - - def testAbility(self): - self.checkConsistency('ability') - - @unittest.skip("QM fails to process it: " - "There is a weird INFLUENCE_AT_DOGAN choice coming from " - "character::alive::neutral state. It has two branches with " - "conditions (and no [else] branch).") - def testCharacter(self): - self.checkConsistency('character') - - def testHealth(self): - self.checkConsistency('health') - - def testKaCounter(self): - self.checkConsistency('kaCounter') - - def testKaTet(self): - self.checkConsistency('kaTet') - - def testPlayerType(self): - self.checkConsistency('player_type') - - def testChoice1(self): - self.checkConsistency('choice1') - -if __name__ == '__main__': - unittest.main() diff --git a/compiler/fullgraphmlparser/service.cpp b/compiler/fullgraphmlparser/service.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/compiler/fullgraphmlparser/service_files.py b/compiler/fullgraphmlparser/service_files.py deleted file mode 100644 index ec65d46..0000000 --- a/compiler/fullgraphmlparser/service_files.py +++ /dev/null @@ -1,82 +0,0 @@ -from typing import List -from string import Template -import os - - -def create_keystrokes(signals: list) -> str: - """ - creates text for service.c - :param signals: list of signals - :return: text of keystrokes - """ - max_len: int = max([len(signal) for signal in signals]) - data = [(signal+'_SIG,'+' '*(5 + max_len - len(signal)) + '"%s"' % signal + ',' + ' '*(5 + max_len - len(signal)) - + "'%s'" % signal[0].lower()) for signal in signals] - res = '},\n{ '.join(data) - res = "{ " + res + '},' - return res - - -def create_main(sm_name: str, path: str): - """ - create main file from template - :param path: path to put main.cpp - :param sm_name:name of sm - :return: - """ - with open(os.path.join(path, "main.cpp"), "w") as f: - with open(r"src/compiler/fullgraphmlparser/templates/main_c.txt") as templ: - modelname = sm_name[0].lower() + sm_name[1:] - Modelname = sm_name[0].upper() + sm_name[1:] - text = Template(templ.read()).safe_substitute({"include": r'#include "%s.h"' % modelname + '\n', - "machine": r'"%s State Machines"\n' % Modelname, - "ctor_call": "%s_ctor()\n" % Modelname, - "sm_call": "the_%s" % modelname, - "event": "%sQEvt e" % modelname}) - - f.write(text) - - -def create_eventhandlers_files(path: str, modelname: str, functions: List): - """ - creates eventhandlers files - :param path: path to files - :param modelname: name of model - :param functions: list of functions - :return: - """ - result = r'#include "%s.h"' % modelname - functions_str = '();\nvoid '.join(functions) - result += '\n\nvoid ' - result += functions_str - result += '();' - with open(os.path.join(path, "eventHandlers.h"), "w") as f: - f.write(result) - result = r'#include "%s.h"' % modelname - result += ("\n" + r'#include "eventHandlers.h"' + '\n') - result += '//stub function, autogenerated\nvoid ' - functions_str = '() {\n \n}\n\n//stub function, autogenerated\nvoid'.join(functions) - result += functions_str - result += '() {\n \n}' - with open(os.path.join(path, "eventHadlers.cpp"), 'w') as f: - f.write(result) - - -def create_files(path: str, signals: List[str], modelname: str, functions: List[str]): - """ - creates necessary service files - :param functions: list of functions - :param modelname: name of mmdel - :param path: path to service.c - :param signals: lost of signals - :return: - """ - with open(os.path.join(path, "service.cpp"), "w") as f: - with open(r"src/compiler/fullgraphmlparser/templates/service_c.txt") as templ: - keystrokes = create_keystrokes(signals) - text = Template(templ.read()).substitute({"keystrokes": keystrokes}) - f.write(text) - with open(os.path.join(path, "cheetcodes.txt"), "w") as g: - g.write(keystrokes) - create_main(modelname, path) - create_eventhandlers_files(path, modelname, functions) diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 2473852..5266514 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -7,7 +7,7 @@ def create_note(label: 'Labels', content: str) -> 'ParserNote': """ - Создать ParserNote на основе метки вставки, и кода для вставки. + Создать ParserNote на основе метки вставки, и кода, который нужно вставить. Между label и контентом добавляется \\n, так как по этому символу\ сплитится строка в функции write_to_file. @@ -57,7 +57,11 @@ class _ParserNoteNodeLabel(BaseModel): class ParserNote(BaseModel): - """Class for code inserting.""" + """ + Class for code inserting. + + ### Create only by create_note function. + """ umlNote: _ParserNoteNodeLabel = Field(serialization_alias='y:UMLNoteNode') diff --git a/compiler/fullgraphmlparser/test.graphml b/compiler/fullgraphmlparser/test.graphml deleted file mode 100644 index cae25d6..0000000 --- a/compiler/fullgraphmlparser/test.graphml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - parent - parent_text - - - - - - - - - - - - - - - - - - - idle - lorem ipsum - - - - - - - - - - - - - - - - - not_idle - lorem ipsum - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TEST TRIGGER - - - - - - - - - - - - initial - - - - - - - - - - - - choice_trigger - - - - - - - - - - - - guard1 - - - - - - - - - - - - guard2 - - - - - - - - - - - Code for cpp-file: (do not delete this caption): -some code here - - - - - - - - - - Constructor code: (do not delete this caption): -me->test_field = test - - - - - - - - - - Constructor fields: (do not delete this caption): -unsigned int: test_constructor - - - - - - - - - - Event fields: (do not delete this caption): -unsigned int: test_event_field - - - - - - - - - - Code for h-file: (do not delete this caption): -some code for h file here - - - - - - - - - - State fields: (do not delete this caption): -unsigned int test_state_field - - - - - - - - diff --git a/compiler/fullgraphmlparser/test_utils.py b/compiler/fullgraphmlparser/test_utils.py deleted file mode 100644 index 2ee6758..0000000 --- a/compiler/fullgraphmlparser/test_utils.py +++ /dev/null @@ -1,24 +0,0 @@ -import os -import shutil -import stat - -def is_boring_line(line: str) -> bool: - line = line.strip() - if not line: - return True - if line.startswith('/*'): - return True - return False - -def remove_boring_lines(code: str) -> str: - return '\n'.join([line for line in code.split('\n') if not is_boring_line(line)]) - -def removeOutputFolder(): - if (os.path.exists('testdata/test_output')): - # Special magic is required to delete read-only files on Windows. - # See https://bugs.python.org/issue19643 and https://hg.python.org/cpython/rev/31d63ea5dffa - def remove_readonly(action, name, exc): - os.chmod(name, stat.S_IWRITE) - os.remove(name) - - shutil.rmtree('testdata/test_output', onerror=remove_readonly) diff --git a/compiler/fullgraphmlparser/testdata/ability.cpp b/compiler/fullgraphmlparser/testdata/ability.cpp deleted file mode 100644 index e1a12f2..0000000 --- a/compiler/fullgraphmlparser/testdata/ability.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/*.$file${.::ability.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: ability.qm -* File: ${.::ability.cpp} -* -*/ -/*.$endhead${.::ability.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "ability.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_ability = (QHsm *) &ability; /* the opaque pointer * -/*.$define${SMs::Ability_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Ability_ctor} ....................................................*/ -void Ability_ctor( - unsigned int ability_pause, - unsigned int ability) -{ - Ability *me = &ability; - me->ability_pause = ability_pause; - me->count = 0; - me->ability = ability; - QHsm_ctor(&me->super, Q_STATE_CAST(&Ability_initial)); -} -/*.$enddef${SMs::Ability_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::Ability} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Ability} .........................................................*/ -/*.${SMs::Ability::SM} .....................................................*/ -QState Ability_initial(Ability * const me, void const * const par) { - /*.${SMs::Ability::SM::initial} */ - - return Q_TRAN(&Ability_idle); -} -/*.${SMs::Ability::SM::global} .............................................*/ -QState Ability_global(Ability * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::Ability::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&Ability_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::Ability::SM::global::ability} ....................................*/ -QState Ability_ability(Ability * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Ability::SM::global::ability} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ability"); - #endif /* def DESKTOP */ - FlashAbilityColor(); - me->ability_pause = 0; - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ability"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Ability_global); - break; - } - } - return status_; -} -/*.${SMs::Ability::SM::global::ability::idle} ..............................*/ -QState Ability_idle(Ability * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Ability::SM::global::ability::idle} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state idle"); - #endif /* def DESKTOP */ - SavePause(); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability::idle} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state idle"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability::idle::TIME_TICK_1M} */ - case TIME_TICK_1M_SIG: { - /*.${SMs::Ability::SM::global::ability::idle::TIME_TICK_1M::[me->ability_pause>0]} */ - if (me->ability_pause > 0) { - me->ability_pause--; - SavePause(); - status_ = Q_HANDLED(); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - /*.${SMs::Ability::SM::global::ability::idle::PILL_ABILITY} */ - case PILL_ABILITY_SIG: { - me->ability = e->id; - FlashAbilityColor(); - SaveAbility(me->ability); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability::idle::LONG_PRESS_THIRD} */ - case LONG_PRESS_THIRD_SIG: { - /*.${SMs::Ability::SM::global::ability::idle::LONG_PRESS_THIRD::[me->ability_pause==0]} */ - if (me->ability_pause == 0) { - status_ = Q_TRAN(&Ability_active); - } - /*.${SMs::Ability::SM::global::ability::idle::LONG_PRESS_THIRD::[else]} */ - else { - FlashWrong(); - status_ = Q_HANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&Ability_ability); - break; - } - } - return status_; -} -/*.${SMs::Ability::SM::global::ability::active} ............................*/ -QState Ability_active(Ability * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Ability::SM::global::ability::active} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state active"); - #endif /* def DESKTOP */ - StartAbility(); - me->count = 0; - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability::active} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state active"); - #endif /* def DESKTOP */ - me->ability_pause = ABILITY_PAUSE_M; - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Ability::SM::global::ability::active::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - /*.${SMs::Ability::SM::global::ability::active::TIME_TICK_1S::[me->count>=ABILITY_THRESHOLD_1S]} */ - if (me->count >= ABILITY_THRESHOLD_1S) { - status_ = Q_TRAN(&Ability_idle); - } - /*.${SMs::Ability::SM::global::ability::active::TIME_TICK_1S::[else]} */ - else { - me->count++; - status_ = Q_HANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&Ability_ability); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::Ability::SM::final} .........................................*/ -QState Ability_final(Ability * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Ability::SM::final} */ - case Q_ENTRY_SIG: { - printf(" - Bye! Bye! - "); exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::Ability} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - -/*tranlated from diagrams code*/ diff --git a/compiler/fullgraphmlparser/testdata/ability.graphml b/compiler/fullgraphmlparser/testdata/ability.graphml deleted file mode 100644 index a768420..0000000 --- a/compiler/fullgraphmlparser/testdata/ability.graphml +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - ability - - -entry/ - FlashAbilityColor(); - me->ability_pause = 0; - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - idle - - -entry/ - SavePause(); - -TIME_TICK_1M [me->ability_pause > 0]/ - me->ability_pause--; - SavePause(); - -PILL_ABILITY/ - me->ability = e->id; - FlashAbilityColor(); - SaveAbility(me->ability); - -LONG_PRESS_THIRD[else]/ - FlashWrong(); - - - - - - - - - - - - - - - active - - -entry/ - StartAbility(); - me->count = 0; - -TIME_TICK_1S[else]/ - me->count++; - -exit/ - me->ability_pause = ABILITY_PAUSE_M; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code for h-file: (do not delete this caption): -#define ABILITY_THRESHOLD_S 30 -#define ABILITY_PAUSE_M - - - - - - - - - - - - Constructor fields (do not delete this caption): -unsigned int ability_pause; -unsigned int ability; - - - - - - - - - - - State fields (do not delete this caption): -unsigned int ability_pause; -unsigned int count; -unsigned int ability; - - - - - - - - - - - Constructor code: (do not delete this caption): - me->ability_pause = ability_pause; - me->count = 0; - me->ability = ability; - - - - - - - - - - - LONG_PRESS_THIRD [me->ability_pause == 0] - - - - - - - - - - - TIME_TICK_1S[me->count >= ABILITY_THRESHOLD_1S] - - - - - - - - - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/ability.h b/compiler/fullgraphmlparser/testdata/ability.h deleted file mode 100644 index 0c2cbf3..0000000 --- a/compiler/fullgraphmlparser/testdata/ability.h +++ /dev/null @@ -1,76 +0,0 @@ -/*.$file${.::ability.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: ability.qm -* File: ${.::ability.h} -* -*/ -/*.$endhead${.::ability.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef ability_h -#define ability_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - -//Start of h code from diagram -#define ABILITY_THRESHOLD_S 30 -#define ABILITY_PAUSE_M -//End of h code from diagram - - -/*.$declare${SMs::Ability} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Ability} .........................................................*/ -typedef struct { -/* protected: */ - QHsm super; - -/* public: */ - unsigned int ability_pause; - unsigned int count; - unsigned int ability; -} Ability; - -/* protected: */ -QState Ability_initial(Ability * const me, void const * const par); -QState Ability_global(Ability * const me, QEvt const * const e); -QState Ability_ability(Ability * const me, QEvt const * const e); -QState Ability_idle(Ability * const me, QEvt const * const e); -QState Ability_active(Ability * const me, QEvt const * const e); - -#ifdef DESKTOP -QState Ability_final(Ability * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::Ability} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static Ability ability; /* the only instance of the Ability class */ - - - -typedef struct abilityQEvt { - QEvt super; - -} abilityQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -TIME_TICK_1M_SIG, -PILL_ABILITY_SIG, -LONG_PRESS_THIRD_SIG, -TIME_TICK_1S_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_ability; /* opaque pointer to the ability HSM */ - -/*.$declare${SMs::Ability_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Ability_ctor} ....................................................*/ -void Ability_ctor( - unsigned int ability_pause, - unsigned int ability); -/*.$enddecl${SMs::Ability_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* ability_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/character.graphml b/compiler/fullgraphmlparser/testdata/character.graphml deleted file mode 100644 index f3b5309..0000000 --- a/compiler/fullgraphmlparser/testdata/character.graphml +++ /dev/null @@ -1,1058 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - character - - -entry/ - me->Todash = false; - DISPATCH_ONESHOT(BOOT); - -DOOR_START/ - if (me->Todash == false) { - me->Todash = true; - SetTodash(true); - DISPATCH_BEGIN((DOOR_VOICE); - } else { - me->Todash = false; - SetTodash(false); - DISPATCH_END(DOOR_VOICE): - } - -DOOR_NEAR_START/ - if (me->Manni == true) { - DISPATCH_BEGIN(DOOR_NEAR_MANNI); - } - -DOOR_FAR_START/ - if (me->Manni == true) { - DISPATCH_BEGIN(DOOR_FAR_MANNI); - } - -DOOR_FAR_END/ - DISPATCH_END(DOOR_FAR_MANNI); - -DOOR_NEAR_END/ - DISPATCH_END(DOOR_NEAR_MANNI); - -CRIMSON_FEELING_END / - DISPATCH_END(CRIMSON_LAUGH); - DISPATCH_END(WHITE_SORROW); - -WHITE_FEELING_END / - DISPATCH_END(CRIMSON_GRIEVE); - DISPATCH_END(WHITE_JOY); - -CRIMSON_BROADCAST1_END/ - DISPATCH_END(BROADCAST1); - -CRIMSON_BROADCAST2_END/ - DISPATCH_END(BROADCAST2); - -CRIMSON_BROADCAST3_END/ - DISPATCH_END(BROADCAST3); - -CRIMSON_BROADCAST4_END/ - DISPATCH_END(BROADCAST4); - -ROSE_END/ - DISPATCH_END(FEAR); - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - - - alive - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - - - whiten - - -WHITE_FEELING_START / - DISPATCH_BEGIN(WHITE_JOY); - -CRIMSON_FEELING_START / - DISPATCH_BEGIN(WHITE_SORROW); - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - whitish - entry/ - Vibro(LONG_VIBRO); - me->DoganScale = WHITE_THRESHOLD; - DISPATCH_ONESHOT(BECOME_WHITISH); - ScreenAddBMPToQueue("BecomeWhiter.bmp"); - SaveState(WHITISH, false, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Whitish.bmp"); - -INFLUENCE_AT_DOGAN[else]/ - me->DoganScale += ((const CharacterQEvt*)e)->amount; - - - - - - - - - - - - - - white - entry/ - Vibro(LONG_VIBRO); ScreenShowPicture("White.bmp"); - DISPATCH_ONESHOT(BECOME_WHITE); - ScreenAddBMPToQueue("White.bmp"); - DISPATCH_ONESHOT(DESTROY_KATET); - SaveState(WHITE, false, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("White.bmp"); - - - - - - - - - - - - - - - - - - - red - - -WHITE_FEELING_START/ - DISPATCH_BEGIN(CRIMSON_GRIEVE); - -CRIMSON_FEELING_START/ - DISPATCH_BEGIN(CRIMSON_LAUGH); - -CRIMSON_BROADCAST1_START/ - DISPATCH_BEGIN(BROADCAST1); - -CRIMSON_BROADCAST2_START/ - DISPATCH_BEGIN(BROADCAST2); - -CRIMSON_BROADCAST3_START/ - DISPATCH_BEGIN(BROADCAST3); - -CRIMSON_BROADCAST4_START/ - DISPATCH_BEGIN(BROADCAST4); - -ROSE_START/ - DISPATCH_BEGIN(FEAR); - ScreenAddToQueue("Fear.bmp"); - - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - crimson - entry/ - Vibro(LONG_VIBRO); - DISPATCH_ONESHOT(BECOME_CRIMSON); - ScreenAddBMPToQueue("Crimson.bmp"); - DISPATCH_ONESHOT(DESTROY_KATET); - SaveState(CRIMSON, false, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Crimson.bmp"); - - - - - - - - - - - - - - - crimsonish - entry/ - Vibro(LONG_VIBRO); - DISPATCH_ONESHOT(BECOME_CRIMSONISH); - ScreenAddBMPToQueue("Crimsonish.bmp"); - SaveState(CRIMSONISH, false, false); - me->DoganScale = CRIMSON_THRESHOLD; - -SHOW_DOGAN_STATE_START / - ScreenShowPicture("Crimsonish.bmp"); - -INFLUENCE_AT_DOGAN[else]/ - me->DoganScale += ((const CharacterQEvt*)e)->amount; - - - - - - - - - - - - - - - corrupted - entry/ - Vibro(LONG_VIBRO); - DISPATCH_ONESHOT(BECOME_CORRUPTED); - ScreenAddBMPToQueue("Corrupted.bmp"); - SaveState(CRIMSONISH, false, true); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Crimsonish.bmp"); - - - - - - - - - - - - - - - - neutral - entry/ - me->DoganScale = 0; - Vibro(LONG_VIBRO, 3); - DISPATCH_ONESHOT(BECOME_NEUTRAL); - ScreenAddBMPToQueue("Neutral.bmp"); - SaveState(NEUTRAL, false, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Neutral.bmp"); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - dead - entry/ - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - neutral_dead - entry/ - SaveState(NEUTRAL, true, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Neutral.bmp"); - - - - - - - - - - - - - - white_dead - entry/ - SaveState(WHITE, true, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("White.bmp"); - -WHITE_FEELING_START/ - DISPATCH_BEGIN(WHITE_JOY); - -CRIMSON_FEELING_START / - DISPATCH_BEGIN(WHITE_SORROW); - - - - - - - - - - - - - - - crimson_dead - entry/ - SaveState(CRIMSON, true, false); - -SHOW_DOGAN_STATE_START/ - ScreenShowPicture("Crimson.bmp"); - -WHITE_FEELING_START/ - DISPATCH_BEGIN(CRIMSON_GRIEVE); - -CRIMSON_FEELING_START/ - DISPATCH_BEGIN(CRIMSON_LAUGH); - -CRIMSON_BROADCAST1_START/ - DISPATCH_BEGIN(BROADCAST1); - -CRIMSON_BROADCAST2_START/ - DISPATCH_BEGIN(BROADCAST2); - -CRIMSON_BROADCAST3_START/ - DISPATCH_BEGIN(BROADCAST3); - -CRIMSON_BROADCAST4_START/ - DISPATCH_BEGIN(BROADCAST4); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //event fields -#int amount - -//statefields -Dispatcher* dispatcher -QStateHandler StartState -int DoganScale -bool Todash -bool Manni - -INFLUENCE_AT_DOGAN happens -every second - -//constructor fileds -$int Dogan -$bool Manni -$bool Corrupted -$bool Dead - -//ctor extra code -^me->Todash = false; -^SetTodash(false); -^me->DoganScale = 0; -^me->Manni = Manni; -^if (Dead) { -^ switch (Dogan) { -^ case CRIMSON: { -^ me->StartState = (QStateHandler)&Character_crimson_dead; -^ break; -^ } -^ case NEUTRAL: { -^ me->StartState = (QStateHandler)&Character_neutral_dead; -^ break; -^ } -^ case WHITE: { -^ me->StartState = (QStateHandler)&Character_white_dead; -^ break; -^ } -^ default: -^ me->StartState = (QStateHandler)&Character_neutral_dead; -^ break; -^ } -^} else { -^ if (Corrupted) { -^ me->StartState = (QStateHandler)&Character_corrupted; -^ } else { -^ switch (Dogan) { -^ case CRIMSON: { -^ me->StartState = (QStateHandler)&Character_crimson; -^ break; -^ } -^ case CRIMSONISH: { -^ me->DoganScale = CRIMSON_THRESHOLD; -^ me->StartState = (QStateHandler)&Character_crimsonish; -^ break; -^ } -^ case NEUTRAL: { -^ me->StartState = (QStateHandler)&Character_neutral; -^ break; -^ } -^ case WHITISH: { -^ me->DoganScale = WHITE_THRESHOLD; -^ me->StartState = (QStateHandler)&Character_whitish; -^ break; -^ } -^ case WHITE: { -^ me->StartState = (QStateHandler)&Character_white; -^ break; -^ } -^ default: -^ me->StartState = (QStateHandler)&Character_neutral; -^ break; -^ } -^ } -^} - -//code for h-file -!#define NEUTRAL 0 -!#define CRIMSON -2 -!#define CRIMSONISH -1 -!#define WHITISH 1 -!#define WHITE 2 -!#define WHITE_THRESHOLD 3600 -!#define CRIMSON_THRESHOLD -4000 - - -//code for cpp-file -?#define LONG_VIBRO 800 -?#define MEDIUM_VIBRO 500 -?#define SHORT_VIBRO 300 - - - - - - - - - - - - - MASTER_ALIVE_START - - - - - - - - - - - - - DEATH_START/ - DISPATCH_ONESHOT(DESTROY_KATET); - - - - - - - - - - - - - - - - - - - - - - - - - - - - BECOME_WHITE_MESSENGER_START - - - - - - - - - - - - - - - INFLUENCE_AT_DOGAN [me->DoganScale<=0]/ - - - - - - - - - - - - - MASTER_WHITE_START - - - - - - - - - - - - - - - MASTER_CRIMSON_START - - - - - - - - - - - - - MASTER_CRIMSON_START - - - - - - - - - - - - - - - - - - - - - - - - - DEATH_START/ - DISPATCH_ONESHOT(DESTROY_KATET); - - - - - - - - - - - - - MASTER_WHITE_START - - - - - - - - - - - - - - - NEUTRALIZE_BEGIN - - - - - - - - - - - - - BECOME_CRIMSON_SERVANT_START - - - - - - - - - - - - - - - MASTER_WHITE_START - - - - - - - - - - - - - MASTER_CRIMSON_START - - - - - - - - - - - - - - - CRIMSON_KING_SONG_START - - - - - - - - - - - - - - - INFLUENCE_AT_DOGAN [me->DoganScale >= 0] - - - - - - - - - - - - - - - MASTER_CANCEL_CORRUPT_START - - - - - - - - - - - - - BECOME_CRIMSON_SERVANT_START - - - - - - - - - - - - - - - MASTER_WHITE_START - - - - - - - - - - - - - - - MASTER_CRIMSON_START - - - - - - - - - - - - - INFLUENCE_AT_DOGAN/ - me->DoganScale += ((const CharacterQEvt*)e)->amount; - - - - - - - - - - - - - - DEATH_START/ - DISPATCH_ONESHOT(DESTROY_KATET); - - - - - - - - - - - - - - - me->DoganScale>=WHITE_THRESHOLD - - - - - - - - - - - - - - - me->DoganScale<=CRIMSON_THRESHOLD - - - - - - - - - - - - - - - - return Q_TRAN(me->StartState); - - - - - - - - - - - - - - - - BECOME_CRIMSON_SERVANT_START - - - - - - - - - - - - - - - BECOME_WHITE_MESSENGER_START - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/cheetcodes.txt b/compiler/fullgraphmlparser/testdata/cheetcodes.txt deleted file mode 100644 index a36501f..0000000 --- a/compiler/fullgraphmlparser/testdata/cheetcodes.txt +++ /dev/null @@ -1,4 +0,0 @@ -{ TIME_TICK_1M_SIG, "TIME_TICK_1M", 't'}, -{ PILL_ABILITY_SIG, "PILL_ABILITY", 'p'}, -{ LONG_PRESS_THIRD_SIG, "LONG_PRESS_THIRD", 'l'}, -{ TIME_TICK_1S_SIG, "TIME_TICK_1S", 't'}, \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/choice1.cpp b/compiler/fullgraphmlparser/testdata/choice1.cpp deleted file mode 100644 index 01d4cd2..0000000 --- a/compiler/fullgraphmlparser/testdata/choice1.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*.$file${.::choice1.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: choice1.qm -* File: ${.::choice1.cpp} -* -*/ -/*.$endhead${.::choice1.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "choice1.h" -// #include "eventHandlers.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_choice1 = (QHsm *) &choice1; /* the opaque pointer */ - -/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*. Check for the minimum required QP version */ -// #if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -// #error qpc version 6.9.0 or higher required -// #endif -/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::Choice1_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Choice1_ctor} ....................................................*/ -void Choice1_ctor(void) { - Choice1 *me = &choice1; - - QHsm_ctor(&me->super, Q_STATE_CAST(&Choice1_initial)); -} -/*.$enddef${SMs::Choice1_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::Choice1} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Choice1} .........................................................*/ -/*.${SMs::Choice1::SM} .....................................................*/ -QState Choice1_initial(Choice1 * const me, void const * const par) { - /*.${SMs::Choice1::SM::initial} */ - return Q_TRAN(&Choice1_idle); -} -/*.${SMs::Choice1::SM::global} .............................................*/ -QState Choice1_global(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::Choice1::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&Choice1_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::Choice1::SM::global::parent} .....................................*/ -QState Choice1_parent(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Choice1::SM::global::parent} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state parent"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Choice1::SM::global::parent} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state parent"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Choice1_global); - break; - } - } - return status_; -} -/*.${SMs::Choice1::SM::global::parent::idle} ...............................*/ -QState Choice1_idle(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Choice1::SM::global::parent::idle} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state idle"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Choice1::SM::global::parent::idle} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state idle"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Choice1::SM::global::parent::idle::TRIGGER} */ - case TRIGGER_SIG: { - /*.${SMs::Choice1::SM::global::parent::idle::TRIGGER::[guard]} */ - if (guard) { - do something - status_ = Q_TRAN(&Choice1_choice1); - } - /*.${SMs::Choice1::SM::global::parent::idle::TRIGGER::[else]} */ - else { - do something - status_ = Q_TRAN(&Choice1_choice2); - } - break; - } - default: { - status_ = Q_SUPER(&Choice1_parent); - break; - } - } - return status_; -} -/*.${SMs::Choice1::SM::global::choice1} ....................................*/ -QState Choice1_choice1(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Choice1::SM::global::choice1} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state choice1"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Choice1::SM::global::choice1} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state choice1"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Choice1_global); - break; - } - } - return status_; -} -/*.${SMs::Choice1::SM::global::choice2} ....................................*/ -QState Choice1_choice2(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Choice1::SM::global::choice2} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state choice2"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Choice1::SM::global::choice2} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state choice2"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Choice1_global); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::Choice1::SM::final} ..............................................*/ -QState Choice1_final(Choice1 * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Choice1::SM::final} */ - case Q_ENTRY_SIG: { - printf("Bye! Bye!"); - exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::Choice1} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - -/*tranlated from diagrams code*/ diff --git a/compiler/fullgraphmlparser/testdata/choice1.graphml b/compiler/fullgraphmlparser/testdata/choice1.graphml deleted file mode 100644 index fbcfbe2..0000000 --- a/compiler/fullgraphmlparser/testdata/choice1.graphml +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - parent - - -entry/ - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - idle - - -entry/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - choice1 - - -entry/ - - - - - - - - - - - - - - - choice2 - - -entry/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRIGGER/ -do something - - - - - - - - - - - - - - [guard] - - - - - - - - - - - - - - [else] - - - - - - - - - - - - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/choice1.h b/compiler/fullgraphmlparser/testdata/choice1.h deleted file mode 100644 index f704780..0000000 --- a/compiler/fullgraphmlparser/testdata/choice1.h +++ /dev/null @@ -1,61 +0,0 @@ -/*.$file${.::choice1.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: choice1.qm -* File: ${.::choice1.h} -* -*/ -/*.$endhead${.::choice1.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef choice1_h -#define choice1_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - - -/*.$declare${SMs::Choice1} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Choice1} .........................................................*/ -typedef struct { -/* protected: */ - QHsm super; -} Choice1; - -/* protected: */ -QState Choice1_initial(Choice1 * const me, void const * const par); -QState Choice1_global(Choice1 * const me, QEvt const * const e); -QState Choice1_parent(Choice1 * const me, QEvt const * const e); -QState Choice1_idle(Choice1 * const me, QEvt const * const e); -QState Choice1_choice1(Choice1 * const me, QEvt const * const e); -QState Choice1_choice2(Choice1 * const me, QEvt const * const e); - -#ifdef DESKTOP -QState Choice1_final(Choice1 * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::Choice1} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static Choice1 choice1; /* the only instance of the Choice1 class */ - - - -typedef struct choice1QEvt { - QEvt super; -} choice1QEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -TRIGGER_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_choice1; /* opaque pointer to the choice1 HSM */ - -/*.$declare${SMs::Choice1_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Choice1_ctor} ....................................................*/ -void Choice1_ctor(void); -/*.$enddecl${SMs::Choice1_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* choice1_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/eventHadlers.cpp b/compiler/fullgraphmlparser/testdata/eventHadlers.cpp deleted file mode 100644 index e7e1e83..0000000 --- a/compiler/fullgraphmlparser/testdata/eventHadlers.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "ability.h" -#include "eventHandlers.h" -//stub function, autogenerated -void FlashAbilityColor() { - -} - -//stub function, autogenerated -voidSavePause() { - -} - -//stub function, autogenerated -voidSaveAbility() { - -} - -//stub function, autogenerated -voidFlashWrong() { - -} - -//stub function, autogenerated -voidStartAbility() { - -} \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/eventHandlers.h b/compiler/fullgraphmlparser/testdata/eventHandlers.h deleted file mode 100644 index b501ec7..0000000 --- a/compiler/fullgraphmlparser/testdata/eventHandlers.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef EVENTSHANDLERS_H_ -#define EVENTSHANDLERS_H_ - -#include "stdio.h" -#include "qhsm.h" -#include -#include "oregonPlayer.h" - - -//logic functions -void UpdateHP(OregonPlayer* me, unsigned int HP); -void Reset(OregonPlayer* me); -void Flash(unsigned int R, unsigned int G, unsigned int B, unsigned int Timeout); -void BeepForPeriod(unsigned int Period); -void SaveHP(unsigned int HP); -void SaveTimerAgony(unsigned int Timer); -void SaveState(unsigned int State); -void ShowCurrentHealth (OregonPlayer* me); -void ShowCurrentHealthGhoul (OregonPlayer* me); -void ClearPill(void); -void PillIndicate(void); - - -#endif /* EVENTSHANDLERS_H_ */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/health.cpp b/compiler/fullgraphmlparser/testdata/health.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/compiler/fullgraphmlparser/testdata/health.graphml b/compiler/fullgraphmlparser/testdata/health.graphml deleted file mode 100644 index 3926954..0000000 --- a/compiler/fullgraphmlparser/testdata/health.graphml +++ /dev/null @@ -1,441 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - alive - - -entry/ - SetHealth(DEFAULT_HP) - StartTramsmitForPath(); - SetColor(LIGHT_GREEN); - SaveHealth(); - - - -MONSTER_SIGNAl/ - MonsterVibro(); - - -PILL_HEAL/ - SetHealth(DEFAULT_HP); - ClearPill(); - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - god - - -entry/ - SetColor(WHITE); - me->count=0; - SaveState(GOD); - -TIME_TICK_1S[else]/ - me->count++; - -exit/ - me->god_pause = GOD_PAUSE_M; - - - - - - - - - - - - - - - - - mortal - - -entry/ - -RAD_RECEIVED [else] - SetHealth(me->health-e->damage); - int red = 255*(1 - me->health/DEFAULT_HEALTH); - int green = 255*me->health/DEFAULT_HEALTH - ShowColor(red, green, 0); - VibroRadiation(); - SaveHealth(); - - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - simple - - -entry/ - SaveState(SIMPLE); - - - - - - - - - - - - - - - god_ready - - -entry/ - Flash(WHITE); - SaveState(GOD_READY); - SaveGodTimer(); - -MIDDLE_BUTTON_PRESSED[else]/ - Flash(WHITE); - -TIME_TICK_1M [god_pause > 0]/ - me->god_pause--; - SaveGodTimer(); - - - - - - - - - - - - - - - - - - - dead - - -entry/ - StopTransmit(); - SetHealth(0); - VibroDeath(); - SaveState(DEAD); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code for h-file: (do not delete this caption): - - -#define SIMPLE 0 -#define GOD_READY 1 -#define GOD 2 -#define DEAD 3 -#define DEFAULT_HP 100 -#define GOD_THRESHOLD_S 30 -#define GOD_PAUSE_M 30 - - - - - - - - - - - - - Constructor code: (do not delete this caption): - me->health = health; - me->count = 0; - me->god_pause=god_pause; - switch (State) { - case SIMPLE: { - me->StartState = - (QStateHandler)&Health_simple; - break; - } - case GOD_READY: { - me->StartState = - (QStateHandler)&Health_god_ready; - break; - } - case GOD: { - me->StartState = - (QStateHandler)&Health_god; - break; - } - case DEAD: { - me->StartState = - (QStateHandler)&Health_god; - break; - } - default: - me->StartState = - (QStateHandler)&Health_simple; - } - - - - - - - - - - - - State fields (do not delete this caption): -unsigned int health; -QStateHandler StartState; -unsigned int count; -unsigned int god_pause; - - - - - - - - - - - Event fields (do not delete this caption): - int damage; - - - - - - - - - - - Constructor fields (do not delete this caption): -unsigned int health; -unsigned int State; -unsigned int god_pause; - - - - - - - - - - PILL_GOD/ - me->god_pause=0; - - - - - - - - - - - - RAD_RECEIVED [me->health <= e->damage] - - - - - - - - - - - - - - - - - MIDDLE_BUTTON_PRESSED [me->god_pause == 0] - - - - - - - - - - - - - - PILL_RESET - - - - - - - - - - - - - LONG_PRESS - - - - - - - - - - - TIME_TICK_1S[me->count >= GOD_THRESHOLD_S] - - - - - - - - - - - - - PILL_RESET - - - - - - - - - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/health.h b/compiler/fullgraphmlparser/testdata/health.h deleted file mode 100644 index a827442..0000000 --- a/compiler/fullgraphmlparser/testdata/health.h +++ /dev/null @@ -1,91 +0,0 @@ -/*.$file${.::health.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: health.qm -* File: ${.::health.h} -* -*/ -/*.$endhead${.::health.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef health_h -#define health_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - -//Start of h code from diagram -#define SIMPLE 0 -#define GOD_READY 1 -#define GOD 2 -#define DEAD 3 -#define DEFAULT_HP 100 -#define GOD_THRESHOLD_S 30 -#define GOD_PAUSE_M 30 -//End of h code from diagram - - -/*.$declare${SMs::Health} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Health} ..........................................................*/ -typedef struct { -/* protected: */ - QHsm super; - -/* public: */ - unsigned int health; - QStateHandler StartState; - unsigned int count; - unsigned int god_pause; -} Health; - -/* protected: */ -QState Health_initial(Health * const me, void const * const par); -QState Health_global(Health * const me, QEvt const * const e); -QState Health_alive(Health * const me, QEvt const * const e); -QState Health_god(Health * const me, QEvt const * const e); -QState Health_mortal(Health * const me, QEvt const * const e); -QState Health_god_ready(Health * const me, QEvt const * const e); -QState Health_simple(Health * const me, QEvt const * const e); -QState Health_dead(Health * const me, QEvt const * const e); - -#ifdef DESKTOP -QState Health_final(Health * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::Health} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static Health health; /* the only instance of the Health class */ - - - -typedef struct healthQEvt { - QEvt super; - int damage; -} healthQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -MONSTER_SIGNAl_SIG, -PILL_HEAL_SIG, -TIME_TICK_1S_SIG, -MIDDLE_BUTTON_PRESSED_SIG, -TIME_TICK_1M_SIG, -PILL_GOD_SIG, -RAD_RECEIVED_SIG, -PILL_RESET_SIG, -LONG_PRESS_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_health; /* opaque pointer to the health HSM */ - -/*.$declare${SMs::Health_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Health_ctor} .....................................................*/ -void Health_ctor( - unsigned int health, - unsigned int State, - unsigned int god_pause); -/*.$enddecl${SMs::Health_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* health_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/kaCounter.cpp b/compiler/fullgraphmlparser/testdata/kaCounter.cpp deleted file mode 100644 index 7c0d8c2..0000000 --- a/compiler/fullgraphmlparser/testdata/kaCounter.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/*.$file${.::kaCounter.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: kaCounter.qm -* File: ${.::kaCounter.cpp} -* -*/ -/*.$endhead${.::kaCounter.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "kaCounter.h" -#include "eventHandlers.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_kaCounter = (QHsm *) &kaCounter; /* the opaque pointer */ - -/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*. Check for the minimum required QP version */ -#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -#error qpc version 6.9.0 or higher required -#endif -/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::KaCounter_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaCounter_ctor} ..................................................*/ -void KaCounter_ctor(void) { - KaCounter *me = &kaCounter; - - QHsm_ctor(&me->super, Q_STATE_CAST(&KaCounter_initial)); -} -/*.$enddef${SMs::KaCounter_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::KaCounter} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaCounter} .......................................................*/ -/*.${SMs::KaCounter::SM} ...................................................*/ -QState KaCounter_initial(KaCounter * const me, void const * const par) { - /*.${SMs::KaCounter::SM::initial} */ - return Q_TRAN(&KaCounter_idle); -} -/*.${SMs::KaCounter::SM::global} ...........................................*/ -QState KaCounter_global(KaCounter * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::KaCounter::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&KaCounter_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::KaCounter::SM::global::ka_tet_counter} ...........................*/ -QState KaCounter_ka_tet_counter(KaCounter * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaCounter::SM::global::ka_tet_counter} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ka_tet_counter"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ka_tet_counter"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::TIME_TICK_1M} */ - case TIME_TICK_1M_SIG: { - SaveCounters(me->KaTetTimers); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&KaCounter_global); - break; - } - } - return status_; -} -/*.${SMs::KaCounter::SM::global::ka_tet_counter::idle} .....................*/ -QState KaCounter_idle(KaCounter * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state idle"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state idle"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle::BEGIN(PERSON_NEAR)} */ - case BEGIN(PERSON_NEAR)_SIG: { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle::BEGIN(PERSON_NEA~::[(((me->KaTets)->get(((constKaCo~} */ - if ((((me->KaTets)->get(((const KaCounterQEvt*)e)->id)) == false) && (me->Characters->count_ones() ==1))) { - me->CurrentId = ((const KaCounterQEvt*)e)->id; - status_ = Q_TRAN(&KaCounter_ka_tet_forming); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle::END(PERSON_NEAR)} */ - case END(PERSON_NEAR)_SIG: { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::idle::END(PERSON_NEAR)::[(me->Characters->count_ones()==~} */ - if ((me->Characters->count_ones() == 1) && (me->KaTets)->get(me->Characters->find_first_one()) == false)) { - me->CurrentId = me->Characters->find_first_one(); - status_ = Q_TRAN(&KaCounter_ka_tet_forming); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&KaCounter_ka_tet_counter); - break; - } - } - return status_; -} -/*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming} ...........*/ -QState KaCounter_ka_tet_forming(KaCounter * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ka_tet_forming"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ka_tet_forming"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::END(PERSON_NEAR)} */ - case END(PERSON_NEAR)_SIG: { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::END(PERSON_NEAR)::[((constKaCounterQEvt*)e)->id==m~} */ - if (((const KaCounterQEvt*)e)->id == me->CurrentId) { - status_ = Q_TRAN(&KaCounter_idle); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::BEGIN(PERSON_NEAR)} */ - case BEGIN(PERSON_NEAR)_SIG: { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::BEGIN(PERSON_NEA~::[((constKaCounterQEvt*)e)->id!=m~} */ - if (((const KaCounterQEvt*)e)->id != me->CurrentId) { - status_ = Q_TRAN(&KaCounter_idle); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::TIME_TICK_1S::[((*(me->KaTetTimers))[me->Curre~} */ - if (((*(me->KaTetTimers))[me->CurrentId] >= KATET_THRESHOLD)) { - DISPATCH_ONESHOT_WITH_PARAM(FORM_KATET, me->CurrentId); - status_ = Q_TRAN(&KaCounter_idle); - } - /*.${SMs::KaCounter::SM::global::ka_tet_counter::ka_tet_forming::TIME_TICK_1S::[else]} */ - else { - (*(me->KaTetTimers))[me->CurrentId]++; - status_ = Q_HANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&KaCounter_ka_tet_counter); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::KaCounter::SM::final} ............................................*/ -QState KaCounter_final(KaCounter * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaCounter::SM::final} */ - case Q_ENTRY_SIG: { - printf(" - Bye! Bye! - "); exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::KaCounter} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - -/*tranlated from diagrams code*/ diff --git a/compiler/fullgraphmlparser/testdata/kaCounter.graphml b/compiler/fullgraphmlparser/testdata/kaCounter.graphml deleted file mode 100644 index 375c9d6..0000000 --- a/compiler/fullgraphmlparser/testdata/kaCounter.graphml +++ /dev/null @@ -1,269 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ka_tet_counter - entry/ - -TIME_TICK_1M/ - SaveCounters(me->KaTetTimers); - - - - - - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - idle - entry/ - - - - - - - - - - - - - - - - - - - - ka_tet_forming - entry/ - -TIME_TICK_1S[else]/ - (*(me->KaTetTimers))[me->CurrentId]++; - - - - - - - - - - - - - - - - - - - - - - - //state fields -Dispatcher* dispatcher -KaTetCounters* KaTetTimers -KaTetLinks* KaTets -NearCharacters* Characters -size_t CurrentId - -//event fields -#size_t id - -//constructor fields -$KaTetCounters* KaTetTimers -$KaTetLinks* KaTets -$NearCharacters* Characters - -//ctor extra code -^me->KaTetTimers = KaTetTimers; -^me->KaTets = KaTets; -^me->Characters = Characters; - -//code for h-file -!#define KATET_THRESHOLD 600 - - - - - - - - - - - - - - - - BEGIN(PERSON_NEAR) [(((me->KaTets)->get(((const KaCounterQEvt*)e)->id)) == false) && (me->Characters->count_ones() ==1))]/ - me->CurrentId = ((const KaCounterQEvt*)e)->id; - - - - - - - - - - - - - - - - END(PERSON_NEAR) [((const KaCounterQEvt*)e)->id == me->CurrentId] - - - - - - - - - - - - - - BEGIN(PERSON_NEAR)[((const KaCounterQEvt*)e)->id != me->CurrentId] - - - - - - - - - - - - - - - - - - TIME_TICK_1S[((*(me->KaTetTimers))[me->CurrentId] >= KATET_THRESHOLD)]/ - DISPATCH_ONESHOT_WITH_PARAM(FORM_KATET, me->CurrentId); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - END(PERSON_NEAR)[(me->Characters->count_ones() == 1) && (me->KaTets)->get(me->Characters->find_first_one()) == false) ]/ - me->CurrentId = me->Characters->find_first_one(); - - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/kaCounter.h b/compiler/fullgraphmlparser/testdata/kaCounter.h deleted file mode 100644 index a738cac..0000000 --- a/compiler/fullgraphmlparser/testdata/kaCounter.h +++ /dev/null @@ -1,63 +0,0 @@ -/*.$file${.::kaCounter.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: kaCounter.qm -* File: ${.::kaCounter.h} -* -*/ -/*.$endhead${.::kaCounter.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef kaCounter_h -#define kaCounter_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - - -/*.$declare${SMs::KaCounter} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaCounter} .......................................................*/ -typedef struct { -/* protected: */ - QHsm super; -} KaCounter; - -/* protected: */ -QState KaCounter_initial(KaCounter * const me, void const * const par); -QState KaCounter_global(KaCounter * const me, QEvt const * const e); -QState KaCounter_ka_tet_counter(KaCounter * const me, QEvt const * const e); -QState KaCounter_idle(KaCounter * const me, QEvt const * const e); -QState KaCounter_ka_tet_forming(KaCounter * const me, QEvt const * const e); - -#ifdef DESKTOP -QState KaCounter_final(KaCounter * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::KaCounter} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static KaCounter kaCounter; /* the only instance of the KaCounter class */ - - - -typedef struct kaCounterQEvt { - QEvt super; -} kaCounterQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -TIME_TICK_1M_SIG, -TIME_TICK_1S_SIG, -BEGIN(PERSON_NEAR)_SIG, -END(PERSON_NEAR)_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_kaCounter; /* opaque pointer to the kaCounter HSM */ - -/*.$declare${SMs::KaCounter_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaCounter_ctor} ..................................................*/ -void KaCounter_ctor(void); -/*.$enddecl${SMs::KaCounter_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* kaCounter_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/kaTet.cpp b/compiler/fullgraphmlparser/testdata/kaTet.cpp deleted file mode 100644 index 92607b9..0000000 --- a/compiler/fullgraphmlparser/testdata/kaTet.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/*.$file${.::kaTet.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: kaTet.qm -* File: ${.::kaTet.cpp} -* -*/ -/*.$endhead${.::kaTet.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "kaTet.h" -#include "eventHandlers.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_kaTet = (QHsm *) &kaTet; /* the opaque pointer */ - -/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*. Check for the minimum required QP version */ -#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -#error qpc version 6.9.0 or higher required -#endif -/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::KaTet_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaTet_ctor} ......................................................*/ -void KaTet_ctor(void) { - KaTet *me = &kaTet; - - QHsm_ctor(&me->super, Q_STATE_CAST(&KaTet_initial)); -} -/*.$enddef${SMs::KaTet_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::KaTet} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaTet} ...........................................................*/ -/*.${SMs::KaTet::SM} .......................................................*/ -QState KaTet_initial(KaTet * const me, void const * const par) { - /*.${SMs::KaTet::SM::initial} */ - return Q_TRAN(me->StartState); - return Q_TRAN(&KaTet_alone); -} -/*.${SMs::KaTet::SM::global} ...............................................*/ -QState KaTet_global(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::KaTet::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&KaTet_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::KaTet::SM::global::has_katet} ....................................*/ -QState KaTet_has_katet(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaTet::SM::global::has_katet} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state has_katet"); - #endif /* def DESKTOP */ - SaveKatet(me->KaTets); - me->KaTetNear = 1; - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state has_katet"); - #endif /* def DESKTOP */ - ScreenAddBMPToQueue("Katet_destroyed.bmp"); - - N(FORM_KATET)/ - (me->KaTets)->set(((const KaTetQEvt*)e)->parameters, true); - ScreenAddBMPToQueue("Katet.bmp"); - Vibro(MEDIUM_VIBRO); - SaveKatet(me->KaTets); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet::BEGIN(DESTROY_KATET)} */ - case BEGIN(DESTROY_KATET)_SIG: { - (me->KaTets)->clear(); - SaveKatet(me->KaTets); - DISPATCH_ONESHOT(KATET_DESTROYED); - status_ = Q_TRAN(&KaTet_alone); - break; - } - default: { - status_ = Q_SUPER(&KaTet_global); - break; - } - } - return status_; -} -/*.${SMs::KaTet::SM::global::has_katet::near} ..............................*/ -QState KaTet_near(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaTet::SM::global::has_katet::near} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state near"); - #endif /* def DESKTOP */ - DISPATCH_BEGIN(KATET_NEAR); - - N(PERSON_NEAR)/ - if ((me->KaTets)->get(((const KaTetQEvt*)e)->id) == true) { - me->KaTetNear++; - } - - PERSON_NEAR)[else]/ - me->KaTetNear--; - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet::near} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state near"); - #endif /* def DESKTOP */ - DISPATCH_END(KATET_NEAR); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet::near::END(PERSON_NEAR)} */ - case END(PERSON_NEAR)_SIG: { - /*.${SMs::KaTet::SM::global::has_katet::near::END(PERSON_NEAR)::[me->KaTetNear<=1]} */ - if (me->KaTetNear <= 1) { - me->KaTetNear = 0; - status_ = Q_TRAN(&KaTet_faraway); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&KaTet_has_katet); - break; - } - } - return status_; -} -/*.${SMs::KaTet::SM::global::has_katet::faraway} ...........................*/ -QState KaTet_faraway(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaTet::SM::global::has_katet::faraway} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state faraway"); - #endif /* def DESKTOP */ - - BEGIN(PERSON_NEAR)[else]/ - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet::faraway} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state faraway"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::has_katet::faraway::BEGIN(PERSON_NEAR)} */ - case BEGIN(PERSON_NEAR)_SIG: { - /*.${SMs::KaTet::SM::global::has_katet::faraway::BEGIN(PERSON_NEA~::[(me->KaTets)->get(((constKaTetQ~} */ - if ((me->KaTets)->get(((const KaTetQEvt*)e)->id) == true) { - status_ = Q_TRAN(&KaTet_near); - } - else { - status_ = Q_UNHANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&KaTet_has_katet); - break; - } - } - return status_; -} -/*.${SMs::KaTet::SM::global::alone} ........................................*/ -QState KaTet_alone(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaTet::SM::global::alone} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state alone"); - #endif /* def DESKTOP */ - - BEGIN(FEAR_PLACE)/ - DISPATCH_BEGIN(FEAR); - ScreenAddToQueue("Fear.bmp"); - - END(FEAR_PLACE)/ - DISPATCH_END(FEAR); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::alone} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state alone"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::KaTet::SM::global::alone::BEGIN(FORM_KATET)} */ - case BEGIN(FORM_KATET)_SIG: { - (me->KaTets)->set(((const KaTetQEvt*)e)->parameter, true); - ScreenAddBMPToQueue("Ka_tet.bmp"); - Vibro(MEDIUM_VIBRO); - status_ = Q_TRAN(&KaTet_faraway); - break; - } - default: { - status_ = Q_SUPER(&KaTet_global); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::KaTet::SM::final} ................................................*/ -QState KaTet_final(KaTet * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::KaTet::SM::final} */ - case Q_ENTRY_SIG: { - printf(" - Bye! Bye! - "); exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::KaTet} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -int main(){ - KaTet_ctor(); - KaTet_initial(me); -} - -/*tranlated from diagrams code*/ diff --git a/compiler/fullgraphmlparser/testdata/kaTet.graphml b/compiler/fullgraphmlparser/testdata/kaTet.graphml deleted file mode 100644 index fbce29a..0000000 --- a/compiler/fullgraphmlparser/testdata/kaTet.graphml +++ /dev/null @@ -1,309 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - alone - entry/ - -BEGIN(FEAR_PLACE)/ - DISPATCH_BEGIN(FEAR); - ScreenAddToQueue("Fear.bmp"); - -END(FEAR_PLACE)/ - DISPATCH_END(FEAR); - - - - - - - - - - - - - - - - - - - - - - - has_katet - entry/ - SaveKatet(me->KaTets); - me->KaTetNear = 1; - - -exit/ - ScreenAddBMPToQueue("Katet_destroyed.bmp"); - -BEGIN(FORM_KATET)/ - (me->KaTets)->set(((const KaTetQEvt*)e)->parameters, true); - ScreenAddBMPToQueue("Katet.bmp"); - Vibro(MEDIUM_VIBRO); - SaveKatet(me->KaTets); - - - - - - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - faraway - entry/ - -BEGIN(PERSON_NEAR)[else]/ - - - - - - - - - - - - - - - - - - - - - near - entry/ - DISPATCH_BEGIN(KATET_NEAR); - -BEGIN(PERSON_NEAR)/ - if ((me->KaTets)->get(((const KaTetQEvt*)e)->id) == true) { - me->KaTetNear++; - } - -END(PERSON_NEAR)[else]/ - me->KaTetNear--; - -exit/ - DISPATCH_END(KATET_NEAR); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ka-tet state machine - -Dispatcher* dispatcher -QStateHandler StartState -KaTetLinks* KaTets -uint8_t KaTetNear - -//event fields -#size_t id -#size_t parameter - -//ctor fields -$KaTetLinks* KaTets - -//ctor code -^me->KaTets = KaTets; -^me->KaTetNear = 0; -^if (me->KaTets->empty()) { -^ me->StartState = (QStateHandler)&KaTet_alone; -^} else { -^ me->StartState = (QStateHandler)&KaTet_faraway; -^} - -//cpp code - ?#define MEDIUM_VIBRO 500 - - - - - - - - - - - - - - - - - - - - BEGIN(FORM_KATET)/ - (me->KaTets)->set(((const KaTetQEvt*)e)->parameter, true); - ScreenAddBMPToQueue("Ka_tet.bmp"); - Vibro(MEDIUM_VIBRO); - - - - - - - - - - - - - - - - BEGIN(DESTROY_KATET)/ - (me->KaTets)->clear(); - SaveKatet(me->KaTets); - DISPATCH_ONESHOT(KATET_DESTROYED); - - - - - - - - - - - - - - - - - BEGIN(PERSON_NEAR) [(me->KaTets)->get(((const KaTetQEvt*)e)->id) == true] - - - - - - - - - - - - - - END(PERSON_NEAR) [me->KaTetNear <= 1]/ - me->KaTetNear = 0; - - - - - - - - - - - - - - return Q_TRAN(me->StartState); - - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/kaTet.h b/compiler/fullgraphmlparser/testdata/kaTet.h deleted file mode 100644 index 69f2d70..0000000 --- a/compiler/fullgraphmlparser/testdata/kaTet.h +++ /dev/null @@ -1,64 +0,0 @@ -/*.$file${.::kaTet.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: kaTet.qm -* File: ${.::kaTet.h} -* -*/ -/*.$endhead${.::kaTet.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef kaTet_h -#define kaTet_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - - -/*.$declare${SMs::KaTet} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaTet} ...........................................................*/ -typedef struct { -/* protected: */ - QHsm super; -} KaTet; - -/* protected: */ -QState KaTet_initial(KaTet * const me, void const * const par); -QState KaTet_global(KaTet * const me, QEvt const * const e); -QState KaTet_has_katet(KaTet * const me, QEvt const * const e); -QState KaTet_near(KaTet * const me, QEvt const * const e); -QState KaTet_faraway(KaTet * const me, QEvt const * const e); -QState KaTet_alone(KaTet * const me, QEvt const * const e); - -#ifdef DESKTOP -QState KaTet_final(KaTet * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::KaTet} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static KaTet kaTet; /* the only instance of the KaTet class */ - - - -typedef struct kaTetQEvt { - QEvt super; -} kaTetQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -BEGIN(FORM_KATET)_SIG, -BEGIN(DESTROY_KATET)_SIG, -BEGIN(PERSON_NEAR)_SIG, -END(PERSON_NEAR)_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_kaTet; /* opaque pointer to the kaTet HSM */ - -/*.$declare${SMs::KaTet_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::KaTet_ctor} ......................................................*/ -void KaTet_ctor(void); -/*.$enddecl${SMs::KaTet_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* kaTet_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/main.cpp b/compiler/fullgraphmlparser/testdata/main.cpp deleted file mode 100644 index 88eb73a..0000000 --- a/compiler/fullgraphmlparser/testdata/main.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include -#include -#include - -#include "bsp.h" -#include "service.h" -#include "eventHandlers.h" -#include "qhsm.h" -#include "ability.h" - -/*..........................................................................*/ - -int main() { - uint8_t i; // Universal counter - uint32_t seconds=0; - printf("Ability State Machines"\n); - #ifdef DEBUG_SM - printf("DEBUG_SM enabled\n\r"); - #endif - #ifdef DESKTOP - printf("Desktop version\n\r"); - #endif - for (i = 0; i < KeyNumber()-1; i++) // Exluding ESC - printf("%18s - '%c'\n\r", KeyStrokes[i].Alias, KeyStrokes[i].Key); - printf("Press ESC to quit...\n"); - - /* instantiate the HSM and trigger the initial transition */ - - Ability_ctor() - - QMSM_INIT(the_ability, (QEvt *)0); - QEvt e; - for (;;) { - static int tickCtr = 1; - std::string msg; - usleep(100000); - - if (kbhit()) { - char c = _getch(); /* read one character from the console */ - printf("%c: ", c); - for (i = 0; i < KeyNumber()-1; i++) { - if (c == KeyStrokes[i].Key) { - e.sig = KeyStrokes[i].Com; - msg = c; - break; - } - } - } - else if (--tickCtr == 0) { /* time for the tick? */ - tickCtr = 10; - e.sig = TIME_TICK_1S_SIG; - msg = "TICK"; - seconds++; - printf("Time: %ds. ", seconds); - } - if (msg.length()) { - /* dispatch the event into the state machine */ - QState r; - abilityQEvt e - r = QMSM_DISPATCH(the_ability, &e); - } - #ifdef DEBUG - printf("returned: %u\n\r", r); - #endif - - } - } - return 0; -} -/*..........................................................................*/ -void Q_onAssert(char const * const file, int line) { - fprintf(stderr, "Assertion failed in %s, line %d", file, line); - _exit(-1); -} diff --git a/compiler/fullgraphmlparser/testdata/oregonPlayer.cpp b/compiler/fullgraphmlparser/testdata/oregonPlayer.cpp deleted file mode 100644 index eab7e59..0000000 --- a/compiler/fullgraphmlparser/testdata/oregonPlayer.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/*.$file${.::oregonPlayer.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: oregonPlayer.qm -* File: ${.::oregonPlayer.cpp} -* -*/ -/*.$endhead${.::oregonPlayer.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "oregonPlayer.h" -#include "eventHandlers.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_oregonPlayer = (QHsm *) &oregonPlayer; /* the opaque pointer */ - -/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*. Check for the minimum required QP version */ -#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -#error qpc version 6.9.0 or higher required -#endif -/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::OregonPlayer_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::OregonPlayer_ctor} ...............................................*/ -void OregonPlayer_ctor( - unsigned int HP, - unsigned int State, - unsigned int TimerAgony) -{ - OregonPlayer *me = &oregonPlayer; - me->CharHP = HP; - me->TimerAgony = TimerAgony; - switch (State) { - case HEALTHY: { - me->StartState = - (QStateHandler)&OregonPlayer_healthy; - break; - } - case AGONY: { - me->StartState = - (QStateHandler)& OregonPlayer_agony; - break; - } - case DEAD: { - me->StartState = - (QStateHandler)& OregonPlayer_dead; - break; - - } - case GHOUL_GOOD: { - me->StartState = - (QStateHandler)& OregonPlayer_ghoul_good; - break; - } - case GHOUL_WOUNDED: { - me->StartState = - (QStateHandler)& OregonPlayer_wounded; - break; - } - case GHOUL_HEALING: { - me->StartState = - (QStateHandler)& OregonPlayer_ghoul_healing; - break; - } - case BLESSED: { - me->StartState = - (QStateHandler)& OregonPlayer_blessed; - break; - } - default: - me->StartState =(QStateHandler)& OregonPlayer_healthy; - } - QHsm_ctor(&me->super, Q_STATE_CAST(&OregonPlayer_initial)); -} -/*.$enddef${SMs::OregonPlayer_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::OregonPlayer} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::OregonPlayer} ....................................................*/ -/*.${SMs::OregonPlayer::SM} ................................................*/ -QState OregonPlayer_initial(OregonPlayer * const me, void const * const par) { - /*.${SMs::OregonPlayer::SM::initial} */ - return Q_TRAN(me->StartState); - return Q_TRAN(&OregonPlayer_healthy); -} -/*.${SMs::OregonPlayer::SM::global} ........................................*/ -QState OregonPlayer_global(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::OregonPlayer::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&OregonPlayer_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active} ................................*/ -QState OregonPlayer_active(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state active"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state active"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_global); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive} .........................*/ -QState OregonPlayer_alive(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state alive"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state alive"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_active); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive::immune} .................*/ -QState OregonPlayer_immune(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive::immune} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state immune"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state immune"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - Flash(0, GREEN_MEDIUM, 0, FLASH_SEC); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::HEAL} */ - case HEAL_SIG: { - UpdateHP(me, me->CharHP+((oregonPlayerQEvt*)e)->value); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::AGONY} */ - case AGONY_SIG: { - status_ = Q_TRAN(&OregonPlayer_agony); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_alive); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive::immune::temp_immune} ....*/ -QState OregonPlayer_temp_immune(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::temp_immune} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state temp_immune"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::temp_immune} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state temp_immune"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::temp_immune::NOT_IMMUNE} */ - case NOT_IMMUNE_SIG: { - status_ = Q_TRAN(&OregonPlayer_healthy); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_immune); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive::immune::blessed} ........*/ -QState OregonPlayer_blessed(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::blessed} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state blessed"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::immune::blessed} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state blessed"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_immune); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive::healthy} ................*/ -QState OregonPlayer_healthy(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state healthy"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state healthy"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - ShowCurrentHealth(me); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::HEAL} */ - case HEAL_SIG: { - UpdateHP(me, me->CharHP+((oregonPlayerQEvt*)e)->value); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::RAD_RCVD} */ - case RAD_RCVD_SIG: { - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::RAD_RCVD::[((oregonPlayerQEvt*)e)->value>=~} */ - if (((oregonPlayerQEvt*)e)->value >= me->CharHP) { - status_ = Q_TRAN(&OregonPlayer_agony); - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::RAD_RCVD::[else]} */ - else { - UpdateHP(me, me->CharHP-((oregonPlayerQEvt*)e)->value); - status_ = Q_HANDLED(); - } - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::AGONY} */ - case AGONY_SIG: { - status_ = Q_TRAN(&OregonPlayer_agony); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::healthy::IMMUNE} */ - case IMMUNE_SIG: { - status_ = Q_TRAN(&OregonPlayer_temp_immune); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_alive); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::alive::agony} ..................*/ -QState OregonPlayer_agony(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::alive::agony} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state agony"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state agony"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::TIME_TICK_10S} */ - case TIME_TICK_10S_SIG: { - BeepForPeriod(SHORT_BEEP_MS); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::TIME_TICK_1S::[me->TimerAgony>TIMEOUT_AGONY_S]} */ - if (me->TimerAgony > TIMEOUT_AGONY_S) { - status_ = Q_TRAN(&OregonPlayer_dead); - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::TIME_TICK_1S::[else]} */ - else { - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); - status_ = Q_HANDLED(); - } - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::BLESSED} */ - case BLESSED_SIG: { - status_ = Q_TRAN(&OregonPlayer_blessed); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::alive::agony::HEAL} */ - case HEAL_SIG: { - UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value); - status_ = Q_TRAN(&OregonPlayer_healthy); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_alive); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::ghoul} .........................*/ -QState OregonPlayer_ghoul(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::ghoul} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ghoul"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ghoul"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - ShowCurrentHealthGhoul(me); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_active); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_good} .............*/ -QState OregonPlayer_ghoul_good(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_good} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ghoul_good"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_good} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ghoul_good"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_ghoul); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing} ..........*/ -QState OregonPlayer_ghoul_healing(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state ghoul_healing"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state ghoul_healing"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing::RAD_RCVD} */ - case RAD_RCVD_SIG: { - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing::RAD_RCVD::[((((oregonPlayerQEvt*)e)->value~} */ - if (((((oregonPlayerQEvt*)e)->value+me->CharHP )>=GHOUL_HP)) { - status_ = Q_TRAN(&OregonPlayer_ghoul_good); - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::ghoul_healing::RAD_RCVD::[else]} */ - else { - UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value); - status_ = Q_HANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_ghoul); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::ghoul::wounded} ................*/ -QState OregonPlayer_wounded(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::ghoul::wounded} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state wounded"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::wounded} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state wounded"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::wounded::TIME_TICK_10S} */ - case TIME_TICK_10S_SIG: { - BeepForPeriod(SHORT_BEEP_MS); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::ghoul::wounded::RAD_RCVD} */ - case RAD_RCVD_SIG: { - UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value); - status_ = Q_TRAN(&OregonPlayer_ghoul_healing); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_ghoul); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::active::dead} ..........................*/ -QState OregonPlayer_dead(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::active::dead} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state dead"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::dead} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state dead"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::active::dead::TIME_TICK_1M} */ - case TIME_TICK_1M_SIG: { - BeepForPeriod(SHORT_BEEP_MS); - Flash(255, 0, 0, FLASH_1M); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_active); - break; - } - } - return status_; -} -/*.${SMs::OregonPlayer::SM::global::test} ..................................*/ -QState OregonPlayer_test(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::global::test} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state test"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::test} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state test"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::OregonPlayer::SM::global::test::RAD_RCVD} */ - case RAD_RCVD_SIG: { - BeepForPeriod(SHORT_BEEP_MS); - Flash(127, 0, 0, FLASH_MS); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&OregonPlayer_global); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::OregonPlayer::SM::final} .........................................*/ -QState OregonPlayer_final(OregonPlayer * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::OregonPlayer::SM::final} */ - case Q_ENTRY_SIG: { - printf(" - Bye! Bye! - "); exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::OregonPlayer} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - -/*tranlated from diagrams code*/ diff --git a/compiler/fullgraphmlparser/testdata/oregonPlayer.graphml b/compiler/fullgraphmlparser/testdata/oregonPlayer.graphml deleted file mode 100644 index 1e0e038..0000000 --- a/compiler/fullgraphmlparser/testdata/oregonPlayer.graphml +++ /dev/null @@ -1,152 +0,0 @@ - -activeentry/ - -exit/ -aliveentry/ - -exit/ -immuneentry/ - -exit/ - -TIME_TICK_1S/ - Flash(0, GREEN_MEDIUM, 0, FLASH_SEC); - -HEAL/ - UpdateHP(me, me->CharHP+((oregonPlayerQEvt*)e)->value); -temp_immuneentry/ - -exit/ -blessedentry/ - -exit/ -healthyentry/ - -exit/ - -TIME_TICK_1S/ - ShowCurrentHealth(me); - -HEAL/ - UpdateHP(me, me->CharHP+((oregonPlayerQEvt*)e)->value); - -RAD_RCVD[else]/ - UpdateHP(me, me->CharHP-((oregonPlayerQEvt*)e)->value); -agonyentry/ - -exit/ - -TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS); - -TIME_TICK_1S[else]/ - me->TimerAgony++; - Flash(RED, 0, 0, FLASH_MS); -ghoulentry/ - -exit/ - -TIME_TICK_1S/ - ShowCurrentHealthGhoul(me); -ghoul_goodentry/ - -exit/ -ghoul_healingentry/ - -exit/ - -RAD_RCVD[else]/ - UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value); -woundedentry/ - -exit/ - -TIME_TICK_10S/ - BeepForPeriod(SHORT_BEEP_MS); -deadentry/ - -exit/ - -TIME_TICK_1M/ - BeepForPeriod(SHORT_BEEP_MS); - Flash(255, 0, 0, FLASH_1M); -testentry/ - -exit/ - -RAD_RCVD/ - BeepForPeriod(SHORT_BEEP_MS); - Flash(127, 0, 0, FLASH_MS); -return Q_TRAN(me->StartState);AGONYNOT_IMMUNERAD_RCVD[((oregonPlayerQEvt*)e)->value >= me->CharHP]AGONYIMMUNETIME_TICK_1S[me->TimerAgony > TIMEOUT_AGONY_S]BLESSEDHEAL/UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value);RAD_RCVD[((((oregonPlayerQEvt*)e)->value+me->CharHP )>=GHOUL_HP)]RAD_RCVD/UpdateHP(me, me->CharHP + ((oregonPlayerQEvt*)e)->value);Constructor code: (do not delete this caption): -me->CharHP = HP; -me->TimerAgony = TimerAgony; -switch (State) { - case HEALTHY: { - me->StartState = - (QStateHandler)&OregonPlayer_healthy; - break; - } - case AGONY: { - me->StartState = - (QStateHandler)& OregonPlayer_agony; - break; - } - case DEAD: { - me->StartState = - (QStateHandler)& OregonPlayer_dead; - break; - - } - case GHOUL_GOOD: { - me->StartState = - (QStateHandler)& OregonPlayer_ghoul_good; - break; - } - case GHOUL_WOUNDED: { - me->StartState = - (QStateHandler)& OregonPlayer_wounded; - break; - } - case GHOUL_HEALING: { - me->StartState = - (QStateHandler)& OregonPlayer_ghoul_healing; - break; - } - case BLESSED: { - me->StartState = - (QStateHandler)& OregonPlayer_blessed; - break; - } - default: - me->StartState =(QStateHandler)& OregonPlayer_healthy; - }Constructor fields: (do not delete this caption): -unsigned int HP; -unsigned int State; -unsigned int TimerAgony;Event fields: (do not delete this caption): -unsigned int value;Code for h-file: (do not delete this caption): -#define HEALTHY 1 -#define AGONY 2 -#define DEAD 0 -#define GHOUL_GOOD 3 -#define GHOUL_WOUNDED 4 -#define GHOUL_HEALING 5 -#define BLESSED 6 -#define FLASH_MS 200 -#define FLASH_SEC 1010 -#define FLASH_1M 60100 -#define TIMEOUT_AGONY_S 600 -#define TIMEOUT_DEATH_S 15 -#define TIMEOUT_RADX_S 900 -#define LONG_BEEP_MS 15000 -#define MEDIUM_BEEP_MS 3000 -#define SHORT_BEEP_MS 500 -#define RED 255 -#define RED_MEDIUM 127 -#define GREEN_MEDIUM 127 -#define BLUE_MEDIUM 127 -#define DEFAULT_HP 27000 -#define GHOUL_HP (DEFAULT_HP/3) -State fields: (do not delete this caption): -unsigned int CharHP; -QStateHandler StartState; -unsigned int TimerAgony; \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/oregonPlayer.h b/compiler/fullgraphmlparser/testdata/oregonPlayer.h deleted file mode 100644 index a455268..0000000 --- a/compiler/fullgraphmlparser/testdata/oregonPlayer.h +++ /dev/null @@ -1,112 +0,0 @@ -/*.$file${.::oregonPlayer.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: oregonPlayer.qm -* File: ${.::oregonPlayer.h} -* -*/ -/*.$endhead${.::oregonPlayer.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef oregonPlayer_h -#define oregonPlayer_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - -//Start of h code from diagram -#define HEALTHY 1 -#define AGONY 2 -#define DEAD 0 -#define GHOUL_GOOD 3 -#define GHOUL_WOUNDED 4 -#define GHOUL_HEALING 5 -#define BLESSED 6 -#define FLASH_MS 200 -#define FLASH_SEC 1010 -#define FLASH_1M 60100 -#define TIMEOUT_AGONY_S 600 -#define TIMEOUT_DEATH_S 15 -#define TIMEOUT_RADX_S 900 -#define LONG_BEEP_MS 15000 -#define MEDIUM_BEEP_MS 3000 -#define SHORT_BEEP_MS 500 -#define RED 255 -#define RED_MEDIUM 127 -#define GREEN_MEDIUM 127 -#define BLUE_MEDIUM 127 -#define DEFAULT_HP 27000 -#define GHOUL_HP (DEFAULT_HP/3) -//End of h code from diagram - - -/*.$declare${SMs::OregonPlayer} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::OregonPlayer} ....................................................*/ -typedef struct { -/* protected: */ - QHsm super; - -/* public: */ - unsigned int CharHP; - QStateHandler StartState; - unsigned int TimerAgony; -} OregonPlayer; - -/* protected: */ -QState OregonPlayer_initial(OregonPlayer * const me, void const * const par); -QState OregonPlayer_global(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_active(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_alive(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_immune(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_temp_immune(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_blessed(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_healthy(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_agony(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_ghoul(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_ghoul_good(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_ghoul_healing(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_wounded(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_dead(OregonPlayer * const me, QEvt const * const e); -QState OregonPlayer_test(OregonPlayer * const me, QEvt const * const e); - -#ifdef DESKTOP -QState OregonPlayer_final(OregonPlayer * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::OregonPlayer} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static OregonPlayer oregonPlayer; /* the only instance of the OregonPlayer class */ - - - -typedef struct oregonPlayerQEvt { - QEvt super; - unsigned int value; -} oregonPlayerQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -TIME_TICK_1S_SIG, -HEAL_SIG, -RAD_RCVD_SIG, -TIME_TICK_10S_SIG, -TIME_TICK_1M_SIG, -AGONY_SIG, -NOT_IMMUNE_SIG, -IMMUNE_SIG, -BLESSED_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_oregonPlayer; /* opaque pointer to the oregonPlayer HSM */ - -/*.$declare${SMs::OregonPlayer_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::OregonPlayer_ctor} ...............................................*/ -void OregonPlayer_ctor( - unsigned int HP, - unsigned int State, - unsigned int TimerAgony); -/*.$enddecl${SMs::OregonPlayer_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* oregonPlayer_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/player_type.cpp b/compiler/fullgraphmlparser/testdata/player_type.cpp deleted file mode 100644 index c456715..0000000 --- a/compiler/fullgraphmlparser/testdata/player_type.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/*.$file${.::player_type.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: player_type.qm -* File: ${.::player_type.cpp} -* -*/ -/*.$endhead${.::player_type.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#include "qhsm.h" -#include "player_type.h" -#include "eventHandlers.h" -#include -//Q_DEFINE_THIS_FILE -/* global-scope definitions -----------------------------------------*/ -QHsm * const the_player_type = (QHsm *) &player_type; /* the opaque pointer */ - -/*.$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*. Check for the minimum required QP version */ -#if (QP_VERSION < 690U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U)) -#error qpc version 6.9.0 or higher required -#endif -/*.$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::Player_type_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Player_type_ctor} ................................................*/ -void Player_type_ctor( - Health* CharHealth, - unsigned int TimeRegen, - unsigned int State) -{ - Player_type *me = &player_type; - - me->TimeRegen = 0; - me->CharHealth = Health; - switch (State) { - case DEAD: { - me->StartState = - (QStateHandler)&Player_type_dead; - break; - } - case LOCAL: { - me->StartState = - (QStateHandler)&Player_type_regenerating; - break; - } - case TAILOR: { - me->StartState = - (QStateHandler)&Player_type_tailor; - break; - - } - case STALKER: { - me->StartState = - (QStateHandler)&Player_type_stalker; - break; - } - default: - me->StartState = - (QStateHandler)&Player_type_dead; - } - QHsm_ctor(&me->super, Q_STATE_CAST(&Player_type_initial)); -} -/*.$enddef${SMs::Player_type_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*.$define${SMs::Player_type} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Player_type} .....................................................*/ -/*.${SMs::Player_type::SM} .................................................*/ -QState Player_type_initial(Player_type * const me, void const * const par) { - /*.${SMs::Player_type::SM::initial} */ - return Q_TRAN(me->StartState); - return Q_TRAN(&Player_type_dead); -} -/*.${SMs::Player_type::SM::global} .........................................*/ -QState Player_type_global(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - -#ifdef DESKTOP - /*.${SMs::Player_type::SM::global::TERMINATE} */ - case TERMINATE_SIG: { - status_ = Q_TRAN(&Player_type_final); - break; - } -#endif /* def DESKTOP */ - - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type} ............................*/ -QState Player_type_player_type(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state player_type"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state player_type"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::PILL_TAILOR} */ - case PILL_TAILOR_SIG: { - status_ = Q_TRAN(&Player_type_tailor); - break; - } - /*.${SMs::Player_type::SM::global::player_type::PILL_STALKER} */ - case PILL_STALKER_SIG: { - UpdateMaxHP(me->CharHealth, StalkerHP); - PlayerType_Save(STALKER); - status_ = Q_TRAN(&Player_type_regenerating); - break; - } - /*.${SMs::Player_type::SM::global::player_type::PILL_LOCAL} */ - case PILL_LOCAL_SIG: { - status_ = Q_TRAN(&Player_type_regenerating); - break; - } - /*.${SMs::Player_type::SM::global::player_type::PILL_RESET} */ - case PILL_RESET_SIG: { - status_ = Q_TRAN(&Player_type_normal); - break; - } - default: { - status_ = Q_SUPER(&Player_type_global); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive} .....................*/ -QState Player_type_alive(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state alive"); - #endif /* def DESKTOP */ - SIMPLE_DISPATCH(the_health, RESET); - SIMPLE_DISPATCH(the_ability, RESET); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state alive"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::PILL_RESET} */ - case PILL_RESET_SIG: { - SIMPLE_DISPATCH(the_health, RESET); - IMPLE_DISPATCH(the_ability, RESET); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Player_type_player_type); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate} .....*/ -QState Player_type_may_regenerate(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state may_regenerate"); - #endif /* def DESKTOP */ - UpdateMaxHP(me->CharHealth; LocalHP); - Flash(0, 0, 255, FLASH_MS); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state may_regenerate"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Player_type_alive); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal} */ -QState Player_type_normal(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state normal"); - #endif /* def DESKTOP */ - TimerRegen_Update(me, 0); - PlayerType_Save(LOCAL); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state normal"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal::DMG_RCVD} */ - case DMG_RCVD_SIG: { - TimerRegen_Update(me, 0); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal::TIME_TICK_1S::[me->TimerRegen>RegenThresh]} */ - if (me->TimerRegen > RegenThresh) { - status_ = Q_TRAN(&Player_type_regenerating); - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::normal::TIME_TICK_1S::[else]} */ - else { - TimerRegen_Update(me, TimerRegen+1); - status_ = Q_HANDLED(); - } - break; - } - default: { - status_ = Q_SUPER(&Player_type_may_regenerate); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::regenerating} */ -QState Player_type_regenerating(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::regenerating} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state regenerating"); - #endif /* def DESKTOP */ - PlayerType_Save(LOCAL); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::regenerating} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state regenerating"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::regenerating::TIME_TICK_1S} */ - case TIME_TICK_1S_SIG: { - playerTypeQEvt new_e; - new_e.super.sig = HEAL_SIG; - new_e.Value = HealAmount; - QMSM_DISPATCH(the_health, (QEvt *)&new_e); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::may_regenerate::regenerating::DMG_RCVD} */ - case DMG_RCVD_SIG: { - status_ = Q_TRAN(&Player_type_normal); - break; - } - default: { - status_ = Q_SUPER(&Player_type_may_regenerate); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive::tailor} .............*/ -QState Player_type_tailor(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive::tailor} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state tailor"); - #endif /* def DESKTOP */ - UpdateMaxHP(me->CharHealth, TailorHP); - Flash(255, 255, 0, FLASH_MS); - PlayerType_Save(TAILOR); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::tailor} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state tailor"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Player_type_alive); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::alive::stalker} ............*/ -QState Player_type_stalker(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::alive::stalker} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state stalker"); - #endif /* def DESKTOP */ - UpdateMaxHP(me->CharHealth, StalkerHP); - Flash(255, 0, 0, FLASH_MS); - PlayerType_Save(STALKER); - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::alive::stalker} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state stalker"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Player_type_alive); - break; - } - } - return status_; -} -/*.${SMs::Player_type::SM::global::player_type::dead} ......................*/ -QState Player_type_dead(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::global::player_type::dead} */ - case Q_ENTRY_SIG: { - #ifdef DESKTOP - printf("Entered state dead"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - /*.${SMs::Player_type::SM::global::player_type::dead} */ - case Q_EXIT_SIG: { - #ifdef DESKTOP - printf("Exited state dead"); - #endif /* def DESKTOP */ - - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&Player_type_player_type); - break; - } - } - return status_; -} - -#ifdef DESKTOP -/*.${SMs::Player_type::SM::final} ..........................................*/ -QState Player_type_final(Player_type * const me, QEvt const * const e) { - QState status_; - switch (e->sig) { - /*.${SMs::Player_type::SM::final} */ - case Q_ENTRY_SIG: { - printf(" - Bye! Bye! - "); exit(0); - status_ = Q_HANDLED(); - break; - } - default: { - status_ = Q_SUPER(&QHsm_top); - break; - } - } - return status_; -} -#endif /* def DESKTOP */ - -/*.$enddef${SMs::Player_type} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - - -/*tranlated from diagrams code*/ - -//Start of c code from diagram -//stub code -unsigned int TailorHP = TAILOR_HP; -unsigned int LocalHP = LOCAL_HP; -unsigned int StalkerHP = STALKER_HP; -//End of c code from diagram diff --git a/compiler/fullgraphmlparser/testdata/player_type.graphml b/compiler/fullgraphmlparser/testdata/player_type.graphml deleted file mode 100644 index ab29638..0000000 --- a/compiler/fullgraphmlparser/testdata/player_type.graphml +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - player_type - - -entry/ - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - - - alive - - -entry/ - SIMPLE_DISPATCH(the_health, RESET); - SIMPLE_DISPATCH(the_ability, RESET); - -PILL_RESET/ - SIMPLE_DISPATCH(the_health, RESET); - SIMPLE_DISPATCH(the_ability, RESET); - - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - tailor - entry/ - UpdateMaxHP(me->CharHealth, TailorHP); - Flash(255, 255, 0, FLASH_MS); - PlayerType_Save(TAILOR); - - - - - - - - - - - - - - stalker - entry/ - UpdateMaxHP(me->CharHealth, StalkerHP); - Flash(255, 0, 0, FLASH_MS); - PlayerType_Save(STALKER); - - - - - - - - - - - - - - - - may_regenerate - - -entry/ - UpdateMaxHP(me->CharHealth; LocalHP); - Flash(0, 0, 255, FLASH_MS); - - - - - - - - - - - get_shot - - - - - - - - - - - - - - - - - normal - entry/ - TimerRegen_Update(me, 0); - PlayerType_Save(LOCAL); - -DMG_RCVD/ - TimerRegen_Update(me, 0); - -TIME_TICK_1S[else]/ - TimerRegen_Update(me, TimerRegen+1); - - - - - - - - - - - - - - regenerating - entry/ - PlayerType_Save(LOCAL); - -TIME_TICK_1S/ - playerTypeQEvt new_e; - new_e.super.sig = HEAL_SIG; - new_e.Value = HealAmount; - QMSM_DISPATCH(the_health, (QEvt *)&new_e); - - - - - - - - - - - - - - - - - - dead - entry/ - - - - - - - - - - - - - - - - - - Code for h-file: (do not delete this caption): -#define LOCAL 1 -#define TAILOR 2 -#define STALKER 3 -#define DEAD 0 -#define REGEN_THRESH_S 60 -#define LOCAL_HP 40 -#define TAILOR_HP 60 -#define STALKER_HP 100 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Constructor fields (do not delete this caption): -Health* CharHealth; -unsigned int TimeRegen; -unsigned int State; - - - - - - - - - - - State fields (do not delete this caption): -unsigned int TimerRegen; -Health* CharHealth; - - - - - - - - - - - Constructor code: do not delete this caption): - - me->TimeRegen = 0; - me->CharHealth = Health; - switch (State) { - case DEAD: { - me->StartState = - (QStateHandler)&Player_type_dead; - break; - } - case LOCAL: { - me->StartState = - (QStateHandler)&Player_type_regenerating; - break; - } - case TAILOR: { - me->StartState = - (QStateHandler)&Player_type_tailor; - break; - - } - case STALKER: { - me->StartState = - (QStateHandler)&Player_type_stalker; - break; - } - default: - me->StartState = - (QStateHandler)&Player_type_dead; - } - - - - - - - - - - - Event fields (do not delete this caption): -int value; - - - - - - - - - - - Code for cpp-file: (do not delete this caption): -//stub code -unsigned int TailorHP = TAILOR_HP; -unsigned int LocalHP = LOCAL_HP; -unsigned int StalkerHP = STALKER_HP; - - - - - - - - - - - - PILL_TAILOR - - - - - - - - - - - - - - PILL_STALKER/ - UpdateMaxHP(me->CharHealth, StalkerHP); - PlayerType_Save(STALKER); - - - - - - - - - - - - - - PILL_LOCAL - - - - - - - - - - - - - - TIME_TICK_1S[me->TimerRegen > RegenThresh] - - - - - - - - - - - PILL_RESET - - - - - - - - - - - - - return Q_TRAN(me->StartState); - - - - - - - - - - - - - - - - DMG_RCVD - - - - - - - - - - - diff --git a/compiler/fullgraphmlparser/testdata/player_type.h b/compiler/fullgraphmlparser/testdata/player_type.h deleted file mode 100644 index a4ca6f8..0000000 --- a/compiler/fullgraphmlparser/testdata/player_type.h +++ /dev/null @@ -1,89 +0,0 @@ -/*.$file${.::player_type.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/* -* Model: player_type.qm -* File: ${.::player_type.h} -* -*/ -/*.$endhead${.::player_type.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifndef player_type_h -#define player_type_h -#ifdef __cplusplus -extern "C" { -#endif -#include "qhsm.h" /* include own framework tagunil version */ - -//Start of h code from diagram -#define LOCAL 1 -#define TAILOR 2 -#define STALKER 3 -#define DEAD 0 -#define REGEN_THRESH_S 60 -#define LOCAL_HP 40 -#define TAILOR_HP 60 -#define STALKER_HP 100 -//End of h code from diagram - - -/*.$declare${SMs::Player_type} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Player_type} .....................................................*/ -typedef struct { -/* protected: */ - QHsm super; - -/* public: */ - unsigned int TimerRegen; - Health* CharHealth; -} Player_type; - -/* protected: */ -QState Player_type_initial(Player_type * const me, void const * const par); -QState Player_type_global(Player_type * const me, QEvt const * const e); -QState Player_type_player_type(Player_type * const me, QEvt const * const e); -QState Player_type_alive(Player_type * const me, QEvt const * const e); -QState Player_type_may_regenerate(Player_type * const me, QEvt const * const e); -QState Player_type_normal(Player_type * const me, QEvt const * const e); -QState Player_type_regenerating(Player_type * const me, QEvt const * const e); -QState Player_type_tailor(Player_type * const me, QEvt const * const e); -QState Player_type_stalker(Player_type * const me, QEvt const * const e); -QState Player_type_dead(Player_type * const me, QEvt const * const e); - -#ifdef DESKTOP -QState Player_type_final(Player_type * const me, QEvt const * const e); -#endif /* def DESKTOP */ - -/*.$enddecl${SMs::Player_type} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - -static Player_type player_type; /* the only instance of the Player_type class */ - - - -typedef struct player_typeQEvt { - QEvt super; - int value; -} player_typeQEvt; - -enum PlayerSignals { -TICK_SEC_SIG = Q_USER_SIG, - -PILL_RESET_SIG, -DMG_RCVD_SIG, -TIME_TICK_1S_SIG, -PILL_TAILOR_SIG, -PILL_STALKER_SIG, -PILL_LOCAL_SIG, - -LAST_USER_SIG -}; -extern QHsm * const the_player_type; /* opaque pointer to the player_type HSM */ - -/*.$declare${SMs::Player_type_ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -/*.${SMs::Player_type_ctor} ................................................*/ -void Player_type_ctor( - Health* CharHealth, - unsigned int TimeRegen, - unsigned int State); -/*.$enddecl${SMs::Player_type_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -#ifdef __cplusplus -} -#endif -#endif /* player_type_h */ \ No newline at end of file diff --git a/compiler/fullgraphmlparser/testdata/qhsm.h b/compiler/fullgraphmlparser/testdata/qhsm.h deleted file mode 100644 index 473d1a8..0000000 --- a/compiler/fullgraphmlparser/testdata/qhsm.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef QHSM_H -#define QHSM_H -/****************************************************************************/ -/*! The current QP version as a decimal constant XXYZ, where XX is a 2-digit -* major version number, Y is a 1-digit minor version number, and Z is -* a 1-digit release number. -*/ -#define QP_VERSION 650U - -/*! The current QP version number string of the form XX.Y.Z, where XX is -* a 2-digit major version number, Y is a 1-digit minor version number, -* and Z is a 1-digit release number. -*/ -#define QP_VERSION_STR "6.5.0" - -/*! Tamperproof current QP release (6.5.0) and date (2019-03-31) */ -#define QP_RELEASE 0x8E8DC8C5U - - -/****************************************************************************/ - - -#include - -#define Q_MAX_DEPTH 8 - -typedef int QSignal; -typedef int QState; - -typedef struct -{ - QSignal sig; -} QEvt; - -typedef QState (*QStateHandler)(void *const me, const QEvt *const event); - -enum -{ - QEP_EMPTY_SIG_ = 0, - Q_ENTRY_SIG, - Q_EXIT_SIG, - Q_INIT_SIG, - Q_USER_SIG, -}; - -enum -{ - Q_RET_SUPER, - Q_RET_UNHANDLED, - Q_RET_HANDLED, - Q_RET_IGNORED, - Q_RET_TRAN, -}; - -typedef struct -{ - QStateHandler current_; - QStateHandler effective_; - QStateHandler target_; -} QHsm; - -#define Q_MSM_UPCAST(me) ((QHsm *)(me)) -#define Q_STATE_CAST(handler) ((QStateHandler)(handler)) - -#define Q_UNHANDLED() ((QState)(Q_RET_UNHANDLED)) -#define Q_HANDLED() ((QState)(Q_RET_HANDLED)) -#define Q_TRAN(target) \ - ((Q_MSM_UPCAST(me))->target_ = Q_STATE_CAST(target), \ - (QState)(Q_RET_TRAN)) -#define Q_SUPER(super) \ - ((Q_MSM_UPCAST(me))->effective_ = Q_STATE_CAST(super), \ - (QState)(Q_RET_SUPER)) - -#define QMSM_INIT(me, event) (QMsm_init(me, event)) -#define QMSM_DISPATCH(me, event) (QMsm_dispatch(me, event)) - -#define SIMPLE_DISPATCH(me_, sig_) \ - do { QEvt e_; e_.sig = sig_##_SIG; QMSM_DISPATCH(me_, &e_); } while (0) // Macro to simple dispatch calls with signal only - -#define PASS_EVENT_TO(obj_) \ - do { QMSM_DISPATCH(obj_, e); } while (0) // Macro with clear name - -#ifdef __cplusplus -extern "C" { -#endif - -QState QHsm_top(void *const me, const QEvt *const event); - -void QHsm_ctor(QHsm *const me, QStateHandler initial); - -void QMsm_init(QHsm *me, const QEvt *const event); -QState QMsm_dispatch(QHsm *me, const QEvt *const event); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/compiler/fullgraphmlparser/testdata/service.cpp b/compiler/fullgraphmlparser/testdata/service.cpp deleted file mode 100644 index ee76c26..0000000 --- a/compiler/fullgraphmlparser/testdata/service.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "service.h" - -const KeyStroke KeyStrokes[]= { -{ TIME_TICK_1M_SIG, "TIME_TICK_1M", 't'}, -{ PILL_ABILITY_SIG, "PILL_ABILITY", 'p'}, -{ LONG_PRESS_THIRD_SIG, "LONG_PRESS_THIRD", 'l'}, -{ TIME_TICK_1S_SIG, "TIME_TICK_1S", 't'}, -{ TERMINATE_SIG, "TERMINATE", 0x1B } - -}; - -unsigned int KeyNumber() { - return sizeof(KeyStrokes)/sizeof(KeyStrokes[0]); -} diff --git a/compiler/types/platform_types.py b/compiler/types/platform_types.py index 39c4218..4405712 100644 --- a/compiler/types/platform_types.py +++ b/compiler/types/platform_types.py @@ -81,3 +81,4 @@ class Platform(BaseModel): compilingSettings: CompilingSettings components: Dict[str, Component] delimeter: str + compile: bool From e00236471be5590c2c42413b25d809ee78753247 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 3 Apr 2024 14:44:47 +0800 Subject: [PATCH 12/14] generate code that includes libraries --- compiler/CGML.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/compiler/CGML.py b/compiler/CGML.py index b807ff9..3e6ebc3 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -34,6 +34,7 @@ _StateId = str _ComponentId = str +_INCLUDE_TEMPLATE = Template('#include "$component_type.h"') _CALL_FUNCTION_TEMPLATE = Template('$id$delimeter$method($args);') _CHECK_SIGNAL_TEMPLATE = Template( """ @@ -420,6 +421,14 @@ def __generate_loop_tick_actions_code( platform: Platform, components: Dict[_ComponentId, InnerComponent] ) -> List[ParserNote]: + """ + Generate code, that will be call every loop's tick. + + Generated code example: + ```cpp + analogIn.read(); + ``` + """ notes: List[ParserNote] = [] for component_id, component in components.items(): platform_component: Component = platform.components[component.type] @@ -462,6 +471,26 @@ def __generate_setup_function_code( return notes +def __get_include_libraries(platform: Platform, + components: List[InnerComponent]) -> Set[str]: + """Get set of source files, that must be included.""" + included_libraries: Set[str] = set() + for component in components: + included_libraries.update( + platform.components[component.type].importFiles) + return set([component.type for component in components]) + + +def __generate_includes_libraries_code( + included_libraries: Set[str] +) -> List[ParserNote]: + """Generate code for including libraries using _INCLUDE_TEMPLATE.""" + return [create_note( + Labels.H_INCLUDE, + _INCLUDE_TEMPLATE.substitute({'component_type': type}) + ) for type in included_libraries] + + def parse(xml: str) -> StateMachine: """ Parse XML with cyberiadaml-py library and convert it\ @@ -532,10 +561,13 @@ def parse(xml: str) -> StateMachine: signals = __get_signals_set(all_triggers) parsed_components = __parse_components(cgml_scheme.components) + included_libraries: Set[str] = __get_include_libraries( + platform, list(parsed_components.values())) notes: List[ParserNote] = [ *__generate_create_components_code(parsed_components, platform), *__generate_setup_function_code(parsed_components, platform), - *__generate_loop_tick_actions_code(platform, parsed_components), + *__generate_includes_libraries_code(included_libraries), + * __generate_loop_tick_actions_code(platform, parsed_components), *__generate_loop_signal_checks_code(platform, all_triggers, parsed_components) From 6f4fb87289e97ea0a8eb7bca1c60f235ba340c69 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Wed, 3 Apr 2024 17:31:53 +0800 Subject: [PATCH 13/14] wip: cgml handling, change library directory structure --- compiler/CGML.py | 33 ++++-- compiler/Compiler.py | 58 +++++++++-- compiler/config.py | 2 +- compiler/fullgraphmlparser/stateclasses.py | 19 +++- compiler/handler.py | 96 +++++++++++++++++- .../{ino/source => ArduinoUno}/AnalogIn.h | 0 .../{ino/source => ArduinoUno}/AnalogIn.ino | 0 .../{ino/source => ArduinoUno}/AnalogOut.h | 0 .../{ino/source => ArduinoUno}/AnalogOut.ino | 0 .../{ino/source => ArduinoUno}/Button.h | 0 .../{ino/source => ArduinoUno}/Button.ino | 0 .../{ino/source => ArduinoUno}/Counter.h | 0 .../{ino/source => ArduinoUno}/Counter.ino | 0 .../{ino/source => ArduinoUno}/DigitalIn.h | 0 .../{ino/source => ArduinoUno}/DigitalIn.ino | 0 .../{ino/source => ArduinoUno}/DigitalOut.h | 0 .../{ino/source => ArduinoUno}/DigitalOut.ino | 0 .../library/{ino/source => ArduinoUno}/LED.h | 0 .../{ino/source => ArduinoUno}/LED.ino | 0 .../{ino/source => ArduinoUno}/Math.cpp | 0 .../library/{ino/source => ArduinoUno}/Math.h | 0 .../library/{ino/source => ArduinoUno}/PWM.h | 0 .../{ino/source => ArduinoUno}/PWM.ino | 0 .../{ino/source => ArduinoUno}/QHsmSerial.h | 0 .../{ino/source => ArduinoUno}/QHsmSerial.ino | 0 .../source => ArduinoUno}/ShiftRegister.h | 0 .../source => ArduinoUno}/ShiftRegister.ino | 0 .../{ino/source => ArduinoUno}/Timer.h | 0 .../{ino/source => ArduinoUno}/Timer.ino | 4 +- .../library/{ino/source => default}/qhsm.c | 0 .../library/{ino/source => default}/qhsm.h | 0 compiler/library/ino/build/Button.o | Bin 2944 -> 0 bytes compiler/library/ino/build/Led.o | Bin 3192 -> 0 bytes compiler/library/ino/build/qhsm.o | Bin 3360 -> 0 bytes compiler/platforms/Arduino.json | 2 +- compiler/routes.py | 1 + test/test_cgml.py | 14 ++- 37 files changed, 200 insertions(+), 29 deletions(-) rename compiler/library/{ino/source => ArduinoUno}/AnalogIn.h (100%) rename compiler/library/{ino/source => ArduinoUno}/AnalogIn.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/AnalogOut.h (100%) rename compiler/library/{ino/source => ArduinoUno}/AnalogOut.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/Button.h (100%) rename compiler/library/{ino/source => ArduinoUno}/Button.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/Counter.h (100%) rename compiler/library/{ino/source => ArduinoUno}/Counter.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/DigitalIn.h (100%) rename compiler/library/{ino/source => ArduinoUno}/DigitalIn.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/DigitalOut.h (100%) rename compiler/library/{ino/source => ArduinoUno}/DigitalOut.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/LED.h (100%) rename compiler/library/{ino/source => ArduinoUno}/LED.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/Math.cpp (100%) rename compiler/library/{ino/source => ArduinoUno}/Math.h (100%) rename compiler/library/{ino/source => ArduinoUno}/PWM.h (100%) rename compiler/library/{ino/source => ArduinoUno}/PWM.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/QHsmSerial.h (100%) rename compiler/library/{ino/source => ArduinoUno}/QHsmSerial.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/ShiftRegister.h (100%) rename compiler/library/{ino/source => ArduinoUno}/ShiftRegister.ino (100%) rename compiler/library/{ino/source => ArduinoUno}/Timer.h (100%) rename compiler/library/{ino/source => ArduinoUno}/Timer.ino (98%) rename compiler/library/{ino/source => default}/qhsm.c (100%) rename compiler/library/{ino/source => default}/qhsm.h (100%) delete mode 100644 compiler/library/ino/build/Button.o delete mode 100644 compiler/library/ino/build/Led.o delete mode 100644 compiler/library/ino/build/qhsm.o diff --git a/compiler/CGML.py b/compiler/CGML.py index 3e6ebc3..c7e0218 100644 --- a/compiler/CGML.py +++ b/compiler/CGML.py @@ -27,14 +27,15 @@ ParserTrigger, ParserNote, Labels, - create_note + create_note, + SMCompilingSettings ) _TransitionId = str _StateId = str _ComponentId = str -_INCLUDE_TEMPLATE = Template('#include "$component_type.h"') +_INCLUDE_TEMPLATE = Template('#include "$component_type"') _CALL_FUNCTION_TEMPLATE = Template('$id$delimeter$method($args);') _CHECK_SIGNAL_TEMPLATE = Template( """ @@ -373,7 +374,6 @@ def __generate_signal_checker( platform_component: Component = platform.components[component_type] signal: Signal = platform_component.signals[method] call_method = signal.checkMethod - print(call_method) condition = __generate_function_call( platform, component_type, component_id, call_method, '') return _CHECK_SIGNAL_TEMPLATE.substitute({ @@ -478,7 +478,7 @@ def __get_include_libraries(platform: Platform, for component in components: included_libraries.update( platform.components[component.type].importFiles) - return set([component.type for component in components]) + return included_libraries def __generate_includes_libraries_code( @@ -491,6 +491,18 @@ def __generate_includes_libraries_code( ) for type in included_libraries] +def __get_build_files( + platform: Platform, + components: List[InnerComponent] +) -> Set[str]: + """Get set of files, that must be included for compiling.""" + build_libraries: Set[str] = set() + for component in components: + build_libraries.update( + platform.components[component.type].buildFiles) + return build_libraries + + def parse(xml: str) -> StateMachine: """ Parse XML with cyberiadaml-py library and convert it\ @@ -563,6 +575,7 @@ def parse(xml: str) -> StateMachine: parsed_components = __parse_components(cgml_scheme.components) included_libraries: Set[str] = __get_include_libraries( platform, list(parsed_components.values())) + build_files = __get_build_files(platform, list(parsed_components.values())) notes: List[ParserNote] = [ *__generate_create_components_code(parsed_components, platform), *__generate_setup_function_code(parsed_components, platform), @@ -572,12 +585,18 @@ def parse(xml: str) -> StateMachine: all_triggers, parsed_components) ] - + compiling_settings = SMCompilingSettings( + included_libraries, + build_files, + platform.id, + platform.compilingSettings + ) return StateMachine( start_node=start_node, name='sketch', start_action='', - notes=notes, # TODO: Сгенерировать вставки для кода. + notes=notes, states=[global_state, *list(states_with_parents.values())], - signals=signals + signals=signals, + compiling_settings=compiling_settings ) diff --git a/compiler/Compiler.py b/compiler/Compiler.py index 1080bd4..bfdd56a 100644 --- a/compiler/Compiler.py +++ b/compiler/Compiler.py @@ -1,8 +1,8 @@ """Module implements communication with compilers.""" - -from typing import Dict, List, Set, TypedDict +import os import asyncio from asyncio.subprocess import Process +from typing import Dict, List, Set, TypedDict from pydantic.dataclasses import dataclass from aiopath import AsyncPath @@ -39,9 +39,8 @@ class SupportedCompiler(TypedDict): class Compiler: """Class for compiling, copying libraries sources.""" - - c_default_libraries = set(['qhsm']) - + DEFAULT_LIBRARY_ID = 'default' + c_default_libraries = set(['qhsm']) # legacy supported_compilers: Dict[str, SupportedCompiler] = { 'gcc': { 'extension': ['.c', '.cpp'], @@ -90,12 +89,36 @@ async def getBuildFiles( ... return build_files + @staticmethod + async def compile_project( + base_dir: str, + flags: List[str], + compiler: str + ) -> CompilerResult: + """Compile project in base_dir by compiler with flags.""" + process: Process = await asyncio.create_subprocess_exec( + compiler, + *flags, + cwd=base_dir, + text=False, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + await process.wait() + stdout, stderr = await process.communicate() + if process.returncode is None: + raise CompilerException('Process doesnt return code.') + + return CompilerResult(process.returncode, + str(stdout.decode('utf-8')), + str(stderr.decode('utf-8'))) + @staticmethod async def compile(base_dir: str, build_files: Set[str], flags: List[str], compiler: SupportedCompilers) -> CompilerResult: - """Run compiler with choosen settings.""" + """(Legacy, use compile_project) Run compiler with choosen settings.""" match compiler: case 'g++' | 'gcc': await AsyncPath(base_dir + 'build/').mkdir(parents=True, @@ -105,7 +128,8 @@ async def compile(base_dir: str, process: Process = await asyncio.create_subprocess_exec( compiler, *build_files, - *flags, cwd=base_dir, + *flags, + cwd=base_dir, text=False, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE @@ -113,7 +137,6 @@ async def compile(base_dir: str, case 'arduino-cli': process = await asyncio.create_subprocess_exec( compiler, - 'compile', '--export-binaries', *flags, *build_files, @@ -131,16 +154,31 @@ async def compile(base_dir: str, str(stdout.decode('utf-8')), str(stderr.decode('utf-8'))) + @staticmethod + async def include_source_files(platform_id: str, + libraries: Set[str], + target_directory: str) -> None: + """Include source files from platform's \ + library directory to target directory.""" + path = os.path.join(LIBRARY_PATH, f'{platform_id}/') + path_to_libs = set([os.path.join(path, library) + for library in libraries]) + await asyncio.create_subprocess_exec('cp', + *path_to_libs, + target_directory, + cwd=BUILD_DIRECTORY) + @staticmethod async def includeLibraryFiles( libraries: Set[str], target_directory: str, extension: str, platform: str) -> None: - """Функция, которая копирует все необходимые файлы библиотек.""" + """(Legacy, use include_source_files) \ + Функция, которая копирует все необходимые файлы библиотек.""" paths_to_libs = [''.join( [ - f'{Compiler._path(platform)}source/', + f'{Compiler._path(platform)}/', library, extension] ) for library in libraries] diff --git a/compiler/config.py b/compiler/config.py index ca5b8d6..4e31da1 100644 --- a/compiler/config.py +++ b/compiler/config.py @@ -11,4 +11,4 @@ LIBRARY_PATH = os.path.join(MODULE_PATH, 'library/') PLATFORM_DIRECTORY = os.path.join(MODULE_PATH, 'platforms/') LOG_PATH = 'logs.log' # Замените на нужную папку -MAX_MSG_SIZE = 1024 * 50 # Максимальный размер сообщения от клиента. \ No newline at end of file +MAX_MSG_SIZE = 1024 * 50 # Максимальный размер сообщения от клиента. diff --git a/compiler/fullgraphmlparser/stateclasses.py b/compiler/fullgraphmlparser/stateclasses.py index 5266514..d45d968 100644 --- a/compiler/fullgraphmlparser/stateclasses.py +++ b/compiler/fullgraphmlparser/stateclasses.py @@ -1,8 +1,15 @@ -from typing import List, Optional, Set, Protocol, runtime_checkable +from typing import ( + List, + Optional, + Set, + Protocol, + runtime_checkable +) from enum import Enum from pydantic import Field, BaseModel, ConfigDict from pydantic.dataclasses import dataclass +from compiler.types.platform_types import CompilingSettings def create_note(label: 'Labels', content: str) -> 'ParserNote': @@ -129,6 +136,14 @@ def __str__(self) -> str: return f"{self.name}, parent: None, {', '.join([child.name for child in self.childs])}" +@dataclass +class SMCompilingSettings: + import_files: Set[str] + build_files: Set[str] + platform_id: str + platform_compiler_settings: CompilingSettings + + @dataclass class StateMachine: name: str @@ -137,3 +152,5 @@ class StateMachine: notes: List[ParserNote] states: List[ParserState] signals: Set[str] + # Установлено дефолтное значение, чтобы не трогать легаси. + compiling_settings: Optional[SMCompilingSettings] = None diff --git a/compiler/handler.py b/compiler/handler.py index e91e87b..9f72f43 100644 --- a/compiler/handler.py +++ b/compiler/handler.py @@ -4,6 +4,7 @@ import time from typing import List, Optional, Set from datetime import datetime +from itertools import chain import aiohttp from aiohttp import web @@ -11,11 +12,16 @@ from aiopath import AsyncPath from pydantic import ValidationError + try: + from .CGML import parse, CGMLException from .Compiler import CompilerResult from .types.inner_types import CompilerResponse, File from .types.ide_types import CompilerSettings - from .fullgraphmlparser.stateclasses import StateMachine + from .fullgraphmlparser.stateclasses import ( + StateMachine, + SMCompilingSettings + ) from .types.ide_types import IdeStateMachine from .GraphmlParser import GraphmlParser from .CJsonParser import CJsonParser @@ -26,10 +32,14 @@ from .config import BUILD_DIRECTORY, MAX_MSG_SIZE from .Logger import Logger except ImportError: + from compiler.CGML import parse, CGMLException from compiler.Compiler import CompilerResult from compiler.types.inner_types import CompilerResponse, File from compiler.types.ide_types import CompilerSettings - from compiler.fullgraphmlparser.stateclasses import StateMachine + from compiler.fullgraphmlparser.stateclasses import ( + StateMachine, + SMCompilingSettings + ) from compiler.types.ide_types import IdeStateMachine from compiler.GraphmlParser import GraphmlParser from compiler.CJsonParser import CJsonParser @@ -41,6 +51,46 @@ from compiler.Logger import Logger +def get_default_libraries() -> Set[str]: + """ + Get set of default libraries. + + Return example: 'qhsm.c', 'qhsm.h' + """ + return set(list( + chain.from_iterable((f'{library}.c', f'{library}.h') + for library in Compiler.c_default_libraries)) + ) + + +async def compile_xml(xml: str, base_dir_path: str) -> CompilerResult: + """ + Compile CGML scheme. + + This function generate code from scheme, compile it. + """ + sm: StateMachine = parse(xml) + await AsyncPath(base_dir_path).mkdir(parents=True) + await CppFileWriter(sm, True, True).write_to_file(base_dir_path, 'ino') + settings: SMCompilingSettings | None = sm.compiling_settings + if settings is None: + raise Exception('Internal error!') + default_library = get_default_libraries() + await Compiler.include_source_files(Compiler.DEFAULT_LIBRARY_ID, + default_library, + base_dir_path) + await Compiler.include_source_files(settings.platform_id, + settings.build_files, + base_dir_path) + flags = settings.platform_compiler_settings.flags + compiler = settings.platform_compiler_settings.compiler + return await Compiler.compile_project( + base_dir_path, + flags, + compiler + ) + + class HandlerException(Exception): """Errors during processing requests.""" @@ -73,8 +123,7 @@ async def main(request: web.Request) -> web.WebSocketResponse: async for msg in ws: await Logger.logger.info(msg) if msg.type == aiohttp.WSMsgType.TEXT: - processed_msg = msg.data - match processed_msg: + match msg.data: case 'close': await ws.close() case 'arduino': @@ -87,6 +136,8 @@ async def main(request: web.Request) -> web.WebSocketResponse: await Handler.handle_berloga_import(request, ws) case 'berlogaExport': await Handler.handle_berloga_export(request, ws) + case 'cgml': + await Handler.handle_cgml_compile(request, ws) case _: await ws.send_str(f'Unknown {msg}!' 'Use close, arduino,' @@ -96,6 +147,43 @@ async def main(request: web.Request) -> web.WebSocketResponse: return ws + @staticmethod + async def handle_cgml_compile( + request: web.Request, + ws: Optional[web.WebSocketResponse] = None + ) -> web.WebSocketResponse: + """Generate code from CGML-scheme and compile it.""" + if ws is None: + ws = web.WebSocketResponse( + autoclose=False, max_msg_size=MAX_MSG_SIZE) + await ws.prepare(request) + try: + xml = await ws.receive_str() + sm: StateMachine = parse(xml) + dirname = str(datetime.now()) + '/' + dirname = dirname.replace(' ', '_') + '/sketch' + await AsyncPath(dirname).mkdir() + await CppFileWriter(sm, True, True).write_to_file(dirname, '.ino') + settings: SMCompilingSettings | None = sm.compiling_settings + if settings is None: + raise Exception('Internal error!') + await Compiler.include_source_files(settings.platform_id, + settings.import_files, + dirname) + flags = settings.platform_compiler_settings.flags + compiler = settings.platform_compiler_settings.compiler + await Compiler.compile(dirname, + settings.build_files, + flags, + compiler) + except CGMLException as e: + await Logger.logException() + await RequestError(e.args[0]).dropConnection(ws) + except Exception: + await Logger.logException() + await RequestError('Internal error!').dropConnection(ws) + return ws + @staticmethod async def handle_ws_compile( request: web.Request, diff --git a/compiler/library/ino/source/AnalogIn.h b/compiler/library/ArduinoUno/AnalogIn.h similarity index 100% rename from compiler/library/ino/source/AnalogIn.h rename to compiler/library/ArduinoUno/AnalogIn.h diff --git a/compiler/library/ino/source/AnalogIn.ino b/compiler/library/ArduinoUno/AnalogIn.ino similarity index 100% rename from compiler/library/ino/source/AnalogIn.ino rename to compiler/library/ArduinoUno/AnalogIn.ino diff --git a/compiler/library/ino/source/AnalogOut.h b/compiler/library/ArduinoUno/AnalogOut.h similarity index 100% rename from compiler/library/ino/source/AnalogOut.h rename to compiler/library/ArduinoUno/AnalogOut.h diff --git a/compiler/library/ino/source/AnalogOut.ino b/compiler/library/ArduinoUno/AnalogOut.ino similarity index 100% rename from compiler/library/ino/source/AnalogOut.ino rename to compiler/library/ArduinoUno/AnalogOut.ino diff --git a/compiler/library/ino/source/Button.h b/compiler/library/ArduinoUno/Button.h similarity index 100% rename from compiler/library/ino/source/Button.h rename to compiler/library/ArduinoUno/Button.h diff --git a/compiler/library/ino/source/Button.ino b/compiler/library/ArduinoUno/Button.ino similarity index 100% rename from compiler/library/ino/source/Button.ino rename to compiler/library/ArduinoUno/Button.ino diff --git a/compiler/library/ino/source/Counter.h b/compiler/library/ArduinoUno/Counter.h similarity index 100% rename from compiler/library/ino/source/Counter.h rename to compiler/library/ArduinoUno/Counter.h diff --git a/compiler/library/ino/source/Counter.ino b/compiler/library/ArduinoUno/Counter.ino similarity index 100% rename from compiler/library/ino/source/Counter.ino rename to compiler/library/ArduinoUno/Counter.ino diff --git a/compiler/library/ino/source/DigitalIn.h b/compiler/library/ArduinoUno/DigitalIn.h similarity index 100% rename from compiler/library/ino/source/DigitalIn.h rename to compiler/library/ArduinoUno/DigitalIn.h diff --git a/compiler/library/ino/source/DigitalIn.ino b/compiler/library/ArduinoUno/DigitalIn.ino similarity index 100% rename from compiler/library/ino/source/DigitalIn.ino rename to compiler/library/ArduinoUno/DigitalIn.ino diff --git a/compiler/library/ino/source/DigitalOut.h b/compiler/library/ArduinoUno/DigitalOut.h similarity index 100% rename from compiler/library/ino/source/DigitalOut.h rename to compiler/library/ArduinoUno/DigitalOut.h diff --git a/compiler/library/ino/source/DigitalOut.ino b/compiler/library/ArduinoUno/DigitalOut.ino similarity index 100% rename from compiler/library/ino/source/DigitalOut.ino rename to compiler/library/ArduinoUno/DigitalOut.ino diff --git a/compiler/library/ino/source/LED.h b/compiler/library/ArduinoUno/LED.h similarity index 100% rename from compiler/library/ino/source/LED.h rename to compiler/library/ArduinoUno/LED.h diff --git a/compiler/library/ino/source/LED.ino b/compiler/library/ArduinoUno/LED.ino similarity index 100% rename from compiler/library/ino/source/LED.ino rename to compiler/library/ArduinoUno/LED.ino diff --git a/compiler/library/ino/source/Math.cpp b/compiler/library/ArduinoUno/Math.cpp similarity index 100% rename from compiler/library/ino/source/Math.cpp rename to compiler/library/ArduinoUno/Math.cpp diff --git a/compiler/library/ino/source/Math.h b/compiler/library/ArduinoUno/Math.h similarity index 100% rename from compiler/library/ino/source/Math.h rename to compiler/library/ArduinoUno/Math.h diff --git a/compiler/library/ino/source/PWM.h b/compiler/library/ArduinoUno/PWM.h similarity index 100% rename from compiler/library/ino/source/PWM.h rename to compiler/library/ArduinoUno/PWM.h diff --git a/compiler/library/ino/source/PWM.ino b/compiler/library/ArduinoUno/PWM.ino similarity index 100% rename from compiler/library/ino/source/PWM.ino rename to compiler/library/ArduinoUno/PWM.ino diff --git a/compiler/library/ino/source/QHsmSerial.h b/compiler/library/ArduinoUno/QHsmSerial.h similarity index 100% rename from compiler/library/ino/source/QHsmSerial.h rename to compiler/library/ArduinoUno/QHsmSerial.h diff --git a/compiler/library/ino/source/QHsmSerial.ino b/compiler/library/ArduinoUno/QHsmSerial.ino similarity index 100% rename from compiler/library/ino/source/QHsmSerial.ino rename to compiler/library/ArduinoUno/QHsmSerial.ino diff --git a/compiler/library/ino/source/ShiftRegister.h b/compiler/library/ArduinoUno/ShiftRegister.h similarity index 100% rename from compiler/library/ino/source/ShiftRegister.h rename to compiler/library/ArduinoUno/ShiftRegister.h diff --git a/compiler/library/ino/source/ShiftRegister.ino b/compiler/library/ArduinoUno/ShiftRegister.ino similarity index 100% rename from compiler/library/ino/source/ShiftRegister.ino rename to compiler/library/ArduinoUno/ShiftRegister.ino diff --git a/compiler/library/ino/source/Timer.h b/compiler/library/ArduinoUno/Timer.h similarity index 100% rename from compiler/library/ino/source/Timer.h rename to compiler/library/ArduinoUno/Timer.h diff --git a/compiler/library/ino/source/Timer.ino b/compiler/library/ArduinoUno/Timer.ino similarity index 98% rename from compiler/library/ino/source/Timer.ino rename to compiler/library/ArduinoUno/Timer.ino index e8854e1..a8480be 100644 --- a/compiler/library/ino/source/Timer.ino +++ b/compiler/library/ArduinoUno/Timer.ino @@ -68,9 +68,9 @@ bool Timer::timeout() if (_active && (millis() - _previous >= _interval)) { _previous = millis(); - return true + return true; } - return false + return false; } /* diff --git a/compiler/library/ino/source/qhsm.c b/compiler/library/default/qhsm.c similarity index 100% rename from compiler/library/ino/source/qhsm.c rename to compiler/library/default/qhsm.c diff --git a/compiler/library/ino/source/qhsm.h b/compiler/library/default/qhsm.h similarity index 100% rename from compiler/library/ino/source/qhsm.h rename to compiler/library/default/qhsm.h diff --git a/compiler/library/ino/build/Button.o b/compiler/library/ino/build/Button.o deleted file mode 100644 index 7654919592324b32f9e497621b21a7ccf8d141ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2944 zcmbuBO>7%Q6vxL&X^UtYQ$PY0A#;I(=;BR66+Tos37gn$NUb=jP(+xn*9%$Uc%$9f z$|(dwE09ct6avF#)MaVZ{_Se}itzeb<>d%4{Cz1-Q_??m^?JJ$Zr z^1V)ecXe;KH+SuB9`ohTAAo1MbF(+Pbtfh}k0leg%bkS$fE<3=OGoHz9dx4oYg-4o z=+%$6_PbriqA@*?TH!`-;%0eAu9`&N?MM9)F@C~IcfRa)yQ_QCkq~~Xuo1Xn=r*24 zPCc2MnR%sfYPlY@L{u?QZe@$ILR~~YJRgn{}wpO zMLg8}&>OJ<{67FEc>)hLUrqdhvIJE+#Qvm${ac1JzZkqL-uQkwMrtm_5m(7@TrH&~ zJ!&vS9&bw=zY~qmOa8s&@w?D?h1!W!K5-3+c>{P`a?}M9*OdCNsA2zf`G!CizdeB8 z9l)QZ7te|_Ie=He=_Ar*b%1>|fV1QqH=K}gBaUK(nA0dUBXoi)VFimI84!8(xPlOf6vKEPr*X@u}^C=D2UavSy+^W6AtLL3w zDi>yFYt|B9nwp-scoNrbHJTOYzeOa^BE>ud*M*wj46W+yV$H8{D+XfH^FvNaxDypB z&y0!Oc_Z}s8r7%iW*NPn7&&d5+rn*AnG<a-1lfA!T2d z{CVn+r+7_r*pH_8Rmrg~?jjZEGs$6(?^5wEB!~UODgJeer{jDpIr2G?vj0wU#D65k zC5}%l)==lUASb}kl$7K^admDlXBTIVVe1gXUpu{iZ%Y3H z&80=qccVd?RzRdrV#I5(#{r>@dE1`k_ diff --git a/compiler/library/ino/build/Led.o b/compiler/library/ino/build/Led.o deleted file mode 100644 index b234c8875179ae403464e61ad6e3a93876968734..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3192 zcmb_e&2Jk;6dxz0DWYvmDH5m%xd#wbbnzx3ln+%&%_cS&CyEn5foif@Z?J{!jrOCs zh0s(Ll`IPs#DxO~{sfL3DnO(vLYzV31Q$dP2!ZIqLXph-?am~_#FmiYNwYKW_de&% z%(E|B#hIa0ib+bbvuux(C}XWdd+VuqImOa!l>IsS;9pDm_RsnDMz)(jYgcyl*EHn$_wImYzI}6d_4Tb7>D-$LzR$N4Wb2#l|IfO;vD1#aS2uQ2(KA;z zy1gD_(U_is%)allTy=8i+hwT4FE}u@X4$uz<;H>CY3}=0v@#S(@Ji~d-t2JvOu@ffe zL1>3HhXbkE_1Y!kye7As6<%?J(2ty$&(>;;&lcy-O&7@|TIB`KmrLX1IX7mJNUY7h z^^@W~S{LHD6OI=lWI3z{g>q<`PSy5#=-ah0C^(k2K-l=I9Z)JBg>~&l!CB;1`3XM% zg0mZXZf2%zE%L?bb480Me%)rJUU2@MN3zV4&qioDkKpZ7{$_}+F&{GP2 zmx50V953v!g5zC)PSH3@L;5KLB!d1Z4T(1Z63Mu6Cnf&P7)@|B?qz}NajywnkNbh5 zug1Nu_(#u_`P@+S?^f_{75!rh{+)uWetr}<^0`OR|3%=)A3a*e6>!`+Pz%{tGC}|h zL(-I3NL==h6%Ci~cvHh=Kl?<(Wn5+i7aO6yN^|HZb5*W&?hm_q}!34@oyRcB_2Nw;QfV z?LSQ!vZj{94r*Se1U~|yLTZfxqkrS9rf8`2lenmx!u|*evBYmE2)`SkhiL%E-B4*( ziz{V1{1^$~bCA8Ruk$9^0@L>;W4Fub`pP{Foep|P-#WPH&l?;GJiRv@5r^P`hGvKkFG-)Qq}8+|5Bh#{N4M={3Y@h zEugB~e=6)hlZs;2?Jp4CuYN62zm~8={m>_+y{uoq*f6Pzgt{URoH1;5d;DM0&z>N* cf~1Hxg?+;9uQl#hKl|TB{_jddF>CJF-|2VW^8f$< diff --git a/compiler/library/ino/build/qhsm.o b/compiler/library/ino/build/qhsm.o deleted file mode 100644 index e59e3a5f875745ff37ad8470d5489790b665118f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3360 zcmbtWU1%It6uz@b+w><*EUgOhXML!o*pAt>iZT8y#<5q3B?-+-QMQ}it-Ch+!EbDP}CUwgj; z#%Dfm!iyUf0Nna8-e@$UywrKLU+BhWV2zh96Us}lU!Drh%8a7t)Z=;e_3iLv7;SB)icfU05R@aTg9Ut_gC!6`~M=LSVYhu{RqqOqhQc8ObOKUoz?hQ(>} z`yAA;>)m{Lmnb!46!LFfU4*>DDgUw2+j?0w%9Or-7b=!{>2d61sI`YOPG#47u+cJY zw9JQ%rTHtoIA=F{E}72BZ6^xX3=f+ZYZ`(o_2bYgF4GPBQcPAfWUR2+FIDG6>vy;a zq~DD4dz`5>ch%?=pSPx04mEk9)z`$mDv>S~vb<5-HS@&{%&YS{IFax~FnL?w)2x0g z^XOO(hFWg^Sis`oiI-p*K@+hXQVSUVQF zNM5+PeiXbjf2RmS%?Z@3A97NlS*U_>t!sA4*xJ4mE5Gh}hfBt~WnAaWlh>VCI-lqw zc1oQ+EZ+BKXX(V^`{DzqPX#+YGV-9me{w3HGV}gGKtHJuoCxHF8kip()CW%Kfn(AD z_f93WPh5Bp!;c2_GBymWx_#E(xU9Xpm3o0Hwg#5N=wte*tCB@ zIB1-frky(l2x~+1t?p#MHQJca6S8in4$-~8Ns%i&gxI2#@K17s9mJ)hUtSwy4-FXkL=B(hs)tps4xSF#y z53c5n>ABgY8J+?+vks3dDI1#(>t<}mWO_7ghM7K<%P~Ehc9cjunZy(_J(V_NI=)#a z#HdOA*;HQ7WYd{g)|^EQWs1c^7qa1GOz!0WF+alTYUwWA6qL%nvj55^$3Us94-&Zq zn}{Qvr^^C8AOrS8CXv1)M7KJO-3?B-91DpumiE+D25oSDQjs#Q!K`e%Yu4z-UIj@s!hh_kh@E ca-d%$#YL*`3c3kGyZC-e3^EpF diff --git a/compiler/platforms/Arduino.json b/compiler/platforms/Arduino.json index e77a308..6dbe87a 100644 --- a/compiler/platforms/Arduino.json +++ b/compiler/platforms/Arduino.json @@ -10,7 +10,7 @@ "compile": true, "compilingSettings": { "compiler": "arduino-cli", - "flags": ["-b", "avr:arduino:uno"] + "flags": ["compile", "--export-binaries", "-b", "arduino:avr:uno"] }, "delimeter": ";", "components": { diff --git a/compiler/routes.py b/compiler/routes.py index a2e23a8..f46a495 100644 --- a/compiler/routes.py +++ b/compiler/routes.py @@ -16,3 +16,4 @@ def setup_routes(app: web.Application) -> None: [web.get('/ws/berloga/import', Handler.handle_berloga_import)]) app.add_routes( [web.get('/ws/berloga/export', Handler.handle_berloga_export)]) + app.add_routes([web.get('/cgml', Handler.handle_cgml_compile)]) diff --git a/test/test_cgml.py b/test/test_cgml.py index 0257958..f8f130c 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -6,6 +6,7 @@ from contextlib import contextmanager import pytest +from compiler.handler import compile_xml from cyberiadaml_py.cyberiadaml_parser import CGMLParser from compiler.fullgraphmlparser.graphml_to_cpp import CppFileWriter from compiler.types.inner_types import InnerEvent, InnerTrigger @@ -17,8 +18,8 @@ @pytest.fixture -def init_platform(): - return PlatformManager.load_platform('compiler/platforms/Arduino.json') +async def init_platform(): + await PlatformManager.load_platform('compiler/platforms/Arduino.json') @contextmanager @@ -102,7 +103,6 @@ def test_parse_actions(raw_trigger: str, expected: str): @pytest.mark.asyncio async def test_generating_code(init_platform): - await init_platform with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: data = f.read() path = './test/test_folder/' @@ -113,3 +113,11 @@ async def test_generating_code(init_platform): print('Code generated!') except Exception as e: print(e) + + +@pytest.mark.asyncio +async def test_cgml_route(init_platform): + await init_platform + with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: + data = f.read() + await compile_xml(data) From 26d70d80646f72f0c9e10e1a44c4ef79c6d41734 Mon Sep 17 00:00:00 2001 From: L140-beep Date: Thu, 4 Apr 2024 10:55:09 +0700 Subject: [PATCH 14/14] cgml handler --- compiler/Compiler.py | 1 + compiler/handler.py | 69 ++++++++++++++++++++++++++++++++------------ test/test_cgml.py | 12 +++++--- 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/compiler/Compiler.py b/compiler/Compiler.py index bfdd56a..a369cac 100644 --- a/compiler/Compiler.py +++ b/compiler/Compiler.py @@ -39,6 +39,7 @@ class SupportedCompiler(TypedDict): class Compiler: """Class for compiling, copying libraries sources.""" + DEFAULT_LIBRARY_ID = 'default' c_default_libraries = set(['qhsm']) # legacy supported_compilers: Dict[str, SupportedCompiler] = { diff --git a/compiler/handler.py b/compiler/handler.py index 9f72f43..7eef022 100644 --- a/compiler/handler.py +++ b/compiler/handler.py @@ -51,6 +51,48 @@ from compiler.Logger import Logger +async def create_response( + base_dir: str, + compiler_result: CompilerResult) -> CompilerResponse: + """ + Get source files, binary files from\ + directory and create CompilerResponse. + + Doesn't send anything. + """ + response = CompilerResponse( + result='NOTOK' if compiler_result.return_code != 0 else 'OK', + return_code=compiler_result.return_code, + stdout=compiler_result.stdout, + stderr=compiler_result.stderr, + binary=[], + source=[] + ) + build_path = base_dir + 'build/' + async for path in AsyncPath(build_path).rglob('*'): + if await path.is_file(): + async with async_open(path, 'rb') as f: + binary = await f.read() + b64_data: bytes = base64.b64encode(binary) + response.binary.append(File( + filename=path.name.split('.')[0], + extension=''.join(path.suffixes), + fileContent=b64_data.decode('ascii'), + )) + + response.source.append(await Handler.readSourceFile( + 'sketch', + 'ino', + base_dir) + ) + response.source.append(await Handler.readSourceFile( + 'sketch', + 'h', + base_dir) + ) + return response + + def get_default_libraries() -> Set[str]: """ Get set of default libraries. @@ -68,9 +110,10 @@ async def compile_xml(xml: str, base_dir_path: str) -> CompilerResult: Compile CGML scheme. This function generate code from scheme, compile it. + + Doesn't send anything. """ sm: StateMachine = parse(xml) - await AsyncPath(base_dir_path).mkdir(parents=True) await CppFileWriter(sm, True, True).write_to_file(base_dir_path, 'ino') settings: SMCompilingSettings | None = sm.compiling_settings if settings is None: @@ -159,23 +202,13 @@ async def handle_cgml_compile( await ws.prepare(request) try: xml = await ws.receive_str() - sm: StateMachine = parse(xml) - dirname = str(datetime.now()) + '/' - dirname = dirname.replace(' ', '_') + '/sketch' - await AsyncPath(dirname).mkdir() - await CppFileWriter(sm, True, True).write_to_file(dirname, '.ino') - settings: SMCompilingSettings | None = sm.compiling_settings - if settings is None: - raise Exception('Internal error!') - await Compiler.include_source_files(settings.platform_id, - settings.import_files, - dirname) - flags = settings.platform_compiler_settings.flags - compiler = settings.platform_compiler_settings.compiler - await Compiler.compile(dirname, - settings.build_files, - flags, - compiler) + base_dir = str(datetime.now()) + '/' + base_dir = base_dir.replace(' ', '_') + '/sketch' + await AsyncPath(base_dir).mkdir() + compiler_result: CompilerResult = await compile_xml(xml, base_dir) + response = await create_response(base_dir, compiler_result) + await Logger.logger.info(response) + await ws.send_json(response.model_dump()) except CGMLException as e: await Logger.logException() await RequestError(e.args[0]).dropConnection(ws) diff --git a/test/test_cgml.py b/test/test_cgml.py index f8f130c..0af1046 100644 --- a/test/test_cgml.py +++ b/test/test_cgml.py @@ -6,7 +6,7 @@ from contextlib import contextmanager import pytest -from compiler.handler import compile_xml +from compiler.handler import compile_xml, create_response from cyberiadaml_py.cyberiadaml_parser import CGMLParser from compiler.fullgraphmlparser.graphml_to_cpp import CppFileWriter from compiler.types.inner_types import InnerEvent, InnerTrigger @@ -25,7 +25,7 @@ async def init_platform(): @contextmanager def create_test_folder(path: str, wait_time: int): try: - Path(path).mkdir() + Path(path).mkdir(parents=True) yield finally: time.sleep(wait_time) @@ -103,6 +103,7 @@ def test_parse_actions(raw_trigger: str, expected: str): @pytest.mark.asyncio async def test_generating_code(init_platform): + await init_platform with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: data = f.read() path = './test/test_folder/' @@ -119,5 +120,8 @@ async def test_generating_code(init_platform): async def test_cgml_route(init_platform): await init_platform with open('examples/CyberiadaFormat-Blinker.graphml', 'r') as f: - data = f.read() - await compile_xml(data) + path = './test/test_project/sketch' + with create_test_folder(path, 10): + data = f.read() + result = await compile_xml(data, path) + await create_response(path, result)