Общий алгоритм генерации конечного автомата для yield: различия между версиями
Mikst (обсуждение | вклад) (Новая страница: «Конечный автомат генерируется по коду тела функции, содержащей yield, после Lowering. Вначале …») |
Mikst (обсуждение | вклад) Нет описания правки |
||
Строка 9: | Строка 9: | ||
Кроме того, тесты показали, что код с вложенными if в PascalABC.NET работает быстрее кода с case. | Кроме того, тесты показали, что код с вложенными if в PascalABC.NET работает быстрее кода с case. | ||
===Общий алгоритм=== | |||
1. Количество yield равно количеству состояний плюс нулевое состояние | |||
2. Сформировать в начале секцию переходов с помощью if | |||
3. После секции переходов помечать меткой текущего состояния и от текущего места до yield переносить код. Код yield expr заменить на | |||
<source lang="Delphi"> | |||
current := <yielded-value> | |||
state := <next-state> | |||
Result := true | |||
exit | |||
</source> | |||
4. В заключительном состоянии в конце Result := False. Или сделать это в начале алгоритма |
Версия от 11:07, 6 июля 2016
Конечный автомат генерируется по коду тела функции, содержащей yield, после Lowering.
Вначале был реализован алгоритм как в C# - с помощью case (switch) по состояниям. Этот алгоритм включал в себя некоторую сложность: при наличии меток после lowering часть кода после метки приходилось выносить за case и организовывалась сложная логика переходов.
Последней каплей стал автовывод типов с узлами auto_type - присваивания для автовывода должны быть записаны в естественном порядке.
Поэтому было решено заменить case на блок вложенных if в начале с переходами по меткам. Этот способ по генерации кода оказывается проще и равномернее: если внутри кода встречается своя метка, то это никак не надло специально обрабатывать.
Кроме того, тесты показали, что код с вложенными if в PascalABC.NET работает быстрее кода с case.
Общий алгоритм
1. Количество yield равно количеству состояний плюс нулевое состояние 2. Сформировать в начале секцию переходов с помощью if 3. После секции переходов помечать меткой текущего состояния и от текущего места до yield переносить код. Код yield expr заменить на
current := <yielded-value>
state := <next-state>
Result := true
exit
4. В заключительном состоянии в конце Result := False. Или сделать это в начале алгоритма