Давайте создадим компилятор! :: Креншоу Джек
Страница:
314 из 382
Это функция, возвращающая конечный тип, позволяющий нам знать, что она решила:
{–}
{ Promote the Size of a Register Value }
function Promote(T1, T2: char; Reg: string): char;
var Typ: char;
begin
Typ := T1;
if T1 <> T2 then
if (T1 = 'B') or ((T1 = 'W') and (T2 = 'L')) then begin
Convert(T1, T2, Reg);
Typ := T2;
end;
Promote := Typ;
end;
{–}
Наконец, следующая функция приводит два регистра к одному типу:
{–}
{ Force both Arguments to Same Type }
function SameType(T1, T2: char): char;
begin
T1 := Promote(T1, T2, 'D7');
SameType := Promote(T2, T1, 'D0');
end;
{–}
Эти новые подпрограммы дают нам заряд, необходимы нам чтобы разложить PopAdd и PopSub:
{–}
{ Generate Code to Add Primary to the Stack }
function PopAdd(T1, T2: char): char;
begin
Pop(T1);
T2 := SameType(T1, T2);
GenAdd(T2);
PopAdd := T2;
end;
{–}
{ Generate Code to Subtract Primary from the Stack }
function PopSub(T1, T2: char): char;
begin
Pop(T1);
T2 := SameType(T1, T2);
GenSub(T2);
PopSub := T2;
end;
{–}
После всех этих приготовлений, в конечном результате нет почти ничего кульминационного. Снова, вы можете видеть что логика совершенно проста. Все что делают эти две подпрограммы – выталкивают вершину стека в D7, приводят два операнда к одному размеру и затем генерируют код.
Обратите внимание на две новые подпрограммы генерации кода GenAdd и GenSub. Они являются остаточной формой оригинальных PopAdd и PopSub. Т.е. они являются чистыми генераторами кода, производящими сложение и вычитание регистров:
{–}
{ Add Top of Stack to Primary }
procedure GenAdd(Size: char);
begin
EmitLn('ADD.
|< Пред. 312 313 314 315 316 След. >|