Программа в  Borland Pascal состоит из заголовка программы,  необязательного оператора uses и основного блока.

программа

і   ЪДДДДДДДДДї  ЪДДДїЪДДДДї  ЪДДДї

АДДДВД>ізаголовокГДД>і ; ГДДДВДДДДДДДДДДДДДДДДД>іблокГД>і . ГД>

і  іпрограммыі   АДДДЩ ^ і  ЪДДДДДДДДДДДї ^ АДДДДЩ  АДДДЩ

і  АДДДДДДДДДЩ   і АД>іпредложениеГДЩ

АДДДДДДДДДДДДДДДДДДДДДДЩ і  uses і

АДДДДДДДДДДДЩ

Заголовок программы определяет имя программы и ее параметры.

заголовок программы

 і

 і  ЪДДДДДДДї   ЪДДДДДДДДДДДДДї

АДД>іprogramГДД>іидентификаторГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД>

АДДДДДДДЩ  АДДДДДДДДДДДДДЩ і  ЪДДДї  ЪДДДДДДДДДї ЪДДДї ^

АД>і ( ГД>іпараметрыГД>і ) ГДЩ

АДДДЩ  іпрограммыі  АДДДЩ

АДДДДДДДДДЩ

 

ЪДДДДДДДДДДДДДДДї

   параметры программы ДДДД>і   список  ГДДДД>

іидентификаторові

АДДДДДДДДДДДДДДДЩ

Если заголовок программы присутствует, он является чисто декоративной деталью и компилятор его игнорирует.

Оператор uses идентифицирует все модули,  используемые программой, включая непосредственно используемые модули и модули, используемые этими модулями.

  ЪДДДДї   ЪДДДДДДДДДДДДДї   ЪДДДї

   предложение uses ДД>іusesГДДВДД>іидентификаторГДДДДД>і ; ГДДД>

  АДДДДЩ  і  АДДДДДДДДДДДДДЩ  ^   АДДДЩ

і   ЪДДДї   і

АДДДДД>і , ГДДДДДДДДДЩ

 АДДДЩ

Модуль System всегда используется  автоматически.  Для поддержки таких средств,  как файловый ввод-вывод,  обработка строк,  операции с плавающей запятой, динамическое распределение памяти и  других этот модуль реализует весь нижний уровень,  а также обслуживающие фоновые программы.

Паскаль, в свою очередь,  обслуживает многие стандартные модули, такие,  как Dos и Crt.  Это не происходит автоматически: вы  должны обязательно включить их в оператор uses. Например:

uses Dos,Crt; { теперь могут быть доступны средства модулей

  Dos и Crt }

Чтобы найти файл, содержащий скомпилированный модуль, компилятор усекает  указанное в  операторе  uses имя модуля до первых  восьми файлов и добавляет расширение файла. Если целевой платформой является DOS,  расширением будет .TPU. Если целевая платформа  - Windows, то расширением файла будет .TPW. Если целевой платформой является  защищенный  режим  DOS, то расширением файла будет  .TPP. Хотя имена файлов усекаются, в операторе uses должен указываться полный идентификатор модуля.

Модули являются основой модульного программирования. Они используются  для  создания  библиотек, которые могут включаться в  различные программы (при этом становится необязательным  иметь  в  наличии  исходный код),  а большие программы могут подразделяться на логически связанные модули.

ЪДДДДДДДДДї   ЪДДДї  ЪДДДДДДДДДДї

  модуль  ДДДДД>ізаголовокГДД>і ; ГДД>іинтерфейс-ГДДДї

і модуля  і  АДДДЩ   іный разделі   і

АДДДДДДДДДЩ  АДДДДДДДДДДЩ   і

 ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

  і  ЪДДДДДДДДДДї ЪДДДДДДДДДДДДДї   ЪДДДї

  АД>і раздел   ГДДД>і раздел   ГДД>і . ГДД>

     іреализацииііинициализацииі   АДДДЩ

  АДДДДДДДДДДЩ АДДДДДДДДДДДДДЩ

