diff options
Diffstat (limited to 'doc/project.mg')
-rw-r--r-- | doc/project.mg | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/doc/project.mg b/doc/project.mg deleted file mode 100644 index 013fb5c..0000000 --- a/doc/project.mg +++ /dev/null @@ -1,321 +0,0 @@ -.ps +1 -.vs +1 -.start -.ds C \f[B]C\f[] -.title "Проект по компютърни системи за управление на роботи" -.title "Език за улесняване на програмиране на вградени устройства" -.author "Галин Симеонов Ф.Н. 81635" "gtsimeonov@uni-sofia.bg" -.heading "Увод" -.paragraph -При програмирането на вградени устройства, -някои от проблемите се моделират чрез автомати. -Също е практика да се програмира на езици от ниско ниво, като \*[C], -при които ръчното имплементиране на автомати с каквито и да е размери -често е неинтуитивно, предразполагащо към грешки и трудоемко. -С цел да помогна разработването на програми, чийто модел е ориентиран околу -състоянията на системата, предлагам и имплементирам експериментален миниатюрен език транспилиращ до \*[C]. -.paragraph -За цели имам той да е прост, интуитивен и евентуално лесен за генериране от инстурменти с графичен интернфейс -.footnote -Макар, че директното генериране на код без този език да действа като посредник би било по-смислено. -.footnote end -\&. -.heading "Описание на езика" -.heading "Общ поглед" 2 -Една 'програма' съдържа един или повече 'машини', които действат като контейнери за състояния,събития и преходи. -Всяка машина си има име и има отделно пространство за имена на състояния и събития. -Чрез преходите може да се извикват външни функции. -Ето най-простият пример за това как изглежда кодът: - -.code -machine light_bulb -[ - states [ ON , OFF ]; - events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; - starting on OFF; - transitions - [ - from ON to OFF on event TURN_OFF; - from ON to OFF on event SWITCH_STATE; - - from OFF to ON on event TURN_ON; - from OFF to ON on event TURN_ON; - ]; - -]; -.code end - -След транспилация се генерират 3 файла - xxx.h xxx.c и xxx_external.h, който съответно съдържат -декларациите на служебните функции, тяхната имплементация и декларациите на външните функции, които са използвани от някой преход. -Подаването на събития към тези 'автомати' става посредством служебната функция - \f[B]push_event_to_machine\f[] - -Горният пример не е много функционален, защото комуникацията е само в една посока. -За да може да връща информация и да има функционалност, на всеки преход може да се сложат функции, които да бъдат изпълнени преди преходът да е завършил -.footnote -Това свойство е важно и авторът се е стремил да го запази. Това позволява, например, да се подават събития от функции изпълнени по време на преход -.footnote end -\&. -Taка горният пример може да бъде преработен да вика функция, която действително да включва и изключва някаква лампа: - -.code -machine light_bulb -[ - states [ ON , OFF ]; - events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; - starting on OFF; - transitions - [ - from ON to OFF on event TURN_OFF - execute light "off"; - from ON to OFF on event SWITCH_STATE - execute light "off"; - - from OFF to ON on event TURN_ON - execute light "on"; - from OFF to ON on event TURN_ON - execute light "on"; - ]; - -]; -.code end - -Тук също е демонстрирано как се подават аргументи към тези функции. -Символните низове са избрани като единствен начин да се подават аргументи, защото е предвидено да се транспилира до езици, различни от \*[C], -а въвеждането на типова система или нещо, което да описва различните аргументи би натоварило езикът твърде много и би донесло само минимална печалба. -.paragraph -Възможно е да има повече от една 'машина' в кодът. Например, нека към горния пример добавим: - -.code -machine light_controler -[ - states [ STATIC , BLINKING ]; - events [ SIGNAL , GO_STATIC, START_BLINKING ]; - starting on STATIC; - transitions - [ - from STATIC to BLINKING on event START_BLINKING; - from BLINKING to STATIC on event GO_STATIC; - - from BLINKING to BLINKING on event SIGNAL - execute prod_light_bulb; - - ]; - -]; - -machine timer -[ - states [ ON , OFF ]; - events [ TICK , START , STOP ]; - starting on OFF; - transitions - [ - from ON to OFF on event STOP; - from OFF to ON on event START - execute prod_timer; - from ON to ON on event TICK - execute prod_timer | prod_light_controler; - ]; - -]; -.code end - -Тук може да се види и 'навързване' на различни функции. -timer 'машината' праща сигнал до себе си и до light_controler, а light_controler праща сигнал до light_bulb. -Тук можем да прескочим предаването на събития между 'машините' чрез използването на \f[B]if\f[]. -Променяме третия преход от timer: - -.code - from ON to ON on event TICK - if(light_controler.BLINKING) - execute prod_timer | prod_light_bulb; - -.code end - -Това е условно изпълнение на командите, преходът се случва и състоянието е променено независимо от истинността на условието. -За реализацията на условен преход, в езикът има \f[B]granted\f[] ключовата дума. -Горното може да се опитаме да имплементираме по следния начин: - -.code - from ON to ON on event TICK granted (light_controler.BLINKING) - execute prod_timer | prod_light_bulb; -.code end - -Тук има проблема, че timer спира да работи ако light_controler не е в състояние BLINKING, -защото преходът няма да се случи и \f[B]execute prod_timer\f[] няма да се изпълни. -.footnote -Това, че този пример може да бъде имплементиран на \*[C] под 10 реда, е забелязано от автора. -.footnote end -.paragraph -\f[B]prod_timer\f[],\f[B]prod_light_bulb\f[],\f[B]prod_timer\f[] и \f[B]light\f[] са функции, чиято имплементация трябва да бъде предоставена от програмиста. -Всички външни функции се събират и се записват в генерирания xxxx_exter.h файл. Този пример би генерирал: - -.code -#ifndef XXXX_EXTERN_H -#define XXXX_EXTERN_H XXXX_EXTERN_H - -extern machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input); - -#endif - -.code end - -Ето и една примерна тяхна импелементация заедно с \f[B]main\f[] функцията: - -.code -machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input) -{ - printf("light %s\n",arguments->buffer); - return NULL; -} -machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(light_bulb,light_bulb_EVENT_SWITCH_STATE,NULL); - return NULL; -} -machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(light_controler,light_controler_EVENT_SIGNAL,NULL); - return NULL; -} -machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(timer,timer_EVENT_TICK,NULL); - sleep(1); - return NULL; -} -int main() -{ - push_event_to_machine(light_controler,light_controler_EVENT_START_BLINKING,NULL); - push_event_to_machine(timer,timer_EVENT_START,NULL); - return 0; -} - -.code end -Това ни дава изхода: -.code -light on -light off -light on -light off -light on -light off -light on -light off -light on -\&... -\&... -.code end - -.heading "Формално описание на езика" 2 -Със затъмнените думи и символи обозначавам думи и символи, които трябва да се интерпретират директно. -.heading "Програма" 3 -.right -.nf -програма : машина [ програма ] -.fi -.right end -Програмата е поредица от машини. Всяка машина има уникално име. -.heading "Машина" 3 -.right -.nf -машина : \f[BI]machine\f[] име \f[BI][\f[] вътрешна част на машината \f[BI] ] ; \f[] -вътрешна част на машината : \f[BI]states [\f[] поредица от състояния \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]events [\f[] поредица от събития \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]transitions [\f[] поредица от преходи \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]starting on \f[] име на състояние \f[BI];\f[] [ вътрешна част на машината ] -.fi -.right end - -В една машина може да се срещне само веднъж декларация на състоянията, събитията, преходите и посочване на стартиращо състояние. -Декларацията на стартиращо състояние трябва да е след декларацията на състоянията. То трябва да е сред декларираните състояния. -Декларацията на преходите трябва да е след декларациите на състоянията и на събитията. -Сред декларираните състояния и събития не трябва да има повтарящи се. -Сред преходите не трябва да има две различни, които излизат от едно състояние и имат за етикет едно събитие. -.heading "Преход" 3 -.right -.nf -преход : \f[BI] from \f[] име-на-състояние - \f[BI] to \f[] име-на-състояние \f[BI] on \f[] име-на-събитие [ опашка-на-прехода ] \f[BI];\f[] -опашка-на-прехода : [ \f[BI] granted \f[] израз ] [ условно-изпълнение ] -условно-изпълнение : \f[BI] if \f[] израз условно-изпълнение [ \f[BI] else \f[] условно-изпълнение ] -условно-изпълнение : \f[BI] execute \f[] опашка на изпълнението -опашка-на-изпълнението : име-на-външна-функция \f[BI]"\f[]символен-низ\f[BI]"\f[] [ \f[BI] | \f[] опашка-на-изпълнението ] -.fi -.right end - -Ако изразът след \f[BI]granted\f[] е истина то преходът се реализира и командите в условното изпълнение се изпълняват спрямо семантиката, -иначе преходът не се изпълнява и опашката на преходът не се изпълнява. -Ако изразът след \f[BI]if\f[] е истина то условното изпълнение след изразът се изпълнява, иначе, ако има \f[BI]else\f[] -съответстващ на \f[BI]if\f[]-а то условното узпълнение след \f[BI]else\f[] се изпълнява. -Ако условното изпълнение е от типа започващ с \f[BI]execute\f[] то външните функции се изпълняват в ред на срещане -като изходът на всяка се подава на следващата. Изходът на последната изпълнена функция се изхвърля. -.heading "Израз" 3 -.right -.nf -израз : израз-или -израз-или : израз-и [ \f[BI]|| \f[] израз-или ] -израз-и : израз-не [ \f[BI]&& \f[] израз-и ] -израз-не : [\f[BI]!\f[]]базов-израз -базов-израз : име-на-машина\f[BI].\f[]име-на-състояние | \f[BI](\f[]израз\f[BI])\f[] -.fi -.right end - -Израз може да се оцени до истина или лъжа. -Логическите оператори имат обичайната семантика. -В базовия израз е позволено да се посочват състояния на други машини, но не е позволено да се посочват състояния на машината, -в която се намира изразът. Тези посочвания се оценяват до истина ако посочената машина е заела посоченото състояние. -Могат да се посочват имена на машини, които са декларирани след сегашната, но те трябва да съществуват. Това важи и за състоянията, те трябва също и да принадлежат на посочената машина. - -.heading "Детайли на имплементацията" -За да се реализира обмена на информация между генерирания код и написания, -е дефинирана структура \f[B]machine_buffer_t\f[], в която се записват данните и техният размер. -Генерират се и няколко помощни функции, които улесняват работата с такива структури. -За да се запази свойството - командите на преходът да се изпълнят преди състоянието да се смени, -се използва опашка, в която се записват -.heading "Описание на командните аргументи" -Имплементацията на този език предадена от автора приема следните аргументи. - -.code ---print-tokens -.code end -Извежда разпознатите лексеми -.code ---print-ast -.code end -Извежда разпознатите структури в текста. ( Абстрактното синтактично дърво ) -.code --o име-на-файл | --output име-на-файл -.code end -Посочва префиксът на генерираните файлове. Например \f[B]xxxx.h xxxx.c xxxx_external.h\f[]. -.code ---extern-mutex -.code end -Добавя мутекс преди и след подаването на събитие. Този мутекс трябва да се имплементира външно. -.code ---extern-queue -.code end -Дава възможност на програмиста да даде собствена имплементация на опашката използвана при задържането на събития. -.code ---extern-buffer -.code end -Дава възможност на програмиста да даде собствена имплементация на структурата използвана за пренос на данни. - -.heading "Забележки" -За имплементацията е използвана само стандартната \*[C] библиотека, което би помогнало този транспилатор да бъде -компилиран до много операционни системи. -.heading "Бъдещи насоки" -.list -.item -Да се добави ключова дума \f[B]signal\f[] която да праща сигнал до определена машина, за да не трябва да го имплементира програмистът. -.item -Да се добави семанитка за състояния и събития, като например - 'при пристигане до това състояние изпълни ... '. -.item -Да се направи така, че отделните машини да могат да бъдат на различни физически устройства, т.е. да бъде направен разпределен. -.item -Да се направи на пълен език за програмиране. -.list end -.finish |