<тело внешней функции> <конец внешней функции>
<заголовок внешней подпрограммы> ::= EXTERNAL PROCEDURE <имя внешней процедуры>
<заголовок внешней функции>::= EXTERNAL FUNCTION <имя внешней процедуры>
<внешний тип>
<имя внешней процедуры> ::= <идентификатор>
| <идентификатор> <список внешних параметров>
<список внешних параметров>::= <заголовок внешних параметров>)
<заголовок внешних параметров>::= (<внешний параметр>
| <заголовок внешних параметров>, <внешний параметр>
<внешний параметр>::= <идентификатор> <внешний тип>
| <идентификатор> <внешний тип> NAME
<внешний тип>::= <базовый тип>
<тело внешней подпрограммы>::= <тело сегмента>
<тело внешней функции>::= <тело сегмента>
<конец внешней подпрограммы>::= END EXTERNAL PROCEDURE <идентификатор>;
<конец внешней функции>::= END EXTERNAL FUNCTION <идентификатор>;
<Внешние процедуры> позволяют компилировать модули раздельно и собирать их вместе во время загрузки. При загрузке допускается лишь одна <внешняя процедура> с данным именем. <Внешние параметры> и возвращаемые <внешними функциями> значения должны иметь <базовый тип>. <Внешние параметры> передаются по значению, если они не помечены резервированным словом NAME; при наличии этого слова параметры передаются по имени. Перед <концом внешней подпрограммы> неявно располагается <инструкция возврата>, однако <внешние функции> должны завершать работу явной <инструкцией возврата> с возвращаемым значением; попытка выхода из <внешней функции> через <конец внешней функции> является семантической ошибкой, которую иногда можно обнаружить при компиляции. Единственной связью между переменными <внешней процедуры> и переменными вызывающей процедуры служит механизм передачи параметров. Однако во время сборки сегментов (например, с помощью загрузчика, подобного описанному в гл. 26) будет проверено совпадение типов формальных и фактических параметров, функций и возвращаемых значений.
Из описания <внешних процедур> усматривается несколько важных различий между Мини и современными языками. В коммерческом языке целесообразно обеспечивать средства для разделения деклараций всех видов между <программными сегментами>. На наш взгляд, усложнения, вносимые в язык такой возможностью, слишком велики по сравнению с педагогическим эффектом от их реализации: это же справедливо по отношению к расширению диапазона возможных типов параметров <внешних процедур>. С другой стороны, коммерческие языки в своем большинстве не допускают передачу параметров по имени (из соображений эффективности), в то время как студента, овладевшего механизмом передачи по имени, не смутить уже, кажется, ничем. Мини многословнее аналогичных языков, поскольку современные исследования[56] показали важность умело распределенной избыточности для исправления синтаксических ошибок. Кроме того, программист, пишущий на Мини, должен явно различать декларации подпрограмм и функций. Хотя компилятор и может самостоятельно выявить различие, язык заставляет программиста явно демонстрировать свои намерения.
Наконец, Мини позволяет полностью проверить совпадение типов во время компиляции и загрузки, следуя неписаному закону: во время выполнения нужно делать как можно меньше.
<тело сегмента>::= <раздел определения типов> <раздел декларации переменных> <раздел определения процедур> <раздел выполняемых инструкций>
<раздел определения типов>::= | <раздел определения типов> <определение типа>
<раздел декларации переменных>::= I <раздел декларации переменных> <декларация переменных>
<раздел определения процедур> ::= | <раздел определения процедур> <определение процедуры>
<раздел выполняемых инструкций>::=<выполняемая инструкция>
| <раздел выполняемых инструкций>
<выполняемая инструкция>
<Тело сегмента> состоит не менее чем из одной <выполняемой инструкции>, которой, возможно, предшествуют <определения типов>, <декларации переменных> и <определения процедур>. Область действия любого имени — вся оставшаяся часть тела данного сегмента; это имя можно использовать в следующих определениях и декларациях. Одно и то же имя нельзя декларировать или определять дважды в <теле сегмента>. Как и в Алголе, имя можно переопределить или передекларировать во внутреннем <теле сегмента>.
<определение типа>::= TYPE <идентификатор> IS <тип>
<тип>::== <базовый тип>
| <массивный тип>
| <структурный тип>
| <идентификатор типа>
<базовый тип> ::= INTEGER
| REAL
| BOOLEAN
| STRING
<массивный тип> ::= ARRAY <границы> OF <тип>
<границы>::= [<граничное выражение>] [<граничное выражение>: <граничное выражение>]
<граничное выражение>::= <выражение>
<структурный тип>::= STRUCTURE <список полей> END STRUCTURE
<список полей>::=<поле>
| <список полей>, <поле>
<поле>::== FIELD <идентификатор> IS <тип>
<идентификатор типа>::= <идентификатор>