Mod/Профи.odc

MODULE Профи; (* простейшие программы в Блэкбоксе *)  (* в таких скобках комменты (* и они могут быть вложенными *) *)
	IMPORT StdLog, Math, In := i21sysIn;  (* импорт модулей; для последнего из импортируемых модулей введен короткий псевдоним, который и должен теперь всюду в данном модуле использоваться *)

	PROCEDURE Do1*;  (* Hello World *)
	BEGIN
		StdLog.String("Привет, профи! ");  (* печать в рабочий журнал (Log) цепочки литер *)
		StdLog.Real( Math.Pi() );       (* печать в Log результата функции Math.Pi() *)
		StdLog.Ln                           (* переход в Log на новую строку *)
	END Do1;

	PROCEDURE Do2*;  (* пример ввод из "командной строки" *)
		VAR  l, m, n: INTEGER;
	BEGIN
		In.Open;  ASSERT( In.Done );     (* открыть поток ввода; убедиться, что ок *)
		In.Int( l );  ASSERT( In.Done );   (* прочесть целое; убедиться, что ок *)
		In.Int( m );  ASSERT( In.Done );  (* типа можно считывать много *)
		IF  l > 0  THEN
			n := l + m;                            (* вычислить что-то *)
			StdLog.Int( n ); StdLog.Ln;    (* напечатать результат в Log *)
		ELSE
			HALT( 127 );       (* форсировать аварийную остановку с "выбросом кишок" *)
		END;
	END Do2;

END Профи. <<< конец исходника; компилятор игнорирует всё, что находится после точки.

Компиляция этого модуля: Ctrl+K (K латинское). Можно нажать! Смотреть в окошко Log (если его не видно, выполнить команду меню Info, Open Log / Инфо, Открыть журнал).
Выполнение процедур: клик по соотв. черному коммандеру, хоть два раза :) при этом наблюдать Log:
Профи.Do1  
Профи.Do2  3  2   <<< менять числа и кликать снова
Поменять 3 на -3 и кликнуть, чтобы посмотреть на символический дамп процедурного стека -- там можно смело покликать по синим ромбикам и черным стрелочкам. 
Нагулявшись по ромбикам, закрыть окошко Trap и продолжать читать тут.

Можно поменять что-нибудь в тексте модуля (добавить инструкции печати).
После изменений текста модуля: скомпилировать его, но чтобы выполнилась новая версия, при первом клике по коммандеру нажимать Ctrl (чтобы выкинуть из памяти старую версию модуля; потом можно Ctrl не нажимать -- модуль сидит в памяти, пока его не выкинут).


Программа Hello world в Блэкбоксе

Никаких project, make и т.п. заводить в Блэкбоксе не нужно. Просто напишите (см. ниже про как?) модуль (вроде показанного выше) и компилируйте его (см. ниже про как?). 
Модули линкуются невидимо, динамически при загрузке (причем безопасно, т.е. с проверкой интерфейсов и типов). 
Загрузка  по мере необходимости. Линковщик остается полностью за кулисами. 
(Еще одна фантомная боль:) Скомпоновать EXE или DLL можно. См. DevLinker, а также пособие по работе с DLL.
Но реально чаще не нужно: распространять свое приложение проще всего, переименовав BlackBox.exe и настроив соотв. образом загрузку (см. Особенностиплатформы) и меню (см. Среда). Можно в нескольких вариантах (кассир, охрана, ... БД, ...).

Программы в Блэкбоксе состоят из модулей (модуль = единица компиляции, инкапсуляции, загрузки). 

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

Чтобы завести новый модуль, нажать Ctrl+N (или через меню: File, New / Файлы, Новый)  и вперед.
Набирается модуль, в принципе, обычным манером. (Однако есть F5: подробней см.  насайте и в разделе Полезныесведения.)
Большие и малые буквы в языке различаются.

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

В каждом модуле может быть сколько угодно процедур, в том числе экспортированных (которые со звездочкой как у двух процедур в примере).
Нет главной (main) процедуры  этого наследия темных веков пакетной обработки (хватит уж, сколько можно).
Любая экспортированная процедура может быть вызвана извне, правда, при вызове коммандером или из меню есть ограничения на параметры (см. StdInterpreter). При вызове из программ никаких таких ограничений, конечно, нет.

Документ Блэкбокса  это не чистый текстовый файл. В нем можно менять размер, цвет и т.п. шрифта. (Установки по умолчанию: Edit, Preferences... / Правка, Настройки...) Кроме того, в текст здесь можно вставлять объекты изображения, они же вьюшки/views  например, маркеры ошибок, которые вставляет компилятор, или невидимые вьюшки, которые оформляют гиперссылки (чтобы увидеть/спрятать их, нажимать Ctrl+H; кстати, все вьюшки построены примерно по одному принципу, см. 6Построениеобъектовизображения(вьюшек)).

Компиляция: Ctrl+K (K латинская) или Dev, Compile / Программирование, Компилировать (модуль должен быть в переднем окошке, в начале текста). 
Есть и другие способы, например, целым списком (DevCompiler.CompileThis имя_модуля1 имя_модуля2 ...) или из программы, не открывая исходник в окошке, а сгенерив его на лету; см. интерфейс модуля DevCompiler (дважды кликнуть по DevCompiler, нажать Ctrl+D).
Если в тексте компилируемого модуля не появились маркеры ошибок (черные квадраты), а в журнале (Log) нет сообщения о количестве ошибок, значит, компиляция прошла успешно. 
По маркеру ошибок можно дважды кликнуть, чтобы прочесть соотв. сообщение об ошибке.