В заголовке модуля определяется имя модуля.

   ЪДДДДї   ЪДДДДДДДДДДДДДДДДДДДДї

   заголовок модуля ДДД>іunitіДД>іидентификатор модуляіДДДД>

   АДДДДЩ   АДДДДДДДДДДДДДДДДДДДДЩ

Имя модуля используется при ссылке на модуль  в  предложении  использования. Это имя должно быть уникальным, так как два модуля  с одним именем не могут одновременно использоваться.

 

Имя исходного  файла модуля и двоичного файла должны совпадать с идентификатором модуля,  усеченным до первых  8 символов.  Если это  не  так,  то компилятор не сможет найти исходный и/или  двоичный файл при компиляции использующей этот модуль программы.

В интерфейсной секции описываются те константы,  типы, переменные,  процедуры и функции, которые являются глобальными,  то  есть доступными основной программе (программе или модулю, которые  используют данный модуль). Основная программа имеет доступ к этим  элементам, как если бы они были описаны в модуле, являющимся вложенным по отношению к данной программе.

   интерфейсная секция

   і

   і ЪДДДДДДДДДї

  АД>іinterfaсeГДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВД>

   і   і і  ЪДДДДДДДДДДДї^ ^ і  ЪДДДДДДДДДДДДДДДДДДї ^ і

   АДДДДДДДДДЩ АД>і  оператор ГЩ і ГД>і  раздел описания ГДґ і

   і   usesі  і і  і  констант  і і і

   АДДДДДДДДДДДЩ  і і АДДДДДДДДДДДДДДДДДДЩ і і

   і і  ЪДДДДДДДДДДДДДДДДДДї і і

   і ГД>і  раздел описания ГДґ і

   і і  і типов переменных і і і

   і і  АДДДДДДДДДДДДДДДДДДЩ і і

   і і  ЪДДДДДДДДДДДДДДДДДДї і і

   і ГД>і  раздел описания ГДґ і

   і і  іпеременных і і і

  і і  АДДДДДДДДДДДДДДДДДДЩ і і

   і і  ЪДДДДДДДДДДДДДДДДДДї і і

   і АД>іраздел заголовков ГДЩ і

  і іпроцедур и функцийі   і

  і АДДДДДДДДДДДДДДДДДДЩ   і

  АДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ

 

   раздел заголовков

   процедур и функций

і  ЪДДДДДДДДДї ЪДДДї

    АДДДДВДД>ізаголовокГДДДДДДДДДД>і ; ГДВДДДДДДДДДДДДДДДДДДДДДДД>

   і   іпроцедурыі  ^  АДДДЩ і ЪДДДДДДДДДї   ЪДДДї ^

   і   АДДДДДДДДДЩ  і  АД>ідирективаГДД>і ; ГДЩ

   і  ЪДДДДДДДДДДДДДДДДДї і і inline  і  АДДДЩ

   АД>ізаголовок функцииГДЩ  АДДДДДДДДДЩ

   АДДДДДДДДДДДДДДДДДЩ

В том случае, если процедура или функция является процедурой  или функцией типа inline, в интерфейсной секции содержится только  список заголовков процедур  или функций.  Модуль  процедуры или  функции следует дальше в секции реализации.  Заметим, что заголовок процедуры или функции может дублироваться и быть  здесь таким  же, как в интерфейсной секции. Вам не нужно задавать здесь список  формальных параметров,  но если вы это сделали и если описание  в  интерфейсной секции и секции реализации не совпадают, то компилятор во время компиляции выдаст сообщение об ошибке.

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

   Секция реализации

   і

   і ЪДДДДДДДДДДДДДДї   ЪДДДДДДДДДДДДДДДДДДї

  АД>іimplementationГДВДДДДДДДДДДДДДДДДДД>і раздел описаний  ГДД>

   АДДДДДДДДДДДДДДЩ і  ЪДДДДДДДДДДДї^   АДДДДДДДДДДДДДДДДДДЩ

  АД>і  оператор ГЩ

     і  uses і

  АДДДДДДДДДДДЩ

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

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

