Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
14
Добавлен:
02.05.2014
Размер:
10 Кб
Скачать
unit Triads;

interface
{ Модуль, обеспечивающий работу с триадами
  и списком триад }

uses Classes, TblElem, LexElem, TrdType;

type
{ Предварительное описание класса триад }
TTriad = class;
{ Типы операндов: константа, переменная,
  ссылка на другую триаду }
TOpType = (OP_CONST, OP_VAR, OP_LINK);

{ Структура данных для описания операнда в триадах }
TOperand = record
  { Тип операнда }
  case OpType: TOpType of
    OP_CONST: (ConstVal: integer);
    { для константы - её значение }
    OP_VAR:   (VarLink: TVarInfo);
    { для переменной - ссылка на элемент
      таблицы идентификаторов }
    OP_LINK:  (TriadNum: integer);
    { для триады - номер триады }
end;
{ Массив операндов из двух элементов }
TOpArray = array[1..2] of TOperand;

{ Структура данных для описания триады }
TTriad = class(TObject)
 private
  { Тип триады }
  TriadType: TTriadType;
  { Массив операндов }
  Operands: TOpArray;
 public
{ Дополнительная информация для оптимизирующих алгоритмов }
  Info: longint;
  { Флаг наличия ссылки на эту триаду }
  IsLinked: Boolean;
  { Конструктор для создания триады }
  constructor Create(Typ: TTriadType; const Ops: TOpArray);
  { Функции для чтения и записи операндов }
  function GetOperand(iIdx: integer): TOperand;
  procedure SetOperand(iIdx: integer; Op: TOperand);
  { Функции для чтения и записи ссылок на другие триады }
  function GetLink(iIdx: integer): integer;
  procedure SetLink(iIdx: integer; TrdN: integer);
  { Функции для чтения и записи типа операндов }
  function GetOpType(iIdx: integer): TOpType;
  procedure SetOpType(iIdx: integer; OpT: TOpType);
  { Функции для чтения и записи значений констант }
  function GetConstVal(iIdx: integer): integer;
  procedure SetConstVal(iIdx: integer; iVal: integer);
  { Свойства триады, основанные на описанных выше
    функциях }
  property TrdType: TTriadType read TriadType;
  property Opers[iIdx: integer]: TOperand read GetOperand
                                write SetOperand; default;
  property Links[iIdx: integer]: integer read GetLink
                                write SetLink;
  property OpTypes[iIdx: integer]: TOpType read GetOpType
                                write SetOpType;
  property Values[iIdx: integer]: integer read GetConstVal
                                write SetConstVal;
  { Функция, проверяющая совпадение (эквивалентность)
    двух триад }
  function IsEqual(Trd1: TTriad): Boolean;
  { Функция, формирующая строковое представление триады }
  function MakeString(i: integer): string;
 end;

{ Класс для описания списка триад и работы с ним }
TTriadList = class(TList)
 public
  { Процедура очистки списка и деструктор
    для удаления списка }
  procedure Clear; override;
  destructor Destroy; override;
  { Процедура вывода списка триад в список строк
    для отображения списка триад }
  procedure WriteToList(list: TStrings);
  { Процедура удаления триады из списка }
  procedure DelTriad(iIdx: integer);
  { Функция получения триады из списка по её номеру }
  function GetTriad(iIdx: integer): TTriad;
  { Свойство списка триад для доступа к нему
    по номеру триады }
  property Triads[iIdx: integer]: TTriad read GetTriad;
     default;
end;

{ Процедура удаления из списка триад
  всех триад заданного типа }
procedure DelTriadTypes(listTriad: TTriadList;
                        TrdType: TTriadType);

implementation

uses SysUtils, FncTree, LexType;

constructor TTriad.Create(Typ: TTriadType;
                          const Ops: TOpArray);
{ Конструктор создания триады }
var i: integer;
begin
  { Вызываем конструктор базового класса }
  inherited Create;
  { Запоминаем тип триады }
  TriadType := Typ;
  { Запоминаем два операнда триады }
  for i:=1 to 2 do Operands[i] := Ops[i];
  { Очищаем поле дополнительной информации
    и поле внешней ссылки }
  Info := 0;
  IsLinked := False;
end;

function TTriad.GetOperand(iIdx: integer): TOperand;
{ Функция получения данных об операнде триады
  по его номеру }
begin
  Result := Operands[iIdx];
end;

procedure TTriad.SetOperand(iIdx: integer; Op: TOperand);
{ Функция записи данных операнда триады по его номеру }
begin
  Operands[iIdx] := Op;
end;

function TTriad.GetLink(iIdx: integer): integer;
{ Функция получения ссылки на другую триаду из операнда
  по его номеру }
begin
  Result := Operands[iIdx].TriadNum;
end;

procedure TTriad.SetLink(iIdx: integer; TrdN: integer);
{ Функция записи номера ссылки на другую триаду
  в операнд по его номеру }
begin
  Operands[iIdx].TriadNum := TrdN;
end;

function TTriad.GetOpType(iIdx: integer): TOpType;
{ Функция получения типа операнда по его номеру }
begin
  Result := Operands[iIdx].OpType;
end;

function TTriad.GetConstVal(iIdx: integer): integer;
{ Функция записи типа операнда по его номеру }
begin
  Result := Operands[iIdx].ConstVal;
end;

procedure TTriad.SetConstVal(iIdx: integer; iVal: integer);
{ Функция получения значения константы в операнде
  по его номеру }