Чтобы выполнить процедуру, нужно где-то иметь (например, напечатать) ее полное имя (т.е. имя модуля, точка, имя процедуры). Если полное имя выделить мышкой, то выполнить процедуру можно командой меню Dev, Execute / Программирование, Выполнить (Процедуру). Но обычно перед полным именем вставляют т.наз. коммандер (черный кружок, см. выше) посредством Ctrl+Q (Tools, Insert Commander / Инструменты, Вставить коммандер) и кликают по нему.
Упр: покликать по обоим коммандерам вверху, наблюдая Log.

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

Модуль, раз загрузившись в память (например, при первом вызове одной из своих процедур), продолжает там сидеть и ждать команды (как объект-синглтон). 
Чтобы вызвать новую версию, предварительно выкинув старую, при клике по коммандеру нажимать Ctrl.

Интерфейс для любого модуля можно посмотреть, выделив его имя (хоть где, хотя бы в Log) и нажав Ctrl+D (Info, Interface / Инфо, Интерфейс (клиентский)). Например, дважды щелкните вот по этому  Strings  и посмотрите.

Документацию к любому модулю (если она приготовлена и хранится по правилам) можно посмотреть, выделив его имя и выполнив Info / Инфо, Documentation (для русского перевода  Документация). Подобные команды могут быть и в контекстном меню.

Чтобы настроить под себя меню (включая контекстные, а также горячие клавиши), вызвать Info, Меnus / Инфо, Меню, кликнуть нужную ссылку  откроется текстовый документ, внести в него изменения, сохранить, выполнить Info, Update Menus / Инфо, Обновить меню  меню обновятся без перезапуска (см. Среда).

Раскраска синтаксиса: при ключевых словах из больших букв это вещь избыточная. Доказано экспериментально: устроить ее нетрудно (можно начать хотя бы с i21sysEdit), и вновь приходящие люди по инерции ее делали (известны минимум две полноценные попытки, где-то лежат готовые к употреблению), но сами авторы в итоге публично отказывались от этих бирюлек за ненадобностью. 
Цвет очень полезен для других целей (отметить исправления и т.п.), и жалко растрачивать такую ценность на ерунду (при ключевых словах в all-caps их еще и раскрашивать  совершенно излишне).

Пошагового отладчика нет и, можно надеяться, не будет. Почему  см. тут.
Зато есть символический дамп (см. работу процедуры Do2 для отрицательного первого вводимого числа).
Учитесь культурно программировать 8))), шпигуя программу ASSERT'ами (прежде всего для предусловий и инвариантов цикла)  тогда символического дампа достаточно.

Обработки исключений тоже нет. По-настоящему это вещь (под названием прерывания) для реального времени. В обычном программировании это нелокальная передача управления, которая  при неизбежных массовых злоупотреблениях  обнуляет возможности верификации программ (классики вроде Дейкстры поняли это еще в 70-х гг.; а производители промышленных инструментов провоцируют и эксплуатируют разврат ничуть не хуже наркоторговцев).
Устроить для этого библиотеку (и обойтись без введения в язык) можно (Трапы же сделаны), но реальное время  всё-таки отдельная песня.

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

Ввод-вывод. За побайтовый ввод-вывод отвечает модуль Files. Там реализована схема (паттерн, шаблон) Carrier-Rider (кстати, изобретенный в рамках проекта Оберон к 1988). 

За ввод-вывод элементарных типов отвечают типы (=классы) Reader и Writer в модуле Stores. Там же средства поддержки сохранения на диск динамических структур данных с множественными внутренними ссылками (см. там тип Stores.Store; см. также пример в исходнике модуля i21sysDesktop, отталкиваясь от инструкций, выделенных синим, в процедурах Save и Restore, ближе к концу модуля).

Полезно иметь в виду, что модуль Files является (почти) чисто интерфейсным, лишь хранящим ссылки на стандартную реализацию (HostFiles), и вместо последней тому же Stores можно подсунуть любую другую (основанную на файлах, смоделированных в памяти, или какой-нибудь фасад над сетевым соединением и т.п.). Stores будет работать с любой корректной реализацией интерфейсов из Files как ни в чем не бывало.
Вообще философия ввода-вывода в Блэкбоксе отличается от старых подходов, здесь принят более высокоуровневый взгляд: чаще работают с блэкбоксовскими текстами (TextModels.Model), используя средства модулей TextMappers (и, возможно, Strings). Превратить внешний обычный текст в TextModels.Model можно примерно так:

	PROCEDURE ImportText ( f: Files.File;  OUT t: TextModels.Model );
		VAR  r: Stores.Reader;  w: TextModels.Writer;
			byte: SHORTCHAR;  ch: CHAR;  len: INTEGER;
	BEGIN
		ASSERT( f # NIL, 20 ); ASSERT( t = NIL, 21 );
		r.ConnectTo( f ); r.SetPos( 0 );
		len := f.Length();
		t := TextModels.dir.New();  w := t.NewWriter( NIL );
		WHILE  len # 0  DO
			r.ReadSChar( byte ); (* use directly r.ReadChar( ch ) to read 2-byte characters *)
			ch := byte;	(* сould translate character set here *)
			w.WriteChar( ch );  DEC( len )
		END;
		r.ConnectTo( NIL )
	END ImportText;

Последний тут маленький, но полезный штрих: ходить по какому-нибудь набору литер в документе можно так: выделить его (набор), нажать F3  попадем на следующий экземпляр этого набора в текущем документе; Shift+F3  на предыдущий; F4  на первый; Shift+F4  на последний. (Поупражняйтесь на ImportText в процитированной процедуре.)

Дальше можно изучать Примерыпроизводителя(подсистемаObx)

Успехов!
info21
2009-04-24
PS Большая благодарность В.В.Лаптеву за совет.
2011-02-04 Добавление русскоязычных названий меню, А.С.Ильин.