Секция инициализации является последней секцией  модуля. Она может  состоять либо из зарезервированного слова end (в этом случае модуль не содержит кода инициализации),  либо из  операторной  части, которая должна выполняться для инициализации модуля.

  ЪДДДї

секция инициализации ДДДВДД>іendГДДДДДДДДДДДДДДДДДД>

і   АДДДЩ  ^

і  ЪДДДДДДДДДДДДДДДДДї і

АД>іоператорная частьГДЩ

АДДДДДДДДДДДДДДДДДЩ

Секции инициализации модулей,  которые используются программой, выполняются в том же порядке, в каком модули указаны в операторе uses.

В операторе uses в  основной программе  должны  содержаться  имена всех модулей, непосредственно или косвенно используемых основной программой. Рассмотрим следующий пример:

Program Prog;

uses Unit1, Unit2

const a = b;

begin

end.

end.

 

unit Unit2;

interface

uses Unit1;

const b = c;

implementation

end.

 

unit Unit1;

interface

const c = 1;

implementation

const d = 2;

end;

В данном примере Unit12 непосредственно зависит от Unit1,  а  Prog непосредственно зависит от Unit2.  Кроме того,  Prog зависит  косвенно от Unit1 (через Unit1),  хотя ни один  из  описанных в Unit1 идентификаторов в Prog не доступен.

Для компиляции программы компилятор должен иметь возможность  находить все модули,  от которых она прямо или косвенно  зависит.  Поэтому, для  компиляции Prog компилятор должен иметь возможность  найти и Unit1, и Unit2, иначе возникнет ошибка.

Когда в интерфейсную часть модуля вносятся изменения, другие  модули,  использующие этот модуль, должны быть заново скомпилированы. При использовании команд Make или Build  компилятор  делает  это автоматически. Однако, если изменения коснулись только секции  реализации или секции инициализации,  то другие модули, в которых  используется этот модуль,  перекомпилировать не нужно. В предыдущем примере,  если интерфейсная часть  модуля  Unit1 изменилась  (например, с = 2), то модуль Unit2 нужно перекомпилировать. Изменение же секции реализации (например,  d = 1) не требует перекомпиляции Unit2.

При компиляции модуля в Borland Pascal на основе контрольной  суммы интерфейсной секции вычисляется номер версии модуля. В предыдущем  примере  при  компиляции модуля Unit2 в скомпилированной  версии модуля Unit2 сохраняется номер версии  модуля  Unit1.  При  компиляции основной программы номер версии модуля Unit1 сравнивается с номером версии,  сохраненным в модуле Unit2.  Если номера  версий  не  совпадают,  что свидетельствует об изменении в интерфейсной части модуля Unit1 со времени последней компиляции модуля  Unit2, компилятор, в зависимости от режима компиляции, выдает сообщение об ошибке или перекомпилирует модуль Unit2 (в зависимости  от режима компиляции).

Размещение в  секции реализации  оператора  uses позволяет  "скрыть" внутренние детали модуля,  поскольку используемые в секции реализации модули оказываются "невидимыми" для того, кто этот  модуль использует.  Более важным,  однако,  является то,  что это  позволяет вам строить взаимозависимые модули.

В следующей программе показаны два модуля,  которые "используют" друг друга. Основная программа Circular использует модуль с  именем Display. Модуль Display содержит в своей интерфейсной секции одну программу WriteXY, которая имеет три параметра: пару координат (x,y) и сообщение для вывода на экран. WriteXY перемещает  курсор в точку (x,y) и выводит там сообщение.  В противном случае  она вызывает простую программу обработки ошибки.

Пока мы не видим здесь ничего интересного: процедура WriteXY  просто используется вместо процедуры Write.  Однако далее,  когда  программа обработки ошибки будет выводить сообщение на экран, начинаются  перекрестные ссылки (ведь при этом она снова использует  WriteXY).  Таким образом,  мы имеем процедуру WriteXY, вызывающую  процедуру обработки ошибки SwapError,  которая в свою очередь вызывает WriteXY для вывода сообщения на экран.  Если у вас уже  от  всего этого закружилась голова,  не беда. Давайте рассмотрим исходный код в примере и увидим, что все это не столь уж запутано.

