Разработка компиляторов

       

Генерация кода: заключение


Наконец, мы генерируем блок catch и завершаем генерацию нашей программы:

il.BeginCatchBlock (typeof (System.Exception)); il.EmitWriteLine ("Finished"); il.EndExceptionBlock (); il.Emit (OpCodes.Ret); classb.CreateType (); ab.SetEntryPoint (mb); ab.Save ("numbers.exe");

Теперь мы перейдем к генерации catch-блока. Стоит отметить следующую деталь: если бы try не заканчивался переходом к следующей итерации, то метод BeginCatchBlock автоматически сгенерировал бы команду для завершения блока.

il.BeginCatchBlock (typeof (System.Exception));

Метод EmitWriteLine используется для генерации вызова System.Console.WriteLine от строковой константы. Тот же эффект можно достичь и более прямым путем (так же, как мы выше выводили значение переменной var_i). Результат будет идентичен, но использованный нами только что способ более краток и удобен, например, для вставки в код вывода отладочной информации.

il.EmitWriteLine ("Finished");

Метод EndExceptionBlock завершает генерацию try-catch блока. Он одновременно выполняет определение метки EndTry, которую создал BeginExceptionBlock. После окончания этого блока необходимо вставить генерацию оператора return.

il.EndExceptionBlock (); il.Emit (OpCodes.Ret);

Теперь нам осталось выполнить только несколько завершающих действий: операция CreateType завершает создание типа. После этого мы уже не можем внести никаких изменений и дополнений в класс LowLevelSample.

classb.CreateType();

Метод SetEntryPoint позволяет установить точку входа для сборки (на уровне генерации MSIL нет никаких неявных соглашений на эту тему, как, скажем, в C#, где точкой входа является метод Main):

ab.SetEntryPoint (mb); ab.Save ("numbers.exe");

И вот выполнено последнее действие: после операции Save сборка записана в исполняемый файл на диске. Процесс генерации кода завершен.



Содержание раздела