MEGATRON



LOG | FILES | OVERVIEW


F diff --git a/doc/bulgarian/.project.mg.swp b/doc/bulgarian/.project.mg.swp new file mode 100644
B Binary files /dev/null and b/doc/bulgarian/.project.mg.swp differ
F diff --git a/doc/bulgarian/makefile b/doc/bulgarian/makefile new file mode 100644 --- /dev/null +++ b/doc/bulgarian/makefile
+ install:
+ cat project.mg | preconv | groff -mg -Tps > a.ps
+ ps2pdf a.ps a.pdf
F diff --git a/doc/bulgarian/project.mg b/doc/bulgarian/project.mg new file mode 100644 --- /dev/null +++ b/doc/bulgarian/project.mg
+ .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
F diff --git a/doc/en.txt b/doc/en.txt new file mode 100644 --- /dev/null +++ b/doc/en.txt
+ MEGATRON transpiler for a language describing automatas
+
+ Here is a description of the language
+
+
+
+ Things encased with "" are to be taken literally, things encased in [] are optional,
+ things encased with () are grouped and are to be taken as a unit,
+ things encased in {} can appear zero or more times and things encased in {}+ can appear one
+ or more times
+
+ Syntax:
+ <program> := { <machine definition> }+
+
+ <machine definition> := <id> "[" <machine internals> "]" ";"
+
+ <machine internals> := { <states definition> ";" | <events definition> ";" | <transitions definition> ";" \
+ | "starting" "on" <id> ";" }
+
+ <states definition> := "states" "[" { <id> [ "on" "entering" <execute statement> ] \
+ [ "on" "exiting" <execute statement> ] }+ "]"
+
+ <events definition> := "events" "[" { <id> }+ "]"
+ <transitions definition> := "transitions" "[" { <transition> ";" }+ "]"
+ <transition> := "from" <id> "to" <id> "on" "event" <id> [ <granted statement> ] [ <if statement> ] ";"
+
+ <if statement> := <execute statement>
+ <if statement> := "if" "(" <expression> ")" <if statement> [ "else" <if statement> ]
+
+ <granted statement> := "granted" "(" <expression> ")"
+
+ <execute statement> := "execute" <pipeline>
+ <pipeline> := <id> [ <string> ] [ "|" <pipeline> ]
+
+ <primary expression> := <id> "." <id> | "(" <expression> ")"
+ <not expression> := "!" <not expression> | <primary expression>
+ <and expression> := <not expression> "&&" <and expression>
+ <or expression> := <and expression> "||" <or expression>
+ <expression> := <or expression>
+
+ Constraints:
+ The name of each machine id shall be unique in a program.
+
+ The order of the machine declarations do not matter to the constraint checks.
+
+ In the internals of each machine there will be exactly one states definition, events definition, transitions
+ definition and starting state declaration.
+
+ State ids shall not have duplicates in the same machine they are defined, meaning you could have a state
+ id appear in two machines.
+
+ Event ids shall not have duplicates across all machines, meaning you can not have an event id appear in
+ two machines at the same time in the same program. The same goes with machine ids.
+
+ Event ids, machine ids and pipeline ids share a namespace, meaning you can not have an id that is both
+ a machine id and an event id at the same time or a pipeline id that is a machine id.
+
+ Let a primary expression be in the form <id> "." <id>. The first id shall be a machine id and the second
+ a state id that belongs to the denoted machine.
+
+ Transition ids shall be state id belonging to the machine the transitions declaration apears in.
+
+ The first id in a transition shall not appear as the first id in another transition in the same
+ transition definition. Meaning you can not have multiple transitions stemming from the same state.
+
+ Semantics:
+ A program describes a set of possibly interdependant automata that execute external code upon certain conditions.
+
+ A machine is always in a single state, starting on the starting state.
+
+ The outside environment can pass events to any machine. The machine switches states and executes
+ external functions. The events are processed in the order they arrive.
+
+ If no transition can take an event, the event is dropped.
+ A transition of states occurs if there is no granted part to the transition.
+ If there is a granted part of the transition then the expression in the granted part must evaluate to 1
+ otherwise the transition does not occur and the event is dropped.
+
+ If a transition occurs then and only then is the conditional execution of external functions executed.
+ Meaning that the if does not go off if the granted statement fails.
+
+ A primary expression in the form <id> "." <id> evaluates to 1 if the machine with the first id
+ is currently in the state with the second id, otherwise it evaluates to 0. For example M.a is 1
+ if the machine 'M' is in the state 'a'.
F diff --git a/doc/makefile b/doc/makefile deleted file mode 100644 --- a/doc/makefile +++ /dev/null
- install:
- cat project.mg | preconv | groff -mg -Tps > a.ps
- ps2pdf a.ps a.pdf
F diff --git a/doc/project.mg b/doc/project.mg deleted file mode 100644 --- a/doc/project.mg +++ /dev/null
- .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