Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[1]

сохраняется естественный порядок расположения линейных фрагментов в теле исходной программы. Будем называть такую конструкцию диспетчером переходов. Каждый диспетчер локален в соответствующем блоке.

Конкретный вид проекции диспетчера переходов и самих переходов в целевой язык определяется его операторами выбора по метке и цикла. В разных целевых языках эти средства существенно варьируются.

Проекции в язык Java

В языке Java, следующем традициям языка Си, но не содержащем операторов локальных переходов, диспетчер имеет следующий вид:

for ( int GotoAddr = 1; GotoAddr != 0; ) {

const int Tmp = GotoAddr; GotoAddr = 0; Dispatch:

switch( Tmp )

case 1: Фрагмент1; case N: ФрагментШ;

При этом оператор GOTO <Метка> переходит в

GotoAddr = <Номер метки>; break Dispatch;

Здесь существенно используется возможность указать при операторе BREAK конструкцию, которая должна быть завершена. Операторы GOTO могут быть вложены в сохранившиеся структурные операторы (в том числе цикла и выбора по метке).

Возможная альтернатива

Существует другой подход к устранению локальных GOTO. Его можно описать на примере обработки одного оператора перехода.

В процессе работы алгоритма сначала происходит пошаговое движение оператора GOTO (goto-movement). Назовем содержащим блоком тот блок, одним из операторов которого, на данном шаге, является рассматриваемый оператор перехода. На каждом шаге оператор GOTO либо выносится из содержащего блока в его объемлющий блок, либо вносится в один из блоков, текстуально вложенных в содержащий блок, либо переносится на другое место в своем блоке. По окончании этих передвижений оператор перехода оказывается непосредственно перед его целевой меткой, после чего он может быть просто удален.

В результате подобных перемещений сохраняются все существующие программные конструкции, но при каждом перемещении они объединяются в попутно создаваемые новые структуры. Также иногда добавляются служебные переменные, выступающие в роли управляющих флагов.

Можно рассмотреть следующий простейший случай работы предложенного алгоритма (рис. 2).

stmt 1;stmt 1;

if ( cond ) goto L 1;if ( ! cond ) {

stmt 2;stmt 2;

L 1: stmt n;}

L 1: stmt n; Рис. 2. Простейший случай работы предложенного алгоритма.

К сожалению, не все случаи применения данного алгоритма ведут к столь же красивым результатам. Подробнее о таких преобразованиях и их оптимизациях можно прочесть в статье [4].


В каком-то смысле этот подход противоположен предыдущему. Действительно, предыдущий подход направлен на разрушение существующих структур операторов, а этот стремится объединить исходные операторы в более сложные структуры.

Более того, если мы возьмем в качестве исходной программу, не содержащую операторов GOTO, произведем в ней редукцию (сведение к низкоуровневым операторам переходов) нескольких произвольно выбранных структурных конструкций и к полученной программе применим данный алгоритм, то он попытается привести ее к исходному виду.

Благодаря этому в будущем может оказаться интересным сравнить результаты применения рассмотренных подходов. Также можно попытаться комбинировать эти подходы для улучшения внешнего вида и повышения читаемости получаемых результатов.

Заключение

В данной работе рассмотрен способ моделирования операторов перехода средствами структурных конструкций. Предложенный алгоритм осуществляет частичную реструктуризацию исходной программы с последующим моделированием операторов переходов с помощью диспетчеров. Дополнительным условием при трансляции ставится требование сходства исходной и получаемой программ.

В качестве примера показан способ трансляции из Си в Java. Тем не менее предложенный алгоритм с незначительными изменениями применим также для большинства современных языков программирования. Если из алгоритма исключить моделирование низкоуровневых пе-




[стр.Начало] [стр.1] [стр.2]