Пока размышлял над Драконизацией программирования, пришла мысль, что, возможно, удобной штукой будет добавить coroutines в ST.
Гипотеза в том, что последовательный код писать проще чем "автоматный".
Да, есть CASE, но расщеплять состояния приходится вручную.
Что можно было бы сделать: добавить оператор "пауза" в ST. Тогда код с паузами при компиляции автоматически бы превращался в CASE автомат.
Пример:
Код:
PROGRAM запуск_насоса
VAR
номер_насоса: INT;
WHILE TRUE
номер_насоса := найти_рабочий_насос();
IF номер_насоса=-1 THEN
авария_всех_насосов();
ПАУЗА t#1s;
CONTINUE;
END_IF;
увеличить_количество_запусков(номер_насоса);
запустить_насос(номер_насоса);
ПАУЗА t#10s;
WHILE давление_есть
ПАУЗА;
END_WHILE;
(* Давление пропало, значит насос сломался *)
остановить_насос(номер_насоса);
установить_признак_аварии(номер_насоса);
END_WHILE;
END_PROGRAM
Эта программа выглядит как бесконечный цикл (WHILE TRUE снаружи), но после компиляции она будет возвращать управление в момент "пауз". При повторном вызове она будет продолжать с места прошлой паузы.
Иными словами, скомпилированный код может выглядеть вот так:
Код:
PROGRAM запуск_насоса
VAR
номер_насоса: INT;
состояние : INT;
ton1: TON;
ton2: TON;
WHILE TRUE
CASE состояние OF
0:
номер_насоса := найти_рабочий_насос();
IF номер_насоса=-1 THEN
авария_всех_насосов();
состояние := 1; (* ПАУЗА 1s *)
ton1(IN := FALSE, PT := t#1s);
RETURN; (* возвращаем управление *)
END_IF;
состояние := 2;
1:
ton1(IN := TRUE); (* ПАУЗА 1s *)
IF ton1.Q THEN
состояние := 0; (* continue *)
ELSE
RETURN; (* возвращаем управление *)
END_IF;
2:
увеличить_количество_запусков(номер_насоса);
запустить_насос(номер_насоса);
ton2(IN := FALSE, PT := t#10s);
состояние := 3;
RETURN;
3:
ton2(IN := TRUE); (* ПАУЗА 10s; *)
IF ton2.Q THEN
состояние := 4;
ELSE
RETURN;
END_IF;
4:
IF давление_есть THEN
RETURN;
ELSE
(* Давление пропало, значит насос сломался *)
состояние := 5;
END_IF;
5:
остановить_насос(номер_насоса);
установить_признак_аварии(номер_насоса);
состояние := 0;
END_WHILE;
END_PROGRAM
С одной стороны, конечно, невелика наука расставить CASE.
Но, с другой стороны, на паузах код гораздо внятнее. Особенно, когда паузы внутри. Была одна строка "ПАУЗА t#1s;", а превратилась в 9 строк кода (запуск таймера, заход, выход)
Да и сам подход с async/await довольно широко сейчас используется в JavaScript, C#, Kotlin.
Что думаете?