1
Общий раздел / Re: Oberon rev. 2015 (февраль)
« : Март 30, 2015, 03:21:24 pm »
Oberon07.Report.doc [25.07.2012] скачал не я, взял из архива какого-то оберонщика.
Онлайн компилятор Oberon-07/11
Путеводитель по Оберон-проектам.
Логи jabber-конференции.
Онлайн исходники BlackBox: тут:WeBB и на github
Исходники Project Oberon V4 на github.
Сборник решений задач книги "Современное программирование с нуля!" тут. А обсуждение здесь.
В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.
ddn:Я бы выложил (500K), да не знаю куда. Работающих файлопомоек больше не существует.
Можете скинуть все версии репорта?
Ну как бэ очевидно, что список идентификаторов имеет мало смысла.Почему мало смысла? Смысл имеют их значения, взятые как изолировано, так и в качестве границ интервалов значений. В предыдущей версии от 16.06.2014, что была еще без CASE как WITH, так и было:
CaseLabelList = LabelRange {"," LabelRange}.Следует учесть, что варианты выбора CASE статические и определены во время компиляции (иначе зачем нужен оператор CASE когда есть IF-THEN?), то есть ident - это был идентификатор константы.
label = integer | string | ident.
CaseLabels = ConstExpression [".." ConstExpression].Но для простоты исходного кода Вирт оставил только integer, string и ident.
Интересно, что Вирт выкинул ident из case-меток и оставил только литерные константы integer и string (типа CHAR).Он только заменил ident на qualident.
CaseLabelList = LabelRange {"," LabelRange} | qualident.Список интервалов значений LabelRange {"," LabelRange} используется в CASE как CASE. В то время как qualident может использоваться только вместо списка интервалов значений, как единичное значение, а для CASE как CASE это странное ограничение.
label = integer | string.
CaseLabelList = LabelRange {"," LabelRange}.
label = integer | string | qualident.
было бы по вашему.
Отличие первое: Вирт поменял определение типа SET, теперь это "SET the sets of integers between 0 and an implementation-dependent limit ", то есть SET может быть и 8 битным и 32 и 128 и даже 3 битным. Зависит от реализации.Нет, это произошло еще в версии от 11 марта 2014 г. (Revision 10.03.2014-I)
Таким образом Вирт окончательно отвязал Оберон от 32битной платформы и мы теперь не знаем какая разрядность у INTEGER'a, SET и так далее.
Портабельность приложений написанных на Обероне становится довольно условной.Для портабельности требуется ввести в каждый исходный файл версию компилятора (либо сигнатуру полностью конкретизированной во всех деталях версии языка), типа спецкомментария, и расширить компилятор на ее обработку. Модули разных версий (как исходники, так и бинарники) будут не совместимы и не смогут использоваться вместе. Прямой переносимости программ не будет, но можно сделать канонический транслятор исходников из версии в версию.
К сожалению в Обероне даже нельзя сделать TYPE INT16 = INTEGER -- это запрещено репортом. Можно конечно выкрутиться тестами и прочим, но это уже не просто костыли, это уже целые заросли костылей. Экзоскелет для оберона.В Обероне-11 и позднее вообще невозможно во время компиляции проверить реализацию базовых типов, или определить реализацию в реал-тайм, даже поверить реализацию в реал-тайм можно только через аварийный выход. В более ранних версиях можно проверить реализацию во время компиляции посредством функций MIN, MAX и DIV.
(* all version: *)
(* MIN(LONGINT) <= MIN(INTEGER) *)
(* MIN(INTEGER) <= MIN(BYTE) *)
(* MIN(BYTE) <= MAX(BYTE) *)
(* MAX(BYTE) <= MAX(INTEGER) *)
(* MAX(INTEGER) <= MAX(LONGINT) *)
CONST
sheckminint = 1 DIV
MIN(
MIN(
(MIN(BYTE)+1) - MIN(MIN(BYTE)+1,-127-1),
MAX(MIN(BYTE),-127) - MIN(BYTE)
),
MIN(
(MIN(INTEGER)+1) - MIN(MIN(INTEGER),-2147483647-1),
MAX(MIN(INTEGER),-2147483647) - MIN(INTEGER)
),
MIN(
(MIN(LONGINT)+1) - MIN(MIN(LONGINT),-9223372036854775807-1),
MAX(MIN(LONGINT),-9223372036854775807) - MIN(LONGINT)
)
);
(* equivalent: *)
(* 1 <= MAX(LONGINT) *)
(* MIN(BYTE) = -128 *)
(* MIN(INTEGER) = -2147483648 *)
(* MIN(LONGINT) = -9223372036854775808 *)
CONST
sheckmaxint = 1 DIV
MIN(
MIN(
MAX(BYTE) - MIN(MAX(BYTE),127-1),
MAX(MAX(BYTE)-1,127) - (MAX(BYTE)-1)
),
MIN(
MAX(INTEGER) - MIN(MAX(INTEGER),2147483647-1),
MAX(MAX(INTEGER)-1,2147483647) - (MAX(INTEGER)-1)
),
MIN(
MAX(LONGINT) - MIN(MAX(LONGINT),9223372036854775807-1),
MAX(MAX(LONGINT)-1,9223372036854775807) - (MAX(LONGINT)-1)
)
);
(* equivalent: *)
(* MIN(LONGINT) <= 1 *)
(* MAX(BYTE) = 127 *)
(* MAX(INTEGER) = 2147483647 *)
(* MAX(LONGINT) = 9223372036854775807 *)
3 Revision 22.9.2011
7 1. Introduction
114 ABS ASR ASSERT BOOLEAN CHAR
115 CHR COPY DEC EXCL FLOOR
117 LSL LONG LONGREAL NEW ODD
118 ORD PACK REAL ROR SET
119 SHORT UNPK
159 (158) LONGREAL real numbers
161 (160) The type LONGREAL is intended to represent real numbers with a higher number of digits than
162 (]160..161[) REAL. However, the two types may be identical.
182 (180) associate from left to right. For example, x-y-z stands for (x-y)-z.
185 (183) SimpleExpression = ["+"|"-"] term {AddOperator term}.
186 (184) AddOperator = "+" | "-" | OR.
309 (307) - difference
314 (312) The operators +, -, *, and / apply to operands of numeric types. Both operands must be of the
315 (313) same type, which is also the type of the result. When used as unary operators, - denotes sign
319 (317) x = q*y + r 0 ? r < y
324 (321) - difference
352 (350) (i+j) * (i-j) (INTEGER)
354 (352) a[i+j] * a[i-j] (REAL)
357 (355) k IN {i .. j-1} (BOOLEAN)
441 (439) | 1: x := x - y
497 (495) In addition to its formal parameters and locally declared objects, the objects declared in the
498 (496) environment of the procedure are also visible in the procedure (with the exception of variables and
499 (]496..497[) of those objects that have the same name as an object declared locally).
565 (562) ABS(x) numeric type type of x absolute value
566 (563) ODD(x) INTEGER BOOLEAN x MOD 2 = 1
567 (564) LEN(v) v: array the length of v
568 (565) LSL(x, n) x: INTEGER type of x logical shift left, x * 2 n
569 (566) ASR(x, n) x: INTEGER type of x signed shift right, x DIV 2 n
570 (567) ROR(x, n) x: INTEGER type of x x rotated right by n bits
573 (570) FLOOR(x) REAL, LONGREAL INTEGER largest integer ? x
577 (]573..574[) LONG(x) REAL LONGREAL x
578 (]573..574[) SHORT(x) LONGREAL REAL x
587 (]581..582[) COPY(x, v) x: character array, string v := x
588 (]581..582[) v: character array
591 (]583..584[) ASSERT(b, n) BOOLEAN, INTEGER
592 (584) PACK(x, y) REAL; INTEGER pack x and y into x
593 (585) UNPK(x, y) REAL; INTEGER unpack x into x and y
594 (586) Procedures INC and DEC may have an explicit increment or decrement. It must be a constant. Also
595 (587) for INCL and EXCL, x must be a constant. The second parameter n of ASSERT is a value
596 (]587..588[) transmitted to the system as an abort parameter.
598 (588) The parameter y of PACK represents the exponent of x. PACK(x, y) is equivalent to x := x * 2 y .
599 (589) UNPK is the reverse operation of PACK. The resulting x is normalized, i.e. 1.0 <= x < 2.0.
]658..659[ (650)
3 Revision 1.10.2013
7 1. History and introduction
114 ABS ASR ASSERT BOOLEAN BYTE
115 CHAR CHR DEC EXCL FLOOR
117 LSL NEW ODD ORD PACK
118 REAL ROR SET UNPK
]118..119[ (119)
158 (159) BYTE the integers between 0 and 255
160 (161) The type BYTE is compatible with the type INTEGER, and vice-versa.
]160..161[ (162)
180 (182) associate from left to right. For example, x?y?z stands for (x?y)?z.
183 (185) SimpleExpression = ["+"|"?"] term {AddOperator term}.
184 (186) AddOperator = "+" | "?" | OR.
307 (309) ? difference
312 (314) The operators +, ?, *, and / apply to operands of numeric types. Both operands must be of the
313 (315) same type, which is also the type of the result. When used as unary operators, ? denotes sign
317 (319) x = q*y + r 0 <= r < y
321 (324) ? difference
350 (352) (i+j) * (i?j) (INTEGER)
352 (354) a[i+j] * a[i?j] (REAL)
355 (357) k IN {i .. j?1} (BOOLEAN)
439 (441) | 1: x := x ? y
495 (497) In addition to its formal parameters and locally declared objects, the objects declared globally are
496 (498) also visible in the procedure.
]496..497[ (499)
562 (565) ABS(x) x: numeric type type of x absolute value
563 (566) ODD(x) x: INTEGER BOOLEAN x MOD 2 = 1
564 (567) LEN(v) v: array INTEGER the length of v
565 (568) LSL(x, n) x, n: INTEGER INTEGER logical shift left, x * 2 n
566 (569) ASR(x, n) x, n: INTEGER INTEGER signed shift right, x DIV 2 n
567 (570) ROR(x, n) x, n: INTEGER INTEGER x rotated right by n bits
570 (573) FLOOR(x) REAL INTEGER truncation
]573..574[ (577)
]573..574[ (578)
]581..582[ (587)
]581..582[ (588)
]583..584[ (591)
584 (591) PACK(x, n) REAL; INTEGER pack x and n into x
585 (592) UNPK(x, n) REAL; INTEGER unpack x into x and n
586 (594) The function FLOOR(x) truncates x. Its fractional part is discarded.
587 (595) FLOOR(1.5) = 1 FLOOR(-1.5) = -2
]587..588[ (596)
588 (598) The parameter n of PACK represents the exponent of x. PACK(x, y) is equivalent to x := x * 2 y .
589 (599) UNPK is the reverse operation. The resulting x is normalized, such that 1.0 <= x < 2.0.
650 (]658..659[) COPY(src, dst, n) all INTEGER copy n consecutive words from src to dst
54 (]53..54[) unless it contains a scale factor with the letter D, in which case it is of type LONGREAL.
58 (57) ScaleFactor = ("E" | "D") ["+" | "–"] digit {digit}.
105 (104) In its declaration, an identifier in the global scope may be followed by an export mark (*) to indicate
106 (105) that it be exported from its declaring module. In this case, the identifier may be used in other
107 (106) modules, if they import the declaring module. The identifier is then prefixed by the identifier
121 (120) ConstantDeclaration = identdef "=" ConstExpression.
513 (512) value, which cannot be changed by assignment. However, if a value parameter is of a scalar type, it
570 (569) FLOOR(x) REAL INTEGER truncation
586 (585) The function FLOOR(x) truncates x. Its fractional part is discarded.
604 (603) an asterisk (export mark) in their declaration. Variables cannot be exported, with the exception of
605 (]603..604[) those of scalar types in read-only mode.
634 (632) definition. It is strongly recommended to restrict their use to specific low-level modules, as such
635 (633) modules are inherently non-portable and not "type-safe". However, they are easily recognized due
636 (634) to the identifier S YSTEM appearing in their import lists. The subsequent definitions are generally
637 (635) applicable. However, individual implementations may include in their module S YSTEM additional
638 (636) definitions that are particular to the specific, underlying computer. In the following, v stands for a
639 (637) variable, x, a, and n for expressions.
]639..640[ (638)
]639..640[ (639)
]639..640[ (640)
]650..651[ (652)
]650..651[ (653)
]650..651[ (654)
]650..651[ (655)
]650..651[ (656)
]650..651[ (657)
]650..651[ (658)
]650..651[ (659)
]650..651[ (660)
]650..651[ (661)
]650..651[ (662)
665 (677) ConstantDeclaration = identdef "=" ConstExpression.
]53..54[ (54)
58 (57) ScaleFactor = "E" ["+" | "–"] digit {digit}.
104 (105) In its declaration, an identifier in the module's scope may be followed by an export mark (*) to
105 (106) indicate that it be exported from its declaring module. In this case, the identifier may be used in
106 (107) other modules, if they import the declaring module. The identifier is then prefixed by the identifier
120 (121) ConstDeclaration = identdef "=" ConstExpression.
512 (513) value, which cannot be changed by assignment. However, if a value parameter is of a basic type, it
569 (570) FLOOR(x) REAL INTEGER round down
585 (586) The function FLOOR(x) yields the largest integer not greater than x.
603 (604) an asterisk (export mark) in their declaration. Variables are always exported in read-only mode.
]603..604[ (605)
632 (634) definition.
633 (635) There are two reasons for provoding facilites in Module S YSTEM ; (1) Their value is implementation-
634 (636) dependent, that is, it is not derivable from the language's definition, and (2) they may corrupt a
635 (637) system (e.g. PUT). It is strongly recommended to restrict their use to specific low-level modules, as
636 (638) such modules are inherently non-portable and not "type-safe". However, they are easily recognized
637 (639) due to the identifier S YSTEM appearing in the module's import lists. The subsequent definitions are
638 (]639..640[) generally applicable. However, individual implementations may include in their module S YSTEM
639 (]639..640[) additional definitions that are particular to the specific, underlying computer. In the following, v
640 (]639..640[) stands for a variable, x, a, and n for expressions.
652 (]650..651[) The following are additional procedures accepted by the compiler for the RISC processor:
653 (]650..651[) Function procedures:
654 (]650..651[) Name Argument types Result type Function
655 (]650..651[) VAL(T, n) scalar T identity
656 (]650..651[) ADC(m, n) INTEGER INTEGER add with carry C
657 (]650..651[) SBC(m, n) INTEGER INTEGER subtract with carry C
658 (]650..651[) UML(m, n) INTEGER INTEGER unsigned multiplication
659 (]650..651[) COND(n) INTEGER BOOLEAN IF Cond(8) THEN ...
660 (]650..651[) Proper procedures:
661 (]650..651[) Name Argument types Function
662 (]650..651[) LED(n) INTEGER display n on LEDs
677 (665) ConstDeclaration = identdef "=" ConstExpression.
3 Revision 1.10.2013
53 factor. The letter E is pronounced as "times ten to the power of". A real number is of type REAL.
158 SET the sets of integers between 0 and 31
502 DeclarationSequence = [CONST {ConstantDeclaration ";"}]
3 Revision 1.10.2013 / 10.3.2014
53 factor. The letter E is pronounced as "times ten to the power of".
158 SET the sets of integers between 0 and an implementation-dependent limit
502 DeclarationSequence = [CONST {ConstDeclaration ";"}]
]209..210[ (210)
]209..210[ (211)
210 (]209..210[) If a type P is defined as POINTER TO T, the identifier T can be declared textually following the
211 (]209..210[) declaration of P, but [if so] it must lie within the same scope.
3 Revision 1.10.2013 / 10.3.2014
430 executed whose case label list contains the obtained value. The case expression must be of type
431 INTEGER or CHAR, and all labels must be integers or single-character strings, respectively.
434 CaseLabelList = LabelRange {"," LabelRange}.
436 label = integer | string | ident.
]443..444[ (444)
]443..444[ (445)
]443..444[ (446)
]443..444[ (447)
]443..444[ (448)
]443..444[ (449)
]443..444[ (450)
]443..444[ (451)
]443..444[ (452)
]443..444[ (453)
]443..444[ (454)
]443..444[ (455)
]443..444[ (456)
]443..444[ (457)
]443..444[ (458)
]443..444[ (459)
]443..444[ (460)
]443..444[ (461)
3 Revision 1.10.2013 / 22.2.2015
430 executed whose case label list contains the obtained value. If the case expression is of type
431 INTEGER or CHAR, all labels must be integers or single-character strings, respectively.
434 CaseLabelList = LabelRange {"," LabelRange} | qualident.
436 label = integer | string.
444 (]443..444[) The type T of the case expression (case variable) may also be a record or pointer type. Then the
445 (]443..444[) case labels must be extensions of T, and in the statements Si labelled by Ti, the case variable is
446 (]443..444[) considered as of type Ti.
447 (]443..444[) Example:
448 (]443..444[) TYPE R = RECORD a: INTEGER END ;
449 (]443..444[) R0 = RECORD (R) b: INTEGER END ;
450 (]443..444[) R1 = RECORD (R) b: REAL END ;
451 (]443..444[) R2 = RECORD (R) b: SET END ;
452 (]443..444[) P = POINTER TO R;
453 (]443..444[) P0 = POINTER TO R0;
454 (]443..444[) P1 = POINTER TO R1;
455 (]443..444[) P2 = POINTER TO R2;
456 (]443..444[) VAR p: P; p0: P0; p1: P1; p2: P2;
457 (]443..444[) CASE p OF
458 (]443..444[) P0: p0.b := 10 |
459 (]443..444[) P1: p1.b := 2.5 |
460 (]443..444[) P2: p2.b := {0, 2}
461 (]443..444[) END
Правильно ли я понимаю, что отрицательные числа в Обероне не включены в определение number?Что мешает внести нужные изменения в лексику?
Обратите внимание на SimpleExpression. То есть знак минус рассматривается не как часть отрицательного числа, а как математическая операция над неотрицательным числом?!
integer = (digit {digit} | digit {hexDigit} "H") ["M"].
real = digit {digit} "P" {digit} ["M"] [scaleFactor].
scaleFactor = ("E" | "D") digit {digit} ["M"].
number = integer | real.
NEW(C, n, n);
For1(1, n);
Здесь, в варианте функции с FOR процедурами, у меня ошибка. NEW(C, n, n);
For1(0, n - 1);
Да!В результате замены операторов FOR на процедуры получим:Для меня это выглядит как искусственное дробление единого контекста. И это все ради пространств имен и прочей методологии?
Потому что в паскалях так принято.А почему нет?А заводить переменную цикла тут же в FOR будет не проще, не?Будет методологически неправильней. Почему в операторном теле процедуры должны быть какие-то декларации?
Любые переменные в паскалях объявляются, то есть имеют декларативную нагрузку. Но дело здесь не в этом, счетчик FOR тоже объявляется, в самом FOR или вне его. Локальные переменные объявляются во вложенной (локальной) области видимости, но тоже в ее декларативной части. Не следует объявлять идентификаторы в операторах.В паскалевских ЯП декларативная область отделена от операторной. Иначе мы получим язык Дейкстры, где у каждого вызываемого оператора свое пространство имен. Операторы не должны вводить новых сущностей или менять свойства уже существующих, их дело работать с тем что уже есть.Почему? Особенно если речь идет о локальных переменных. Которые по сути своей - регистры для временных значений, не несущие никакой декларативной нагрузки.
Сущность в данном случае, это идентификатор-счетчик который в операторе FOR либо вводиться, либо меняется с var на read only.А если в теле процедуры в одном месте действуют одни сущности, в другом другие, или одна и та же используется с разным смыслом в разных местах, то это основание, чтобы вывести такие участки в подпроцедуры.Не-не. Не передергивай. С сущностями все хорошо
они одни и те же и с одним смыслом.А какой смысл имеет счетчик вне FOR? Либо никакого, либо использется для других целей.
Речь идет лишь о пространстве имен отдельного оператора - почему это плохо я не понял.Потому что в паскалях не принято делать пространства имен для отдельного (вызова) оператора. Все объявления идут перед началом операторного тела процедуры, модуля или программы.
[19:38:03] <vlad2> Мне кажется товарищ ddn из лагеря драконоидов...Почему драконоид? Я обычный паскалист.
[19:39:29] <vlad2> Вот я помню в универе писал вычисление детерминанта и не помню, чтоб там было 5 вложенных циклов...И еще два WHILE. Эту функцию за 10 минут я переписал с ее версии под Мапл. Там нет 5 вложенных друг в друга FOR. Там две пары FOR, где в каждой паре FORы вложены.
[19:47:02] <alexey.veselovsky> не, ну ведь он говорит наоборот - плохо если FOR меняет область видимостиИ это ошибочая реализация логики FOR оператора. Что останется от специфики FOR, если в его теле значение счетчика будет коверкаться как угодно? Но модифицировать область видимости, вводя локальную IN-переменную или запрещая меняться внешней (по отношению к FOR) переменной, тоже нельзя, это нарушение паскалевской методологии. Значит или переводить FOR в процедурную форму, или полностью изгнать с позором этот рассадник греха и порока из райских кущь Оберона.
[19:47:08] <alexey.veselovsky> а он, в Обероне, НЕ МЕНЯЕТ!
А синтез для Xilinx кто делать будет? Компилятора не достаточно.Какого компилятора? Который оберон-текст переводит в команды FPGA? Так эта Lola вроде другое делает: логическое описание схемы она переводит в непосредственный рисунок для литографии, или в прямые команды для литографической машины, или что там у них. То есть тоже что делает Verilog.
А лучше родного софта под данный конкретный кристалл никто не сделает.Какого софта? Если под конкретный кристалл, то значит кристалл на котором уже сформирована схема, тогда это микрокод, компилятор. Разве Xilinx вообще пишет компиляторы под Обероны?
А можно пример (кода) того, что получится в итоге?Вот например функция, вычисляющая детерминант матрицы:
PROCEDURE Det (IN A: ARRAY OF ARRAY OF REAL; (*IN*) n: INTEGER): REAL;
VAR
b: POINTER TO ARRAY OF BOOLEAN;
C: POINTER TO ARRAY OF ARRAY OF REAL;
d: REAL;
i, j, k, l: INTEGER;
BEGIN
ASSERT((LEN(A, 0) <= n) & (LEN(A, 1) <= n));
NEW(b, n); (* b[i] = FALSE *)
NEW(C, n, n);
FOR i := 0 TO n - 1 DO
FOR j := 0 TO n - 1 DO
C[i, j] := A[i, j]
END
END;
d := 1;
j := 0;
WHILE j < n DO
i := 0;
WHILE (i < n) & (b[i] OR (C[i, j] = 0)) DO
i := i + 1
END;
IF i = n THEN (* EXITIF.EXITWHILE *)
d := 0;
j := n - 1
ELSE (* ~b[i] & (C[i, j] # 0) *)
d := d * C[i, j];
(* C b j l *)
(* i: FALSE C[i, j] C[i, l] *)
(* k: FALSE C[k, j] C[k, l] *)
b[i] := TRUE;
FOR k := 0 TO n - 1 DO
IF ~b[k] THEN
FOR l := j + 1 TO n - 1 DO
C[k, l] := C[k, l] - C[k, j] * C[i, l] / C[i, j]
END
END
END;
FOR k := i + 1 TO n - 1 DO
IF ~b[k] THEN
C[k, j] := 0
END
END
(* C b j l *)
(* i: TRUE C[i, j] C[i, l] *)
(* k: FALSE 0 C[k, l] - C[k, j] * C[i, l] / C[i, j] *)
END;
INC(j)
END;
C := NIL;
b := NIL
;RETURN
d
END Det;
В ней 5 операторов FOR, причем две пары вложенных.MODULE det;
IMPORT StdLog;
VAR a: ARRAY 2 OF ARRAY 2 OF REAL;
...
BEGIN
a[0, 0] := 3; a[0, 1] := 7;
a[1, 0] := 5; a[1, 1] := 11;
StdLog.Real(Det(a, 2)); (* -2.0 *)
a[0, 0] := 5; a[0, 1] := 5;
a[1, 0] := 9; a[1, 1] := 9;
StdLog.Real(Det(a, 2)) (* 0.0 *)
END det.
PROCEDURE Det (IN A: ARRAY OF ARRAY OF REAL; (*IN*) n: INTEGER): REAL;
VAR
b: POINTER TO ARRAY OF BOOLEAN;
C: POINTER TO ARRAY OF ARRAY OF REAL;
d: REAL;
i, j: INTEGER;
PROCEDURE For1 FOR i : INTEGER;
PROCEDURE For4 FOR j : INTEGER DO
C[i, j] := A[i, j]
END
DO
For4(0, n - 1)
END;
(* FOR i := 0 TO n - 1 DO
FOR j := 0 TO n - 1 DO
C[i, j] := A[i, j]
END
END;
For1(0, n - 1); *)
PROCEDURE For2 FOR k : INTEGER;
PROCEDURE For5 FOR l : INTEGER DO
C[k, l] := C[k, l] - C[k, j] * C[i, l] / C[i, j]
END
DO
IF ~b[k] THEN
For5(j + 1, n - 1)
END
END;
(* FOR k := 0 TO n - 1 DO
IF ~b[k] THEN
FOR l := j + 1 TO n - 1 DO
C[k, l] := C[k, l] - C[k, j] * C[i, l] / C[i, j]
END
END
END;
For2(0, n - 1); *)
PROCEDURE For3 FOR k : INTEGER DO
IF ~b[k] THEN
C[k, j] := 0
END
END;
(* FOR k := i + 1 TO n - 1 DO
IF ~b[k] THEN
C[k, j] := 0
END
END;
For3(i + 1, n - 1); *)
BEGIN
ASSERT((LEN(A, 0) <= n) & (LEN(A, 1) <= n));
NEW(b, n); (* b[i] = FALSE *)
NEW(C, n, n);
For1(1, n);
d := 1;
j := 0;
WHILE j < n DO
i := 0;
WHILE (i < n) & (b[i] OR (C[i, j] = 0)) DO
i := i + 1
END;
IF i = n THEN (* EXITIF.EXITWHILE *)
d := 0;
j := n - 1
ELSE (* ~b[i] & (C[i, j] # 0) *)
d := d * C[i, j];
(* C b j l *)
(* i: FALSE C[i, j] C[i, l] *)
(* k: FALSE C[k, j] C[k, l] *)
b[i] := TRUE;
For2(0, n - 1);
For3(i + 1, n - 1)
(* C b j l *)
(* i: TRUE C[i, j] C[i, l] *)
(* k: FALSE 0 C[k, l] - C[k, j] * C[i, l] / C[i, j] *)
END;
INC(j)
END;
C := NIL;
b := NIL
RETURN
d
END Det;
Если это покажется слишком сложным или трудным для восприятия, то FOR нужно выпилить вообще. Либо так, либо никак.А заводить переменную цикла тут же в FOR будет не проще, не?Будет методологически неправильней. Почему в операторном теле процедуры должны быть какие-то декларации?