Основная программа Circular очищает экран  и  выполняет три  обращения к процедуре WriteXY:

program Circular;

{ выводит текст, используя WriteXY }

 

uses

WinCrt, Display;

 

begin

   ClrScr;

  WriteXY(1, 1, 'Левый верхний угол экрана');

   WriteXY(100, 100, 'За пределами экрана');

   WriteXY(81 - Lenght('Снова в экран..'), 15,

  'Снова в экран..');

end.

Взгляните на координаты (x,y) при втором обращении к процедуре WriteXY.  В точке с координатами (100,100) на 80х25-символьном экране  вывести текст невозможно.  Давайте теперь посмотрим,  как работает процедура WriteXY.  Далее приведен  текст  исходного  кода модуля Display, в котором содержится процедура WriteXY. Если  координаты (x,y) являются допустимыми, она выводит на экран сообщение. В противном случае она выводит сообщение об ошибке.

unit Display;

{ содержит простую программу вывода информации на экран }

 

interface

 

procedure WriteXY(X,Y : integer, Message : string);

 

implementation

uses

Crt, Error;

procedure WriteXY(X,Y : integer, Message : string);

begin

   if (X in [1..80] and Y in [1..25] then

   begin

  Goto(X,Y);

  Write(Message);

   end;

   else

  ShowError('Неверные координаты в процедуре WriteXY');

end;

 

end.

Процедура ShowError, вызываемая в процедуре WriteXY, показана в приведенном далее исходном коде модуля Error. Она всегда выводит сообщение об ошибке на 25-й строке экрана.

unit Error;

{ содержит простую программу сообщения об ошибке }

 

interface

 

procedure ShowError(ErrMsg : string);

 

implementation

 

uses

Display;

 

procedure ShowError(ErrMsg :string);

begin

   WriteXY(1,25, 'Ошибка: '+ ErrMsg);

end;

 

    end.

Обратите внимание,  что операторы  uses в секции реализации  обоих модулей (Display и Error) ссылаются друг на друга.  Эти два  модуля могут ссылаться друг на друга в секции реализации благодаря тому,  что Borland Pascal может для обеих  модулей  выполнять  полную компиляцию интерфейсных секций.  Другими словами, компилятор воспринимает ссылку на частично скомпилированный модуль  A  в  секции  реализации модуля В,  если интерфейсные секции модуля A и  модуля В не зависят друг от друга (и,  следовательно, строго соблюдаются правила Паскаля, касающиеся порядка описания).

В случае  взаимозависимости  интерфейсных  секций модулей вы  получите ошибку из-за перекрестных ссылок.

Можно модифицировать процедуру WriteXY таким образом,  чтобы  она воспринимала дополнительный параметр,  задающий прямоугольное  окно на экране:

procedure WriteXY(SomeWindow : WindRec;

X, Y : integer;

    Message :string);

 

procedure ShowError(Somewindow : WindRec; ErrMsg : string);

Нужно учитывать,  что две процедуры находятся в разных модулях. Даже если вы описываете WindData в интерфейсной секции одного модуля,  то нет такого допустимого способа, с помощью которого  это описание могло бы быть доступно в другом модуле. Решение состоит в том,  чтобы описать третий модуль, в  котором  содержится  только определение записи WindRec:

unit WindData;

interface

 

type

   WindRec = record

  X1, Y1, X2, Y2 : integer;

  ForeColor,

  BackColor   : byte;

     Active  : boolean;

end;

implementation

end.

В добавление к тому, что модификация кода процедур WriteXY и  ShowError  позволяет использовать новый параметр,  в интерфейсной  секции  модулей  Display  и Error  теперь  может использоваться WindData.  Это  допустимо,  так как модуль WindData не зависит от  своего оператора uses, а модули Display и Error ссылаются друг на друга только в соответствующих секциях реализации.

Взаимозависимые модули могут быть полезны в отдельных ситуациях, но использовать их надо аккуратно. Если вы будете применять  их так,  где это не требуется, программу станет сложней обслуживать, и она будет больше подвержена ошибкам.