begin
  Operands[iIdx].ConstVal := iVal;
end;

procedure TTriad.SetOpType(iIdx: integer; OpT: TOpType);
{ Функция записи значения константы в операнд
  по его номеру }
begin
  Operands[iIdx].OpType := OpT;
end;

function IsEqualOp(const Op1,Op2: TOperand): Boolean;
{ Функция проверки совпадения (эквивалентности)
  двух операндов }
begin
  { Операнды равны, если совпадают их типы }
  Result := (Op1.OpType = Op2.OpType);
  { и значения в зависимости от типа }
  if Result then
  case Op1.OpType of
    OP_CONST: Result := (Op1.ConstVal = Op2.ConstVal);
    OP_VAR:   Result := (Op1.VarLink = Op2.VarLink);
    OP_LINK:  Result := (Op1.TriadNum = Op2.TriadNum);
  end;
end;

function TTriad.IsEqual(Trd1: TTriad): Boolean;
{ Функция, проверяющая совпадение (эквивалентность)
  двух триад }
begin
  { Триады эквивалентны, если совпадают их типы }
  Result := (TriadType = Trd1.TriadType)
        { и оба операнда }
        and IsEqualOp(Operands[1],Trd1[1])
        and IsEqualOp(Operands[2],Trd1[2]);
end;

function GetOperStr(Op: TOperand): string;
{ Функция формирования строки для отображения
  оператора триады }
begin
  case Op.OpType of
    OP_CONST: Result := IntToStr(Op.ConstVal);
    OP_VAR:   Result := Op.VarLink.VarName;
    OP_LINK:  Result := '^'+ IntToStr(Op.TriadNum+1);
  end{case};
end;

function TTriad.MakeString(i: integer): string;
begin
  Result := Format('%d:'#9'%s (%s, %s)',
            [i+1,TriadStr[TriadType],
             GetOperStr(Opers[1]),GetOperStr(Opers[2])]);
end;

destructor TTriadList.Destroy;
{ Деструктор для удаления списка триад }
begin
  { Очищаем список триад }
  Clear;
  { Вызываем деструктор базового класса }
  inherited Destroy;
end;

procedure TTriadList.Clear;
{ Процедура очистки списка триад }
var i: integer;
begin
  { Освобождаем память для всех триад из списка }
  for i:=Count-1 downto 0 do TTriad(Items[i]).Free;
  { Вызываем функцию базового класса }
  inherited Clear;
end;

procedure TTriadList.DelTriad(iIdx: integer);
{ Функция удаления триады из списка триад }
begin
  { Если это не последняя триада }
  if iIdx < Count-1 then
   { и если на нее есть ссылка - переставляем
     флаг ссылки на предыдущую }
   TTriad(Items[iIdx+1]).IsLinked :=
      TTriad(Items[iIdx+1]).IsLinked
      or TTriad(Items[iIdx]).IsLinked;
  { Освобождаем память триады }
  TTriad(Items[iIdx]).Free;
  { Удаляем ссылку на триаду из списка }
  Delete(iIdx);
end;

function TTriadList.GetTriad(iIdx: integer): TTriad;
{ Функция выборки триады из списка по её номеру }
begin
  Result := TTriad(Items[iIdx]);
end;

procedure TTriadList.WriteToList(list: TStrings);
{ Процедура вывода списка триад в список строк
  для отображения списка триад }
var
  i,iCnt: integer;
begin
  { Очищаем список строк }
  list.Clear;
  iCnt := Count-1;
  { Для всех триад из списка триад }
  for i:=0 to iCnt do
   { Формируем строковое представление триады
     и добавляем его в список строк }
   list.Add(TTriad(Items[i]).MakeString(i));
end;

procedure DelTriadTypes(listTriad: TTriadList;
                        TrdType: TTriadType);
{ Процедура удаления из списка триад всех триад
  заданного типа }
var
  i,j,iCnt,iDel: integer;
  listNum: TList;
  Trd: TTriad; { список для запоминания изменений
                 индексов триад }
begin
  { Вначале изменение индекса нулевое }
  iDel := 0;
  iCnt := listTriad.Count-1;
  { Создаем список для запоминания изменений
    индексов триад }
  listNum := TList.Create;
  try
    { Для всех триад списка выполняем запоминание
      изменений индекса }
    for i:=0 to iCnt do
    begin
      { Запоминем изменение индекса данной триады }
      listNum.Add(TObject(iDel));
      { Если эта триада удаляемого типа,
        то увеличиваем изменение индекса }
      if listTriad[i].TriadType = TrdType then Inc(iDel);
    end;
    { Для всех триад списка изменяем индексы ссылок }
    for i:=iCnt downto 0 do
    begin
      Trd := listTriad[i];
      { Если эта триада удаляемого типа, то удаляем ее }
      if Trd.TriadType = TrdType then listTriad.DelTriad(i)
      else
      { Иначе для обоих операндов триады смотрим,
        не является ли он ссылкой }
      for j:=1 to 2 do
       if Trd[j].OpType = OP_LINK then
        { Если операнд является ссылкой на триаду,
          уменьшаем её индекс }
        Trd.Links[j] :=
          Trd.Links[j] - integer(listNum[Trd.Links[j]]);
    end;
    { Уничтожаем список для запоминания
      изменений индексов триад }
    finally listNum.Free;
  end;
end;

end.

Соседние файлы в папке Common