{–}
{ Store Primary to Variable }
procedure StoreVar(Name, Typ: char);
begin
EmitLn('LEA ' + Name + '(PC),A0');
Move(Typ, 'D0', '(A0)');
end;
{–}
{ Store a Variable from the Primary Register }
procedure Store(Name: char);
begin
StoreVar(Name, VarType(Name));
end;
{–}
Вы можете проверить их таким же образом, что и загрузку.
Теперь, конечно, достаточно легко использовать их для обработки операций присваивания. Что мы сделаем – создадим специальную версию процедуры Block, которая поддерживает только операции приваивания, а также специальную версию Expression, которая поддерживает в качестве допустимых выражений только одиночные переменные. Вот они:
{–}
{ Parse and Translate an Expression }
procedure Expression;
var Name: char;
begin
Load(GetName);
end;
{–}
{ Parse and Translate an Assignment Statement }
procedure Assignment;
var Name: char;
begin
Name := GetName;
Match('=');
Expression;
Store(Name);
end;
{–}
{ Parse and Translate a Block of Statements }
procedure Block;
begin
while Look <> '.' do begin
Assignment;
Fin;
end;
end;
{–}
(Стоит заметить, что новые процедуры, которые позволяют нам манипулировать типами, даже проще и яснее чем те, что мы видели ранее. Это в основном блягодаря нашим усилиям по изоляции подпрограмм генерации кода.)
Есть одна небольшая назойливая проблема. Прежде мы использовали завершающую точку Паскаля чтобы выбраться из процедуры TopDecl. Теперь это неправильный символ... он использован для завершения Block. В предудущих программах мы использовали для выхода символ BEGIN (сокращенно 'b'). Но он теперь используется как символ типа.
Решение, хотя и является отчасти клуджем, достаточно простое. Для обозначения BEGIN мы будем использовать 'B' в верхнем регистре. Так что измените символ в цикле WHILE внутри TopDecl с '.' на 'B' и все будет прекрасно.
Теперь мы можем завершить задачу, изменив основную программу следующим образом:
{–}
{ Main Program }
begin
Init;
TopDecls;
Match('B');
Fin;
Block;
DumpTable;
end.
{–}
(Обратите внимание, что я должен был расставить несколько обращений к Fin чтобы избежать проблем переносов строк.)
ОК, запустите эту программу. Попробуйте ввести:
ba { byte a } *** НЕ НАБИРАЙТЕ КОММЕНТАРИИ!!! ***
wb { word b }
lc { long c }
B { begin }
a=a
a=b
a=c
b=a
b=b
b=c
c=a
c=b
c=c
.
Для каждого объявления вы должны получить сгенерированный код, распределяющий память. Для каждого присваивания вы должны получить код который загружает переменную корректного размера и сохраняет ее, также корректного размера.
Есть только одна небольшая проблема: сгенерированный код неправильный!
Взгляните на код для a=c:
MOVE.L C(PC),D0
LEA A(PC),A0
MOVE.B D0,(A0)