Oberon space

General Category => Общий раздел => Тема начата: Geniepro от Июль 04, 2013, 08:58:57 pm

Название: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 04, 2013, 08:58:57 pm
"Man or boy?" Donald Knuth (http://www.chilton-computing.org.uk/acl/applications/algol/p006.htm)

http://rosettacode.org/wiki/Man_or_boy_test

Попробовал решение для онлайн-компилятора Оберона-7:
MODULE test;
IMPORT JS;

TYPE Function = PROCEDURE ():INTEGER;

PROCEDURE F0():  INTEGER; BEGIN RETURN  0 END F0;
PROCEDURE F1():  INTEGER; BEGIN RETURN  1 END F1;
PROCEDURE Fn1(): INTEGER; BEGIN RETURN -1 END Fn1;

PROCEDURE A(ink: INTEGER; x1, x2, x3, x4, x5: Function): INTEGER;
VAR
  res : INTEGER;
  k   : INTEGER;

  PROCEDURE B(): INTEGER;
  BEGIN
    DEC(k);
    RETURN A(k, B, x1, x2, x3, x4)
  END B;

BEGIN
  k := ink;
  IF k <= 0 THEN
    res := x4() + x5();
  ELSE
    res := B();
  END;
  RETURN res
END A;

BEGIN
    JS.alert(A(10, F1, Fn1, Fn1, F1, F0))
END test.

а он мне раз и заявил: "Нельзя, мол, ссылаться на локальную процедуру"!
Компилятор от akron1 с ним солидарен...

Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?
Если есть, значит для Оберона-7 нельзя сделать "взрослый" компилятор (Man)? Язык вынуждает компиляторы быть "детскими" (Boy)?

ЗЫ. Ну и моё решение для хацкеля (зря что ли его делал):
import Data.IORef
import Control.Monad

main = do
    k <- newIORef 10
    print =<< a k (return 1) (return (-1)) (return (-1)) (return 1) (return 0)

a in_k x1 x2 x3 x4 x5 = do
    k <- newIORef =<< readIORef in_k
    let b = do
            k `modifyIORef` (\x -> x-1)
            a k b x1 x2 x3 x4

    k' <- readIORef k
    if k' <= 0 then liftM2 (+) x4 x5 else b
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 04, 2013, 09:04:54 pm
Есть такое ограничение:
Цитировать
6.5. Procedure types
Variables of a procedure type T have a procedure (or NIL) as value. If a procedure P is assigned to
a procedure variable of type T, the (types of the) formal parameters of P must be the same as those
indicated in the formal parameters of T. The same holds for the result type in the case of a function
procedure (see 10.1). P must not be declared local to another procedure, and neither can it be a
standard procedure.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 05, 2013, 03:18:41 pm
Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?

Оно всегда так было в паскалях. Типа - скажи нет скрытой неэффективности. Не говоря об усложнении компилятора :) В общем случае связанный с локальной процедурой контекст (локальные переменные) надо где-то хранить (в куче). Кроме того, есть еще VAR-параметры... Короче не работает это для оберонов.

P.S. Хотя с точки зрения транслятора в жабаскрипт никаких проблем нет, т.е. это чисто искусственное ограничение, чтобы остаться верным букве репорта.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 05, 2013, 04:13:05 pm
Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?

Оно всегда так было в паскалях. Типа - скажи нет скрытой неэффективности. Не говоря об усложнении компилятора :) В общем случае связанный с локальной процедурой контекст (локальные переменные) надо где-то хранить (в куче). Кроме того, есть еще VAR-параметры... Короче не работает это для оберонов.

При этом в Модуле-3 это работает...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 05, 2013, 05:00:23 pm
Думаю обсуждение пойдет бодрее, если ты сформулируешь задачу на русском.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 05, 2013, 05:14:19 pm
Думаю обсуждение пойдет бодрее, если ты сформулируешь задачу на русском.

На русском она описана тут: "О распределении памяти при выполнении теста Кнута" (http://rsdn.ru/article/pl1/PL1ex7/pl1ex7.xml)

Там суть в том, что бы вызвать взаимную рекурсию двух процедур, одна из которых является локальной для другой и имеет доступ к объемлющему контексту текущего вызова (замыкание с мутабельной переменной).
При этом уже на небольших параметрах происходит большая нагрузка на стек...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 05, 2013, 05:27:50 pm
Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?

P.S. Хотя с точки зрения транслятора в жабаскрипт никаких проблем нет, т.е. это чисто искусственное ограничение, чтобы остаться верным букве репорта.

А может стоит убрать это ограничение? Ведь данный транслятор не предназначен для генерации кода для мелкоконтроллеров, и в нём оно не имеет особого смысла...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 05, 2013, 06:33:51 pm
Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?

P.S. Хотя с точки зрения транслятора в жабаскрипт никаких проблем нет, т.е. это чисто искусственное ограничение, чтобы остаться верным букве репорта.

А может стоит убрать это ограничение? Ведь данный транслятор не предназначен для генерации кода для мелкоконтроллеров, и в нём оно не имеет особого смысла...
Это нарушит совместимость и создаст еще один диалект. Кроме того, современный Оберон, как и раньше, позиционируется как язык общего назначения, а не только для микроконтроллеров
.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 05, 2013, 06:37:06 pm
Я что-то запямятовал -- в Обероне-7 действительно есть такое ограничение?

P.S. Хотя с точки зрения транслятора в жабаскрипт никаких проблем нет, т.е. это чисто искусственное ограничение, чтобы остаться верным букве репорта.

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

Это нарушит совместимость и создаст еще один диалект. Кроме того, современный Оберон, как и раньше, позиционируется как язык общего назначения, а не только для микроконтроллеров .

Да кому нужна эта совместимость оберонов при таком неполном их описании?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 05, 2013, 06:40:44 pm
Нам нужен. Что бы наши компиляторы были совместимы хотя бы на базовом уровне.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 12:00:52 pm
Нам нужен. Что бы наши компиляторы были совместимы хотя бы на базовом уровне.

Ты рассуждаешь как схоласт, а не как истинный оберонщик, последователь Вирта.
Ведь что говорят оберонщики: "Вот вам минимальное языковое ядро, для своей задачи расширяйте его как хотите..."
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 06, 2013, 12:27:25 pm

Ведь что говорят оберонщики: "Вот вам минимальное языковое ядро, для своей задачи расширяйте его как хотите..."
полный п..ж они говорят.. "Вот вам минимальное языковое ядро... и на все ваши задачи его вполне хватит"
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Valery Solovey от Июль 06, 2013, 12:34:21 pm
Попробовал решение для онлайн-компилятора Оберона-7:
...
а он мне раз и заявил: "Нельзя, мол, ссылаться на локальную процедуру"
Может, получится выкрутиться средствами модуля JS?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 12:54:39 pm
Попробовал решение для онлайн-компилятора Оберона-7:
...
а он мне раз и заявил: "Нельзя, мол, ссылаться на локальную процедуру"
Может, получится выкрутиться средствами модуля JS?

Проще уж сразу на JS сделать. На JS тут проблемы не возникает:
var JS = function(){return this;}();
var test = function (){

function F0(){
return 0;
}

function F1(){
return 1;
}

function Fn1(){
return -1;
}

function A(ink/*INTEGER*/, x1/*Function*/, x2/*Function*/, x3/*Function*/, x4/*Function*/, x5/*Function*/){
var res = 0;
var k = 0;

function B(){
--k;
return A(k, B, x1, x2, x3, x4);
}
k = ink;
if (k <= 0){
res = x4() + x5();
}
else {
res = B();
}
return res;
}
JS.alert(A(10, F1, Fn1, Fn1, F1, F0));
}();
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 06, 2013, 01:46:56 pm
Ты рассуждаешь как схоласт, а не как истинный оберонщик, последователь Вирта.
Ведь что говорят оберонщики: "Вот вам минимальное языковое ядро, для своей задачи расширяйте его как хотите..."

Минимальное "расширение", которое практически не повлияет на эффективность (не требует GC и кучи) и на другие аспекты языка, а также сохранит пресловутую "герметичность", я представляю так:
- Вводится маркер для параметра процедуры (по аналогии с VAR), что этот параметр процедурного типа может быть локальной процедурой из процедуры выше по стеку. Например некий LOCAL:
PROCEDURE p(f: LOCAL PROCEDURE);
- Такая "LOCAL f" может быть только вызвана или передана в другую процедуру, но не может быть приведена к обычной процедурной переменной и не может быть передана по ссылке (VAR).
- Обычная процедурная переменная или процедура может быть передана как LOCAL (хотя можно сделать более интересно, но это отдельная тема).

Такое расширение позволит решить оригинальную задачу. Кроме того, можно попытаться написать хоть какую-нибудь библиотеку алгоритмов - тот же sort/find/for_each без тех ужасов, которые надо городить сейчас. И вообще появятся хоть какие-то зачатки функционального программирования в обероне. В оригинальном виде локальные процедуры в обероне имеют совсем мало смысла (не зря их Вирт собирается выпилить).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 06, 2013, 02:04:42 pm
Народ, сабжевая задача, мягко говоря, не является приоритетом.

До лепления расширений нужно сделать две вещи:
1) реализовать язык полностью.
2) написать уточненный репорт.

PS. Полагаю решить эту задачу на Оберон-07/11 можно. Вечером подумаю.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 02:59:15 pm
Задача Кнута показывает, что Оберон-07, вроде бы продолжающий алголовскую традицию языков, является тем не менее "детским" (Boy) языком, и это при том что уже в 60-х гг. прошлого века были "взрослые" (Man) реализации Алгола-60...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 06, 2013, 04:01:46 pm
Код из первого поста в А2 отработал 11 раз (каждая процедура) и трапнулся с access violation
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 04:20:06 pm
Код из первого поста в А2 отработал 11 раз (каждая процедура) и трапнулся с access violation

Не совсем понял, что это значит, но там явно что-то не то в А2.
Количество вызовов процедуры А должно быть равно 722 раз, результат = -67.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 06, 2013, 05:01:39 pm
ну что происходит - при вызове A из B происходит реальный вызов A
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 05:12:51 pm
ну что происходит - при вызове A из B происходит реальный вызов A

А версия контекста процедуры А при этом какая? Новая для каждого вызова В или одна общая для всех вызовов А?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 06, 2013, 05:15:51 pm
Я взял из статьи код для М3, адаптировал для запуска в А2, и у меня получился совсем другой результат, чем при использовании кода из первого поста.
результат - stack overflow
проверь таки код
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 05:33:29 pm
Я взял из статьи код для М3, адаптировал для запуска в А2, и у меня получился совсем другой результат, чем при использовании кода из первого поста.
результат - stack overflow
проверь таки код

Какой код проверить? Мой Обероновский (переделанный из варианта для Модулы-3 из той статьи на http://rosettacode.org/wiki/Man_or_boy_test#Modula-3 (http://rosettacode.org/wiki/Man_or_boy_test#Modula-3))? Так он невалиден для Оберона-07.

Я приводил код на JS http://oberspace.dyndns.org/index.php/topic,518.msg17329.html#msg17329 (http://oberspace.dyndns.org/index.php/topic,518.msg17329.html#msg17329), который я получил с помощью небольшого трюка Владовским онлайн-компилятором -- его результат совпал с результатом моего варианта на хаскелле и кучей других вариантов этого теста.

Приведи свой код для A2, посмотрим, в чём отличия...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 06, 2013, 07:45:33 pm
Если есть, значит для Оберона-7 нельзя сделать "взрослый" компилятор (Man)? Язык вынуждает компиляторы быть "детскими" (Boy)?
Вопрос поставлен не корректно. Man or Boy - это про реализации Алгола-60. По сути, это тест на корректность реализации того языка. А конкретно - проверка на вполне конкретную его фенечку.

Собственно ни Man ни Boy компилятор Оберона быть не может.

Про что тест, и в чем его соль, хорошо описано в Вики: http://en.wikipedia.org/wiki/Man_or_boy_test

Собственно реализовать то что там есть, можно хоть на Обероне-07/11 хоть на Си. Проблем не вижу. Но, еще раз, тест не про это. Тест про корректность компилятора Алгола-60.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 06, 2013, 09:04:17 pm
Собственно реализовать то что там есть, можно хоть на Обероне-07/11 хоть на Си. Проблем не вижу. Но, еще раз, тест не про это. Тест про корректность компилятора Алгола-60.

Не могу согласиться. Да, в те годы у Кнута выбор был небольшой, поэтому он и ограничился Алголом. Однако это не значит, что нельзя использовать этот тест для оценки реализаций других языков, имеющих необходимые для этого теста средства -- передачу процедур (в том числе локальных) как параметры с сохранением их контекста.
Другое дело, что Оберон-07 (а также Компонентный Паскаль) такой возможности не имеет, поэтому для него этот тест не имеет смысла...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 07, 2013, 04:33:25 am
ну что происходит - при вызове A из B происходит реальный вызов A

А версия контекста процедуры А при этом какая? Новая для каждого вызова В или одна общая для всех вызовов А?
Вложенная процедура B - логически является частью процедуры А, поэтому при вызове B используется общий фрейм с А. Вызовы А из А являются рекурсивными, при этом создаётся новый фрейм, а так как B это составная часть A, то вызов A из B тоже рекурсивен, и иное было бы странно.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 07, 2013, 06:05:17 am
Подумал над задачкой. Самое смешное, что на Обероне (Oberon/Oberon-07/Oberon-2/CP) похоже не удастся обойтись без использования динамической памяти (кучи), стека не достаточно. Ведь в Обероне нельзя получить указатель на переменную, что на стеке. Поэтому решение в стиле Си не прокатит.

Ну, или использовать SYSTEM, но в случае как минимум Oberon-07/11 наличие SYSTEM'а не гарантировано.

Так что NEW в зубы и руками городить рядом с нормальным стеком, стек своих фреймов, в куче.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 07, 2013, 07:44:56 am
Какой код проверить? Мой Обероновский (переделанный из варианта для Модулы-3 из той статьи на http://rosettacode.org/wiki/Man_or_boy_test#Modula-3 (http://rosettacode.org/wiki/Man_or_boy_test#Modula-3))? Так он невалиден для Оберона-07.
Вариант с локальной переменной не идентичен варианту М3.
Приведи свой код для A2, посмотрим, в чём отличия...
Он полностью соответствует коду М3 (за исключением исправленного синтаксиса, замены INTEGER->LONGINT и наличия счетчиков
MODULE TestM;
IMPORT Commands;

TYPE Function = PROCEDURE ():LONGINT;

VAR ACount, BCount : LONGINT;

PROCEDURE A(k: LONGINT; x1, x2, x3, x4, x5: Function): LONGINT ;
  PROCEDURE B(): LONGINT ;
  BEGIN
    INC(BCount);
    DEC(k);
    RETURN A(k, B, x1, x2, x3, x4);
  END B;

BEGIN
  INC(ACount);
  IF k <= 0 THEN
    RETURN x4() + x5();
  ELSE
    RETURN B();
  END;
END A;

PROCEDURE F0(): LONGINT ; BEGIN RETURN 0; END F0;
PROCEDURE F1(): LONGINT ; BEGIN RETURN 1; END F1;
PROCEDURE Fn1(): LONGINT ; BEGIN RETURN -1; END Fn1;

 PROCEDURE Do*( context : Commands.Context );
 VAR nums : LONGINT;
 BEGIN
  ACount := 0; BCount := 0;
  IF context.arg.GetInteger( nums, FALSE ) THEN
(*    context.out.Int( A(nums, F1, Fn1, Fn1, F1, F0), 10 );*)
    TRACE(A(nums, F1, Fn1, Fn1, F1, F0), ACount, BCount)
  END;
 END Do;

 PROCEDURE ShowCounts*;
 BEGIN
  TRACE(ACount, BCount);
 END ShowCounts;
 
BEGIN

END TestM.

SystemTools.Free TestM ~

TestM.Do 0 ~

TestM.ShowCounts ~
Максимальное значение параметра, при котором оно работает( и выдаёт результаты идентичные контрольной таблице) - 3, больше - трап от переполнения стека активности (потока).

PS: TRACE выводит результат в KernelLog
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 07, 2013, 08:28:45 am
Чуть изменил процедуру запуска теста - теперь принимается список параметров:
PROCEDURE Do*( context : Commands.Context );
 VAR nums : LONGINT;
 BEGIN
  WHILE context.arg.GetInteger( nums, FALSE ) DO
    ACount := 0; BCount := 0;
    TRACE(A(nums, F1, Fn1, Fn1, F1, F0), ACount, BCount)
  END;
 END Do;
Соответственно, коммандер теперь выглядит так:

TestM.Do 0 1 2 3 ~
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 07, 2013, 12:00:53 pm
Вариант с локальной переменной не идентичен варианту М3.

С этой локальной переменной компиляторо- (или языково-) зависимые сложности -- где-то параметр k передаётся по ссылке, и тогда нужно заводить её локальную копию, где-то по значению, и тогда этого не нужно делать, а в Аде, например, она не изменяемая и поэтому опять нужно заводить её копию...

Попробуй всё же вот так:
PROCEDURE A(ink: LONGINT; x1, x2, x3, x4, x5: Function): LONGINT ;
  VAR k: LONGINT;

  PROCEDURE B(): LONGINT ;
  BEGIN
    INC(BCount);
    DEC(k);
    RETURN A(k, B, x1, x2, x3, x4);
  END B;

BEGIN
  INC(ACount);
  k := ink;
  IF k <= 0 THEN
    RETURN x4() + x5();
  ELSE
    RETURN B();
  END;
END A;
Таблица результатов:
A( 1, 1, -1, -1, 1, 0) =       0
A( 2, 1, -1, -1, 1, 0) =      -2
A( 3, 1, -1, -1, 1, 0) =       0
A( 4, 1, -1, -1, 1, 0) =       1
A( 5, 1, -1, -1, 1, 0) =       0
A( 6, 1, -1, -1, 1, 0) =       1
A( 7, 1, -1, -1, 1, 0) =      -1
A( 8, 1, -1, -1, 1, 0) =     -10
A( 9, 1, -1, -1, 1, 0) =     -30
A(10, 1, -1, -1, 1, 0) =     -67
A(11, 1, -1, -1, 1, 0) =    -138
A(12, 1, -1, -1, 1, 0) =    -291
A(13, 1, -1, -1, 1, 0) =    -642
A(14, 1, -1, -1, 1, 0) =   -1446
A(15, 1, -1, -1, 1, 0) =   -3250
A(16, 1, -1, -1, 1, 0) =   -7244
A(17, 1, -1, -1, 1, 0) =  -16065
A(18, 1, -1, -1, 1, 0) =  -35601
A(19, 1, -1, -1, 1, 0) =  -78985
A(20, 1, -1, -1, 1, 0) = -175416
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 07, 2013, 12:20:24 pm
Попробуй всё же вот так:
Результат тот же - при параметре больше 3-х трап по переполнению стека активности (в нативе стек активности 128К, в WinAos - по умолчанию для CreateThread).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 07, 2013, 01:23:41 pm
Попробуй всё же вот так:
Результат тот же - при параметре больше 3-х трап по переполнению стека активности (в нативе стек активности 128К, в WinAos - по умолчанию для CreateThread).

Странно, при k = 4 происходит всего 8 вызовов A и 7 вызовов B -- как может стек переполниться???
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 07, 2013, 07:22:10 pm
Подумал над задачкой. Самое смешное, что на Обероне (Oberon/Oberon-07/Oberon-2/CP) похоже не удастся обойтись без использования динамической памяти (кучи), стека не достаточно.

Да, я чего-то тоже не могу придумать как такое на обероне07 без NEW сделать...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 07, 2013, 07:27:36 pm
Подумал над задачкой. Самое смешное, что на Обероне (Oberon/Oberon-07/Oberon-2/CP) похоже не удастся обойтись без использования динамической памяти (кучи), стека не достаточно.

Да, я чего-то тоже не могу придумать как такое на обероне07 без NEW сделать...
Да и на КП тоже. На всей линейке "классических" оберонов.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Илья Ермаков от Июль 08, 2013, 07:33:53 am
а он мне раз и заявил: "Нельзя, мол, ссылаться на локальную процедуру"!
Компилятор от akron1 с ним солидарен...

Совершенно правильное ограничение.... дабы отсекать сами попытки ваять такую замудрённую и двусмысленную чушь, как протаскивание контекстов процедур и т.п.
В том же JS "эти ваши замыкания" используются направо и налево от отсутствия модульности и удобного "не-ассемблерного" ООП (как и в ФП их главная роль - быть альтернативой ООП).
Я в JS сначала поигрался с замыканиями, когда обнаружил, что для удержания этого клубка в голове и его объяснения кому-то нужны дополнительные усилия, послал их в..., кроме совсем ограниченных случаев, типа обработки событий и т.п.

Хочется таскать контекст - задекларируй явно объект для этого контекста, как тип данных, - и таскай...
Неявщину, умолчания, запутанные клубки связей - в.... топку :)





Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 08, 2013, 07:48:44 am
а он мне раз и заявил: "Нельзя, мол, ссылаться на локальную процедуру"!
Компилятор от akron1 с ним солидарен...

Совершенно правильное ограничение.... дабы отсекать сами попытки ваять такую замудрённую и двусмысленную чушь, как протаскивание контекстов процедур и т.п.
В том же JS "эти ваши замыкания" используются направо и налево от отсутствия модульности и удобного "не-ассемблерного" ООП (как и в ФП их главная роль - быть альтернативой ООП).
Я в JS сначала поигрался с замыканиями, когда обнаружил, что для удержания этого клубка в голове и его объяснения кому-то нужны дополнительные усилия, послал их в..., кроме совсем ограниченных случаев, типа обработки событий и т.п.

Хочется таскать контекст - задекларируй явно объект для этого контекста, как тип данных, - и таскай...
Неявщину, умолчания, запутанные клубки связей - в.... топку :)

Ну, если в качестве эталона языка для использования замыканий брать js, то действительно, замыкания - богомерзкая дрянь :-) (впрочем, это к любой концепции относится - динамическая типизация, синтаксис, сборщик мусора, прототипное наследование - что ни рассматривай на примере js, всё дрянью покажется) А вот если брать что-то более вменяемое, ну там haskell например, то становится очевидно что это классная штука, которая делает код яснее, и не столь запутанным, как в случае ОО-языков.

И нет, у замыканий роль не в "замене" ООП. Программирование не крутится вокруг объектной методологии.

PS. А модульность вооще тут ортогональна. Замыкание контекста штука динамическая, а модуль штука статическая.

PPS. А ООП в Обероне, таки ассемблерного типа.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 07:57:02 am
Странно, при k = 4 происходит всего 8 вызовов A и 7 вызовов B -- как может стек переполниться???
Нет, оказывается результаты моего варианта и твоего несколько отличаются:
Если взять к = 100,
то в твоём варианте:
ink = 0
k = 0
A called = 101
B called = 101
результат - TRAP access violation.

В моём же варианте:
k=94200383
A called=23547
B called=23547
и результат - TRAP stack overflow

в диапазоне 0..3 оба диапазона ведут себя одинаково и выдают правильные результаты.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 08, 2013, 10:33:17 am
Странно, при k = 4 происходит всего 8 вызовов A и 7 вызовов B -- как может стек переполниться???
Нет, оказывается результаты моего варианта и твоего несколько отличаются:
Если взять к = 100,
то в твоём варианте:
ink = 0
k = 0
A called = 101
B called = 101
результат - TRAP access violation.

В моём же варианте:
k=94200383
A called=23547
B called=23547
и результат - TRAP stack overflow

в диапазоне 0..3 оба диапазона ведут себя одинаково и выдают правильные результаты.

Боюсь, для того что бы процедура A выполнилась при k = 100, не хватит времени существования вселенной, ну и памяти тоже. Теоретический предел на 32-битной архитектуре -- k = 32, практический предел на этой архитектуре -- что-то около k = 27... Для того, чтобы получить результат для k = 100, нужно уже делать мемоизацию процедуры A...

Что-то не то генерирует компилятор в A2...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 11:05:31 am
Что-то не то генерирует компилятор в A2...
Об этом и речь
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 08, 2013, 11:22:26 am
Что-то не то генерирует компилятор в A2...
Об этом и речь

А что там вообще сказано в описании активного оберона про передачу ссылок на локальные прцедуры? Если в репорте сказано что это нельзя, то надо бы им багрепорт отправить )

Вапще, скачал на днях эту A2, запустил -- и увидел пустой сиреневый экран, а по краям какие-то непонятные серые полоски... Так что я не удивлён, что компилятор что-то не то генерирует у них )))
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 08, 2013, 11:42:50 am
Хочется таскать контекст - задекларируй явно объект для этого контекста, как тип данных, - и таскай...
Неявщину, умолчания, запутанные клубки связей - в.... топку :)

Ага, ООП тоже вреден -- всякие хрупкие классы там, только для ГУИ годится, а для всего остального -- в топку...
И ваще назад в машкоды пора вернуться...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 12:32:14 pm
А что там вообще сказано в описании активного оберона про передачу ссылок на локальные прцедуры? Если в репорте сказано что это нельзя, то надо бы им багрепорт отправить )
Репорт давно устарел.
По трассировке вызовов видно, что при каждом вызове A стек опускается на 44 байта (стек для A - 32 байта и - 12 для B ), при вызове B адрес k для A и B одинаков(как и адреса всех параметров) и так продолжается до 5-го вызова B, после чего стек вдруг не минусуется на -12, а плюсуется +20, и всё, фрейм данных потерян, и дальше пошла полная фигня.
Вапще, скачал на днях эту A2, запустил -- и увидел пустой сиреневый экран, а по краям какие-то непонятные серые полоски... Так что я не удивлён, что компилятор что-то не то генерирует у них )))
у меня всё работает, загружается с флешки, никаких странных серых полосок нету. Но можешь WinAos попробовать.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 08, 2013, 12:36:45 pm
А что там вообще сказано в описании активного оберона про передачу ссылок на локальные прцедуры? Если в репорте сказано что это нельзя, то надо бы им багрепорт отправить )
Репорт давно устарел.
По трассировке вызовов видно, что при каждом вызове A стек опускается на 44 байта (стек для A - 32 байта и - 12 для B ), при вызове B адрес k для A и B одинаков(как и адреса всех параметров) и так продолжается до 5-го вызова B, после чего стек вдруг не минусуется на -12, а плюсуется +20, и всё, фрейм данных потерян, и дальше пошла полная фигня.
Вапще, скачал на днях эту A2, запустил -- и увидел пустой сиреневый экран, а по краям какие-то непонятные серые полоски... Так что я не удивлён, что компилятор что-то не то генерирует у них )))
у меня всё работает, загружается с флешки, никаких странных серых полосок нету. Но можешь WinAos попробовать.

Народ, правильно ли я понял, что сий замечательный тест Кнута позволил выявить странный баг в компиляторе АО? То есть тест оказался таки полезным для одного из потомков Алгола-60?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 08, 2013, 12:52:43 pm
Но можешь WinAos попробовать.
Я как раз WinAOS и пробовал...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 02:21:58 pm
Народ, правильно ли я понял, что сий замечательный тест Кнута позволил выявить странный баг в компиляторе АО? То есть тест оказался таки полезным для одного из потомков Алгола-60?
Пока неясно, может проблема связана с выравниванием в процессорах AMD, надо на интеле проверять
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 08, 2013, 02:24:40 pm
Народ, правильно ли я понял, что сий замечательный тест Кнута позволил выявить странный баг в компиляторе АО? То есть тест оказался таки полезным для одного из потомков Алгола-60?
Пока неясно, может проблема связана с выравниванием в процессорах AMD, надо на интеле проверять
Наврятли это баг процессора. Так что, опять таки, даже если это из за специфического выравнивания, то это баг компилятора.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 08, 2013, 03:49:00 pm
Совершенно правильное ограничение.... дабы отсекать сами попытки ваять такую замудрённую и двусмысленную чушь, как протаскивание контекстов процедур и т.п.

Ну будет у тебя оформлено замыкание в виде кошерного объекта (хотя я ни разу не согласен, что это всегда нагляднее). Конкретно данный алгоритм все равно требует NEW, потому что в обероне нельзя получить указатель/ссылку на локальную RECORD. Или я что-то пропустил? Вообще хотелось бы увидеть решение на обероне - у меня с наскоку не получилось - слишком много кода получается и страшно. Можно начать с решения для ББ, потому что в О7 с "оформлением в виде объекта" возникает ненужный мусор.

В том же JS "эти ваши замыкания" используются направо и налево от отсутствия модульности и удобного "не-ассемблерного" ООП

Ой, только не надо начинать про жабаскрипт...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 03:59:11 pm
Наврятли это баг процессора. Так что, опять таки, даже если это из за специфического выравнивания, то это баг компилятора.
Ну код-то не самомодифицирующийся ) он на протяжении всех 100 вызовов один и тот же и на всем протяжении стек опускается правильно - на 32 и 12 байт соответственно, и только на 5-м вызове B он вместо 12 байт опускается на 8 (и BP соответственно)
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 04:16:27 pm
вот как это выглядит:
TestMR@763 - процедура A
TestMR@497 - процедура B
TestMR@1652:currentSP= 67502080; (currentSP DIV 1024)= 65920;

TestMR@763:ADDRESSOF(k)= 0405FF38H; currentSP= 67501852; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FF38H; currentSP= 67501840; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FF0CH; currentSP= 67501808; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FF0CH; currentSP= 67501796; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FEE0H; currentSP= 67501764; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FEE0H; currentSP= 67501752; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FEB4H; currentSP= 67501720; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FEB4H; currentSP= 67501708; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FE88H; currentSP= 67501676; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FEA8H; currentSP= 67501668; (prevSP - currentSP)= 8;
TestMR@763:ADDRESSOF(k)= 0405FE60H; currentSP= 67501636; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FE60H; currentSP= 67501624; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FE34H; currentSP= 67501592; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FE34H; currentSP= 67501580; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FE08H; currentSP= 67501548; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FE08H; currentSP= 67501536; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FDDCH; currentSP= 67501504; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FDDCH; currentSP= 67501492; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FDB0H; currentSP= 67501460; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FDB0H; currentSP= 67501448; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FD84H; currentSP= 67501416; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FD84H; currentSP= 67501404; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FD58H; currentSP= 67501372; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FD58H; currentSP= 67501360; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FD2CH; currentSP= 67501328; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FD2CH; currentSP= 67501316; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FD00H; currentSP= 67501284; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FD00H; currentSP= 67501272; (prevSP - currentSP)= 12;
TestMR@763:ADDRESSOF(k)= 0405FCD4H; currentSP= 67501240; (prevSP - currentSP)= 32;
TestMR@497:ADDRESSOF(k)= 0405FCD4H; currentSP= 67501228; (prevSP - currentSP)= 12;
...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 04:59:52 pm
блин, тормоз, там, где стек опустился на 8-м - k стало равно 0, поэтому вызова B небыло.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 05:03:11 pm
ыыыы, целые в Оберонах = знаковые, вот тут она проблема и вылезла, твою мать
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 08, 2013, 05:21:09 pm
хотя, не, это я не подумавши
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Kemet от Июль 09, 2013, 05:24:53 pm
Но можешь WinAos попробовать.
Я как раз WinAOS и пробовал...
Перезалил полное дерево исходников А2 на на GitHub (https://github.com/metacore/A2OS). Это точно работает, ибо это одна из моих рабочих копий. Основана на ревизии 5348 (текущая 5355).
По сравнению с оригиналом поправлено 4 файла(поправлены сигнатуры нескольких процедур в UDP.Mod для синхронизации с изменениями интерфейса, в оригинале изменения внести видимо забыли, поправлен мелкий баг в FoxCompiler.Mod - перепутан порядок следования параметров, убрана зависимость от Streams в FATVolumes и заменен pci.ids на свежий). Эти изменения не затрагивают WinAos.
Ну и полностью пересобраны модули WinAos.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 10, 2013, 06:34:37 am
Итак, работающее решение на O7. Обратите внимание на приседание с дополнительной процедурной переменной pB - из-за невозможности предварительно задекларировать B. Может кто-нибудь предложит более элегантное решение, ибо текущее просто ужасно.
MODULE test;
IMPORT JS;

TYPE
    PState = POINTER TO State;
    Function = PROCEDURE(s: PState): INTEGER;
    State = RECORD
        f: Function;
        k: INTEGER;
        x1, x2, x3, x4, x5: PState
    END;

VAR
    pB: Function;
    init: PState;

PROCEDURE call(s: PState): INTEGER;
    RETURN s.f(s)
END call;

PROCEDURE makeEmptyState(f: Function): PState;
VAR
    result: PState;
BEGIN
    NEW(result);
    result.f := f;
    RETURN result
END makeEmptyState;

PROCEDURE makeState(f: Function; k: INTEGER; x1, x2, x3, x4, x5: PState): PState;
VAR
    result: PState;
BEGIN
    result := makeEmptyState(f);
    result.k := k;
    result.x1 := x1;
    result.x2 := x2;
    result.x3 := x3;
    result.x4 := x4;
    result.x5 := x5;
    RETURN result
END makeState;

PROCEDURE F0(s: PState):  INTEGER; BEGIN RETURN  0 END F0;
PROCEDURE F1(s: PState):  INTEGER; BEGIN RETURN  1 END F1;
PROCEDURE Fn1(s: PState): INTEGER; BEGIN RETURN -1 END Fn1;

PROCEDURE A(s: PState): INTEGER;
VAR
    res: INTEGER;
BEGIN
  IF s.k <= 0 THEN
    res := call(s.x4) + call(s.x5);
  ELSE
    res := call(makeState(pB, s.k, s.x1, s.x2, s.x3, s.x4, s.x5));
  END;
  RETURN res
END A;

PROCEDURE B(s: PState): INTEGER;
BEGIN
    DEC(s.k);
    RETURN call(makeState(A, s.k, s, s.x1, s.x2, s.x3, s.x4))
END B;

BEGIN
    pB := B;
    JS.alert(call(makeState(
        A,
        10,
        makeEmptyState(F1),
        makeEmptyState(Fn1),
        makeEmptyState(Fn1),
        makeEmptyState(F1),
        makeEmptyState(F0))))
END test.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 10, 2013, 07:56:52 am
Итак, работающее решение на O7. Обратите внимание на приседание с дополнительной процедурной переменной pB - из-за невозможности предварительно задекларировать B.

А что, Вирт убрал из Оберона forward declarations? о_О
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 10, 2013, 09:01:20 am
Итак, работающее решение на O7. Обратите внимание на приседание с дополнительной процедурной переменной pB - из-за невозможности предварительно задекларировать B.

А что, Вирт убрал из Оберона forward declarations? о_О
Да. Как лишнюю сущность, которая дублирует уже имеющиеся процедурные типы.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 10, 2013, 10:06:18 am
Итак, работающее решение на O7. Обратите внимание на приседание с дополнительной процедурной переменной pB - из-за невозможности предварительно задекларировать B.

А что, Вирт убрал из Оберона forward declarations? о_О
Да. Как лишнюю сущность, которая дублирует уже имеющиеся процедурные типы.

Я понимаю там в хаскелле/сишарпе forward declarations не нужны -- весь модуль/класс просматривается при поиске нужной процедуры, переменной или типа , но в обероне...
Жестокое упрощение языка...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 10, 2013, 10:48:58 am
Итак, работающее решение на O7. Обратите внимание на приседание с дополнительной процедурной переменной pB - из-за невозможности предварительно задекларировать B.

А что, Вирт убрал из Оберона forward declarations? о_О
Да. Как лишнюю сущность, которая дублирует уже имеющиеся процедурные типы.

Я понимаю там в хаскелле/сишарпе forward declarations не нужны -- весь модуль/класс просматривается при поиске нужной процедуры, переменной или типа , но в обероне...
Жестокое упрощение языка...
Дык лишняя сущность же!

Ну, на самом деле, если ослабить вот это требование: "The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local." до "whole block (procedure or module)", то получится язык поприятнее для кодописателя (и чуть менее приятный для компилятороклепателя, хотя и тут выигрыш таки в итоге будет, ибо компилятор железно перестает быть однопроходным).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 10, 2013, 01:17:45 pm
Да. Как лишнюю сущность, которая дублирует уже имеющиеся процедурные типы.

Лишняя сущность - это дополнительная переменная. Вобщем да, O7 это уже за гранью "но не проще".

P.S. Конечно же я ее забыл проинитить сначала.
P.S.S. Да, надо просто ослабить требование и искать во всем блоке.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 10, 2013, 04:54:05 pm
- Вводится маркер для параметра процедуры (по аналогии с VAR), что этот параметр процедурного типа может быть локальной процедурой из процедуры выше по стеку. Например некий LOCAL:

Можно расширить эту идею и на указатели. Т.е., локальная переменная может быть приведена к LOCAL POINTER TO с теми же ограничениями и совместимостями. Тогда оригинальная задача тоже быть решена без обращения к куче и GC.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 10, 2013, 05:19:56 pm
- Вводится маркер для параметра процедуры (по аналогии с VAR), что этот параметр процедурного типа может быть локальной процедурой из процедуры выше по стеку. Например некий LOCAL:

Можно расширить эту идею и на указатели. Т.е., локальная переменная может быть приведена к LOCAL POINTER TO с теми же ограничениями и совместимостями. Тогда оригинальная задача тоже быть решена без обращения к куче и GC.
Мне не кажется правильным менять (расширять) язык для решения искусственных задач. Ну, то есть, как минимум такие изменения не приоритетны.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: igor от Июль 10, 2013, 05:44:39 pm
Ну, на самом деле, если ослабить вот это требование: "The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local." до "whole block (procedure or module)", то получится язык поприятнее для кодописателя (и чуть менее приятный для компилятороклепателя, хотя и тут выигрыш таки в итоге будет, ибо компилятор железно перестает быть однопроходным).
Утверждение, что в этом случае "компилятор железно перестаёт быть однопроходным" не верно.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 10, 2013, 07:21:41 pm
Ну, на самом деле, если ослабить вот это требование: "The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local." до "whole block (procedure or module)", то получится язык поприятнее для кодописателя (и чуть менее приятный для компилятороклепателя, хотя и тут выигрыш таки в итоге будет, ибо компилятор железно перестает быть однопроходным).
Утверждение, что в этом случае "компилятор железно перестаёт быть однопроходным" не верно.
Да? А как? Вот у меня процедура Foo, которая использует другую процедуру которая определена где-то далеко внизу. Вопрос - как за один проход такое компилировать?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 10, 2013, 08:09:09 pm
Да? А как? Вот у меня процедура Foo, которая использует другую процедуру которая определена где-то далеко внизу. Вопрос - как за один проход такое компилировать?

Никак. Просто потому, что в общем случае нельзя "угадать" сигнатуру - оберон допускает неявные преобразования типов аргументов. Например f('A') может быть как вызовом "PROCEDURE f(c: CHAR)" так и "PROCEDURE(s: ARRAY OF CHAR)". Кроме того, передача VAR-аргументов тоже влияет на генерируемый код в точке вызова.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 10, 2013, 08:11:57 pm
Да? А как? Вот у меня процедура Foo, которая использует другую процедуру которая определена где-то далеко внизу. Вопрос - как за один проход такое компилировать?

Никак. Просто потому, что в общем случае нельзя "угадать" сигнатуру - оберон допускает неявные преобразования типов аргументов. Например f('A') может быть как вызовом "PROCEDURE f(c: CHAR)" так и "PROCEDURE(s: ARRAY OF CHAR)". Кроме того, передача VAR-аргументов тоже влияет на генерируемый код в точке вызова.
Нет, ну можно конечно, как в древних языках (том же алголе) сделать единицей компиляции не модуль, а функцию, и, соответственно, всю эту работу свалить на компоновщик. Но это как-то на подтасовку смахивает :-)
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: igor от Июль 11, 2013, 04:59:04 am
Утверждение, что в этом случае "компилятор железно перестаёт быть однопроходным" не верно.
Для сомневающихся хочу дать некоторые пояснения. Я использовал специальную структуру данных, которую назвал "буфер отложенных объявлений". Основная идея в упрощенном виде выглядит так. Парсер делает один проход по исходному тексту. Если парсер в операторной последовательности встречает неизвестный идентификатор, то он панику не разводит, а помещает этот идентификатор в буфер отложенных объявлений. Затем, если далее по тексту встречается объявление этого идентификатора, то парсер переносит его из буфера в таблицу имён. К тому моменту, когда будет достигнут конец модуля, буфер должен быть пуст, иначе ошибка. На самом деле всё несколько сложнее из-за вложенности областей видимости, но в моём случае (обероноподобный язык, но не Оберон) задача алгоритмически вполне решабельна (проверено на практике).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 11, 2013, 05:31:40 am
Ну и для полноты картины решение на С++. Решение "в лоб", без придумок, с использованием библиотечных замыканий:
#include <boost/bind.hpp>
#include <boost/function/function0.hpp>
#include <iostream>

typedef boost::function0<int> function_t;

int f0(){return 0;}
int f1(){return 1;}
int fn1(){return -1;}

int b(int& k,
      function_t const& x1,
      function_t const& x2,
      function_t const& x3,
      function_t const& x4);

int a(int k,
      function_t const& x1,
      function_t const& x2,
      function_t const& x3,
      function_t const& x4,
      function_t const& x5)
{
    return k <= 0 ? x4() + x5() : b(k, x1, x2, x3, x4);
}

int b(int& k,
      function_t const& x1,
      function_t const& x2,
      function_t const& x3,
      function_t const& x4)
{
    --k;
    return a(k,
             boost::bind(&b, boost::ref(k), x1, x2, x3, x4),
             x1,
             x2,
             x3,
             x4);
}

int main()
{
    std::cout << a(10, f1, fn1, fn1, f1, f0) << std::endl;
    return 0;
}
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 11, 2013, 05:53:55 am
И в довесок "велосипедное" (замыкания вручную) решение на С++. Работает сильно быстрее, не лезет в кучу и кушает меньше стека.
#include <iostream>

struct function_t
{
    virtual int operator() () const = 0;
};

struct f0 : function_t
{
    virtual int operator() () const {return 0;}
};

struct f1 : function_t
{
    virtual int operator() () const {return 1;}
};

struct fn1 : function_t
{
    virtual int operator() () const {return -1;}
};

struct b : function_t
{
    b(int k,
      function_t const& x1,
      function_t const& x2,
      function_t const& x3,
      function_t const& x4)
    : k(k), x1(x1), x2(x2), x3(x3), x4(x4)
    {}

    virtual int operator() () const;
private:
    mutable int k;
    function_t const& x1;
    function_t const& x2;
    function_t const& x3;
    function_t const& x4;
};

int a(int k,
      function_t const& x1,
      function_t const& x2,
      function_t const& x3,
      function_t const& x4,
      function_t const& x5)
{
    return k <= 0 ? x4() + x5() : b(k, x1, x2, x3, x4)();
}

int
b::operator() () const
{
    --this->k;
    return a(this->k,
             *this,
             this->x1,
             this->x2,
             this->x3,
             this->x4);
}

int main()
{
    std::cout << a(10, f1(), fn1(), fn1(), f1(), f0()) << std::endl;
    return 0;
}
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 11, 2013, 06:00:21 am
Парсер делает один проход по исходному тексту. Если парсер в операторной последовательности встречает неизвестный идентификатор, то он панику не разводит, а помещает этот идентификатор в буфер отложенных объявлений. Затем, если далее по тексту встречается объявление этого идентификатора, то парсер переносит его из буфера в таблицу имён. К тому моменту, когда будет достигнут конец модуля, буфер должен быть пуст, иначе ошибка.

Хорошо, парсер однопроходный. А код кто генерить будет? В текущей реализации моего компилятора все далется за один проход - и парсинг, и проверка семантики и генерация кода (никаких AST не строится). Почему нельзя сгенерировать код для вызова необъявленной процедуры - я написал выше.

Каких-то особых проблем в реализации многопроходности я не вижу - Вирт держится за однопроходность сугубо из-за своих личных предпочтений. Нет там никаких страшных усложнений компиялятора.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 11, 2013, 06:35:42 am
Утверждение, что в этом случае "компилятор железно перестаёт быть однопроходным" не верно.
Для сомневающихся хочу дать некоторые пояснения. Я использовал специальную структуру данных, которую назвал "буфер отложенных объявлений". Основная идея в упрощенном виде выглядит так. Парсер делает один проход по исходному тексту. Если парсер в операторной последовательности встречает неизвестный идентификатор, то он панику не разводит, а помещает этот идентификатор в буфер отложенных объявлений. Затем, если далее по тексту встречается объявление этого идентификатора, то парсер переносит его из буфера в таблицу имён. К тому моменту, когда будет достигнут конец модуля, буфер должен быть пуст, иначе ошибка. На самом деле всё несколько сложнее из-за вложенности областей видимости, но в моём случае (обероноподобный язык, но не Оберон) задача алгоритмически вполне решабельна (проверено на практике).

Если Вы генерируете маш. код уже после прохода по тексту по какой-то внутренней структуре данных -- то вот уже второй проход, компилятор двухпроходным стал...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: igor от Июль 11, 2013, 07:03:00 am
Под многопроходностью я понимаю несколько проходов по одному и тому же представлению программы. Проходы по другому представлению программы - это следующий этап обработки. Front-end и back-end обычно разделены в коде. Это же не означает, что компилятор стал двухпроходным? Или означает? Вопрос терминологии.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 11, 2013, 07:12:15 am
Классический однопроходный компилятор (например, для виртовских языков Паскаль/Оберон) считывает строку исходного кода и сразу же генерирует для неё маш. код, если там есть что генерировать -- выделяет место под переменные, транслирует операторы.

Транслятор с фронт-эндом и бэк-эндом -- уже как минимум двухпроходные...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: igor от Июль 11, 2013, 08:09:23 am
Вот у меня процедура Foo, которая использует другую процедуру которая определена где-то далеко внизу. Вопрос - как за один проход такое компилировать?
Никак. Просто потому, что в общем случае нельзя "угадать" сигнатуру - оберон допускает неявные преобразования типов аргументов. Например f('A') может быть как вызовом "PROCEDURE f(c: CHAR)" так и "PROCEDURE(s: ARRAY OF CHAR)".

В моём компиляторе переднего плана часть необходимых проверок производится отложенно, после того, как в исходном тексте встретится объявление неизвестного идентификатора. Конечно, при таком подходе генерировать машинный код на лету было бы проблематично, но такой задачи я себе и не ставил.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 11, 2013, 08:34:15 am
Под многопроходностью я понимаю несколько проходов по одному и тому же представлению программы. Проходы по другому представлению программы - это следующий этап обработки. Front-end и back-end обычно разделены в коде. Это же не означает, что компилятор стал двухпроходным? Или означает? Вопрос терминологии.
Угу, означает. Это и есть классический многопроходный компилятор. С созданием промежуточного представления и так далее. Переход на такой подход дает множество профитов, например дает возможность передать промежуточное представление стороннему приложению, которое делает что-то более интересное нежели кодогенерация. Компилятор превращается из компилятора в SDK для разаработки инструментария поддержки языка (всяко-разны статические анализаторы кода, рефакторинги, аналитика и так далее).

По такой схеме писан например GPCP. И это круто. Классическая Виртовская однопроходность компиляторов штука хорошая только в плане скорости компиляции на слабом железе.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: igor от Июль 11, 2013, 09:00:53 am
Под многопроходностью я понимаю несколько проходов по одному и тому же представлению программы. Проходы по другому представлению программы - это следующий этап обработки. Front-end и back-end обычно разделены в коде. Это же не означает, что компилятор стал двухпроходным? Или означает? Вопрос терминологии.
Угу, означает. Это и есть классический многопроходный компилятор. С созданием промежуточного представления и так далее.
Вот, и Geniepro то же самое говорит. Хорошо, буду знать (не зря всё-таки я этот разговор затеял).
Кстати, Свердлов в своей книге упоминает о 16-проходном компиляторе (один из ранних). Неужели там использовалось 16 различных представлений одной и той же программы?  :)  Хотя, нет конечно. Вот там действительно по каждому из представлений делалось по несколько проходов. Памяти не хватало даже на то, чтобы хранить код самого компилятора, загружался и выполнялся по частям.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 11, 2013, 09:52:43 am
Кстати, Свердлов в своей книге упоминает о 16-проходном компиляторе (один из ранних). Неужели там использовалось 16 различных представлений одной и той же программы?  :)  Хотя, нет конечно. Вот там действительно по каждому из представлений делалось по несколько проходов. Памяти не хватало даже на то, чтобы хранить код самого компилятора, загружался и выполнялся по частям.

Вот воспомминания об одном из первых трансляторов расширенного Алгола-60, первого сильно-оптимизирующего транслятора в мире:

"ИСТОРИЯ АЛЬФА-ПРОЕКТА" (http://www.computer-museum.ru/books/n_mozaika/alfa.htm) проф. И. В. Поттосин

Цитировать
Общая структура транслятора состоит из четырех этапов: получение промежуточного представления, превращение его во внутренний язык и оптимизации на внутреннем языке построение машинных команд, экономия памяти и формирование машинной программы. Все эти этапы разбивались на блоки. Разбиение определялось как функциональными действиями, так и необходимостью «вписаться» в малую (4К  45-разрядных слов) память компьютера.

Окончательная структура блоков такова:

 Ввод и первичный синтаксический контроль (блок 1) разработчик и реализатор — Загацкий.
 Обработка описаний (блок 2) — Кожухин.
 Завершение идентификации (блок 3) — Бабецкий.
 Декомпозиция выражений (блоки 4 и 5), разработчик — Кожухин, реализатор — Кожухина.
 Анализ и программирование процедур (блоки б и 7) — Загацкий.
 Перевод из промежуточного представления во внутренний язык (блок 8) — Ершов.
 Обработка геометрических операций над массивами и реализация действий с многомерными массивами (блоки 9, 10) — Волошин.
 Анализ и чистка циклов (блоки 11-13) — Бежанова (при участии в разработке Поттосина).
 Экономия выражений (блок 14) — Поттосин.
 Построение машинных команд (блок 15) — Кожухина (при участии в разработке Бабецкого).
 Программирование индекс-регистров и циклов (блоки 16-18) — разработчик Поттосин, реализатор Кожухина.
 Экономия констант (блок 19) — Змиевская (при участии в разработке Ершова).
 Построение операторной схемы и графа несовместимости (блоки 20, 21) — Мишкович (при участии в разработке Ершова).
 Распределение памяти (блок 22) — Трохан (при участии в разработке Ершова).
 Чистка и компоновка программы (блоки 23, 24) — Трохан, Змиевская.

Потом они портировали этот транслятор с М-20 на БЭСМ-6 и сильно упростили, уменьшив количество проходов в два раза...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: ddn от Июль 12, 2013, 05:24:47 am
Я понимаю там в хаскелле/сишарпе forward declarations не нужны -- весь модуль/класс просматривается при поиске нужной процедуры, переменной или типа , но в обероне...
Жестокое упрощение языка...
Дык лишняя сущность же!

Ну, на самом деле, если ослабить вот это требование: "The scope extends textually from the point of the declaration to the end of the block (procedure or module) to which the declaration belongs and hence to which the object is local." до "whole block (procedure or module)", то получится язык поприятнее для кодописателя (и чуть менее приятный для компилятороклепателя, хотя и тут выигрыш таки в итоге будет, ибо компилятор железно перестает быть однопроходным).
Даже если этого не делать, не следует по крайней мере разрешать видимость в процедуре внешнего к ней идентификатора, до того места где внутри процедуры будет (если будет) объявлен локальный идентификатор с тем же именем. Все идентификаторы внешние к процедуре следует импортировать в процедуру явно, возможно по псевдониму, и объявлений в процедуре идентификаторов с теми же именами/псевдонимами быть не должно. Хотя такой импорт расширяет синтаксис.


Да? А как? Вот у меня процедура Foo, которая использует другую процедуру которая определена где-то далеко внизу. Вопрос - как за один проход такое компилировать?
Никак. Просто потому, что в общем случае нельзя "угадать" сигнатуру - оберон допускает неявные преобразования типов аргументов. Например f('A') может быть как вызовом "PROCEDURE f(c: CHAR)" так и "PROCEDURE f(s: ARRAY OF CHAR)". Кроме того, передача VAR-аргументов тоже влияет на генерируемый код в точке вызова.
Неуверен, что невозможность без заглядывания вперед "угадать" сигнатуру вызываемой процедуры влечет невозможность генерировать готовый код такого вызова. Для ссылочных типов это получается.

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

Начиная с версии 2011 литералы литер (тип CHAR) и строк (тип Srtring) проходят одним нетерминалом и задаются через литерные цепочки только с двойными кавычками либо через число с суффиксом "X". Но неясно, можно ли однолитерные литерные цепочки использовать как литеры.
В версии 07 литералы литер, помимо числа с суффиксом "X", задаются через литерные цепочки с одинарными кавычками (в переводе Бурцева в репорте написано: CharConst = """ character """ | digit {hexDigit} "X", но примеры идут: 'A' '%' 22X), но строковые литералы задаются через литерные цепочки и с двойными кавычками и с одинарными. В версии 1 литералы и литер и строк могут задаваться литерными цепочками только с двойными кавычками (в репорте для литер нет примеров).

Есть и другой пример невозможности угадать сигнатуру без заглядывания вперед, если идентификаторы видны всюду в блоке, а не только впереди от точки своего объявления.
Фактический параметр может быть не только литералом неясного типа, тип которого требуется уточнять типом формального параметра, но и объектом, чей тип объявлен позже чем сделано обращение к объекту. Поскольку, вызов процедуры "f", происходящий когда обработаны еще не все декларативные области модуля (включая локальные), возможен только внутри другой процедуры "h", т.е. локально, и поскольку после такого вызова далее объявляются лишь процедуры (внешние по отношению к "h"), указанный пример возможен, если фактический параметр есть идентификатор некоторой нелокальной процедуры "g" или вычисляется на основе таких процедур.
То есть, если в теле некоторой процедуры "h" идет вызов "f(g)" или например "f(g(0)+g(1))" некоторой процедуры "PROCEDURE f(a: T)", где процедуры "f" и "g" объявлены после точки этого вызова, то в этой точке тоже невозможно угадать сигнатуру "f" без заглядывания вперед.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 12, 2013, 03:32:51 pm
Даже если этого не делать, не следует по крайней мере разрешать видимость в процедуре внешнего к ней идентификатора, до того места где внутри процедуры будет (если будет) объявлен локальный идентификатор с тем же именем. Все идентификаторы внешние к процедуре следует импортировать в процедуру явно, возможно по псевдониму, и объявлений в процедуре идентификаторов с теми же именами/псевдонимами быть не должно. Хотя такой импорт расширяет синтаксис.

Это оверкилл. Не пишите процедур на 1000 строк и не заводите кучу глобальных переменных - и будет вам счастье. Хотя если как средство отбить желание заводить глобальные переменные...

Неуверен, что невозможность без заглядывания вперед "угадать" сигнатуру вызываемой процедуры влечет невозможность генерировать готовый код такого вызова. Для ссылочных типов это получается.
...
То есть, если в теле некоторой процедуры "h" идет вызов "f(g)" или например "f(g(0)+g(1))" некоторой процедуры "PROCEDURE f(a: T)", где процедуры "f" и "g" объявлены после точки этого вызова, то в этой точке тоже невозможно угадать сигнатуру "f" без заглядывания вперед.

Взаимоисключающие параграфы детектед.

P.S. На самом деле посыл был в том, что в современном компиляторостроении однопроходность (без дополнительных оговорок) можно считать недостатком, а не достоинством. Не дает выигрыша ни пользователю языка ни создателю компилятора. А железо с компилируемой программой на ленте и невозможностью считать ее всю в память ушло в прошлое.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: ddn от Июль 12, 2013, 06:44:26 pm
Это оверкилл. Не пишите процедур на 1000 строк и не заводите кучу глобальных переменных - и будет вам счастье.
Если во всех вызовах параметр-переменная ссылается на один и тот же объект/подобъект и даже обязана ссылаться по логике задачи, что плохого если она импортируется один раз при декларации процедуры, а не много раз как фактический параметр.
Что значит кучу, больше 10, больше 100? Если запрещать в процедурах внешние переменные (не как параметры), то совсем.
Хотя если как средство отбить желание заводить глобальные переменные...
Это средство запретить использовать разные объекты под одним именем в одном блоке (за вычетом подблоков), область видимости блока должна быть однородной. Поэтому оператор FOR тоже нужно запретить, он тоже делает область видимости блока неоднородной, можно оформить FOR как спецконструктор процедур со своими областями видимости.

Мое предложение не относится к преопределенным идентификаторам, которые должны импортироваться неявно всюду и их нельзя перекрывать.


Неуверен, что невозможность без заглядывания вперед "угадать" сигнатуру вызываемой процедуры влечет невозможность генерировать готовый код такого вызова. Для ссылочных типов это получается.
...
То есть, если в теле некоторой процедуры "h" идет вызов "f(g)" или например "f(g(0)+g(1))" некоторой процедуры "PROCEDURE f(a: T)", где процедуры "f" и "g" объявлены после точки этого вызова, то в этой точке тоже невозможно угадать сигнатуру "f" без заглядывания вперед.
Взаимоисключающие параграфы детектед.
Во втором процитированном предложении я утверждаю, что если локальные идентификаторы процедуры/модуля видимы в ней всюду (в декларативной и операторной области) т.е. их можно использовать до точки объявления, то без заглядывания вперед будет невозможно в общем случае угадать сигнатуру вызываемой процедуры.
В первом предложении я лишь высказываю сомнение в том, что "если невозможно угадать сигнатуру вызываемой процедуры, то из этого следует невозможность сгенерировать готовый код такого вызова".
Что здесь взаимоисключающего?

То есть, я высказал сомнение в том что из видимости локальных идентификаторов всюду в процедуре/модуле следует в общем случае невозможность сгенерировать готовый код вызова процедур без заглядывания вперед (невозможность однопроходного компилятора). Однопроходность скорее свойство компилятора чем языка. Конечно, при видимости идентификаторов до точки объявления однопроходный компилятор будет сложнее, а генерируемый им код неоптимальнее, но компилятор будет.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: maliya от Июль 24, 2013, 06:52:48 pm
hi,I have done some work to make bb can work with this example.

so far, I don't think the closure is useful in bb programing, just do a half work only.

does we need this feature to built  in compiler?

 



   
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 24, 2013, 07:49:23 pm
hi,I have done some work to make bb can work with this example.

Wow! SYSTEM and a little bit of machine codes :) Still it traps on my BB 1.6-rc6...

so far, I don't think the closure is useful in bb programing, just do a half work only.

does we need this feature to built  in compiler?

Do you know how to do it (with GC awareness and so on)?

P.S. Yes, I think a modern general purpose language with GC must have a feature like full fledged closures.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: maliya от Июль 25, 2013, 02:28:33 am
Цитировать
Still IT traps on My BB 1.6-rc6 ...

it needs to make some changes of compiler, I say  it's half work,only a draft.
if it needed, can continue change compiler to let original example compiled and work without any change.
It is only a local procedure be packed as a normal procedure, not a true closure.

for my little knownledge of closure reason,I dont known what syntax should be add to cp if we want it.

closure reference, example and suggestion is welcome!
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 25, 2013, 06:57:32 am
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 25, 2013, 07:56:32 am
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
да нет, как вы поймете по существующему синтаксису в каком случае нужно сохранять локальный контент процедуры, в  каком нет?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 25, 2013, 09:41:21 am
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
да нет, как вы поймете по существующему синтаксису в каком случае нужно сохранять локальный контент процедуры, в  каком нет?
Так его сохранять нужно в любом случае. Если Вы передадите куда-то процедуру, имеющую доступ к какому-то внешнему для неё контексту, то что случится, если этот контекст не будет сохранён? Crash boom bang -- вот что случится...

Если обращается процедура к внешним переменным -- значит эти переменные должны быть сохранены в её контексте. И синтаксис тут ни при чём...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: valexey_u от Июль 25, 2013, 09:55:47 am
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
При чем тут синтаксис? Имелась ввиду естественно семантика замыкания контекста. Лямбды тут вообще не в тему.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 25, 2013, 10:17:06 am
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
да нет, как вы поймете по существующему синтаксису в каком случае нужно сохранять локальный контент процедуры, в  каком нет?
Так его сохранять нужно в любом случае. Если Вы передадите куда-то процедуру, имеющую доступ к какому-то внешнему для неё контексту, то что случится, если этот контекст не будет сохранён? Crash boom bang -- вот что случится...

Если обращается процедура к внешним переменным -- значит эти переменные должны быть сохранены в её контексте. И синтаксис тут ни при чём...
смотрите внимательно - я говорил о  сохранении локального контента (на который она замыкается) между вызовами.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 25, 2013, 11:32:50 am
смотрите внимательно - я говорил о  сохранении локального контента (на который она замыкается) между вызовами.

А какой такой локальный контент, сохраняемый между вызовами, может быть у процедуры в обероне? Статические переменные как в сях? Так их же не было никогда в паскалях...

Для замыканий не нужны статические переменные процедур:
http://ru.wikipedia.org/wiki/Замыкание_(программирование) (http://ru.wikipedia.org/wiki/Замыкание_(программирование))
Цитировать
Замыкание (англ. closure) в программировании — функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции и не в качестве её параметров (а в окружающем коде). Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своём контексте.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 25, 2013, 11:52:46 am
А какой такой локальный контент, сохраняемый между вызовами, может быть у процедуры в обероне? Статические переменные как в сях? Так их же не было никогда в паскалях...
тот  который я  хочу сохранить (по каким причинам, для простоты, неважно) - в самом простом случае я хочу сохранить переменную (ее содержимое) лексически связанную с функцией. Почти как в сях (есть нюансы). Ну и что , в делфях есть.
Цитировать
Для замыканий не нужны статические переменные процедур:
....
давайте договоримся какого эффекта мы хотим добиться их введением(как минимум, как максимум- для чего) а уж с помощью чего добиваться этого дело пятое-десятое.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 25, 2013, 04:32:49 pm
It is only a local procedure be packed as a normal procedure, not a true closure.

I don't think it worth efforts to do it in this way. I'd like to have true closures, not something I can use only with SYSTEM. This particular task can be resolved without closures supported by language (see my solution for O7).

No special syntax needed for CP to support closures. It just semantic change - you can pass and return a local function and this local function can refer to outer variables (including outer function variables).
But compiler will definitely demand some work - procedure variable cannot be just "address" any more, it became "address + pointer to context".

closure reference, example and suggestion is welcome!

You can see how closures work in JavaScript (there was example in this topic for discussed task).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 25, 2013, 04:39:31 pm
как вы поймете по существующему синтаксису в каком случае нужно сохранять локальный контент процедуры, в  каком нет?

Очевидно, что надо сохранять то, на что есть ссылки из локальной процедуры. Нет?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 25, 2013, 05:45:20 pm
Про синтаксис я не понял -- у замыканий синтаксис такой же как у обычной процедуры. Может быть maliya имел в виду лямбды?
При чем тут синтаксис? Имелась ввиду естественно семантика замыкания контекста. Лямбды тут вообще не в тему.

Я, конечно, знаю, что в английском пишется "Манчестер", читается "Ливерпуль", но не настолько же.
maliya чётко написал:
Цитата: maliya
for my little knownledge of closure reason,I dont known what syntax should be add to cp if we want it.
Вот я и удивился, не понял, что он имел в виду...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: qp от Июль 25, 2013, 09:09:49 pm
Промелькнуло в одной из рассылок http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html (http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html), "Достижение сатори с помощью замыканий":

* * *

  The venerable master Qc Na was walking with his student, Anton.  Hoping to
prompt the master into a discussion, Anton said "Master, I have heard that
objects are a very good thing - is this true?"  Qc Na looked pityingly at
his student and replied, "Foolish pupil - objects are merely a poor man's
closures."

  Chastised, Anton took his leave from his master and returned to his cell,
intent on studying closures.  He carefully read the entire "Lambda: The
Ultimate..." series of papers and its cousins, and implemented a small
Scheme interpreter with a closure-based object system.  He learned much, and
looked forward to informing his master of his progress.

  On his next walk with Qc Na, Anton attempted to impress his master by
saying "Master, I have diligently studied the matter, and now understand
that objects are truly a poor man's closures."  Qc Na responded by hitting
Anton with his stick, saying "When will you learn? Closures are a poor man's
object."  At that moment, Anton became enlightened.

:)
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 26, 2013, 09:52:25 am
как вы поймете по существующему синтаксису в каком случае нужно сохранять локальный контент процедуры, в  каком нет?

Очевидно, что надо сохранять то, на что есть ссылки из локальной процедуры. Нет?
Да (т.е. локальные переменные допустимых типов внешней процедуры), но меня беспокоит другой вопрос.. а если по замыслу эти внешние переменные не являются обьектами замыкания (являются обычными глобальными переменными относительно этой процедуры), сохранять их в любом случае?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: maliya от Июль 26, 2013, 12:28:55 pm
More trouble than benefit! keep language and compiler as simple as possible,though any problem can be solved by reference to other language's compiler,I think there is no need to continue to do: we are not good
at function programming just now, isn't it?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 03:45:31 pm
Очевидно, что надо сохранять то, на что есть ссылки из локальной процедуры. Нет?
Да (т.е. локальные переменные допустимых типов внешней процедуры), но меня беспокоит другой вопрос.. а если по замыслу эти внешние переменные не являются обьектами замыкания (являются обычными глобальными переменными относительно этой процедуры), сохранять их в любом случае?

Все "внешние" переменные, используемые в локальной процедуре являются объектами замыкания. Иначе оно не будет работать в общем случае. Если какую-то внешнюю переменную надо исключить из замыкания, но при этом ее значение используется в локальной функции, то такую переменную всегда можно передать как аргумент (т.е., скопировать и запомнить).
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 03:54:33 pm
More trouble than benefit! keep language and compiler as simple as possible,though any problem can be solved by reference to other language's compiler,I think there is no need to continue to do: we are not good
at function programming just now, isn't it?

Yeah, adding closures to original CP/Oberon requires a big piece of work from compiler/runtime implementation stand point. Although closures do not open something new comparing to classical "objects" (qp's quote has a good reflection on this) they can make source code much more clearer. So eventually I'd like to see them in some oberon implementation.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: DddIzer от Июль 26, 2013, 04:26:45 pm


Все "внешние" переменные, используемые в локальной процедуре являются объектами замыкания. Иначе оно не будет работать в общем случае. Если какую-то внешнюю переменную надо исключить из замыкания, но при этом ее значение используется в локальной функции, то такую переменную всегда можно передать как аргумент (т.е., скопировать и запомнить).
можно то можно, но не всегда удобно. Ладно, а ради чего все это делается в Обероне - с одной стороны, есть возможности создания обьектов с почти такими же свойствами (временем существования, степенью изолированности), с другой стороны, семантика Оберона ограничена...- более точно формулирую вопрос следующим образом: имеет ли смысл вводить замыкания не расширяя Оберон (по крайней мере его семантику)?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 26, 2013, 04:57:27 pm
Ладно, а ради чего все это делается в Обероне - с одной стороны, есть возможности создания обьектов с почти такими же свойствами (временем существования, степенью изолированности), с другой стороны, семантика Оберона ограничена...- более точно формулирую вопрос следующим образом: имеет ли смысл вводить замыкания не расширяя Оберон (по крайней мере его семантику)?

Да, именно поэтому и бродила раньше такая шутка: "Объекты -- это замыкания для бедных. Замыкания -- это объекты для бедных".

Не знаю, честно говоря, есть ли смысл вводить замыкания в Оберон -- там куда полезнее были бы шаблоны. Но просто это выглядит как-то искусственно -- есть все возможности что бы ввести замыкания, которые могут быть кому-то полезными, но для упрощения транслятора от этой возможности отказываются.
Впрочем, после отказа Вирта от перечислимого типа и от "forward declarations" я уже ничему не удивляюсь...  :-\
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 04:57:54 pm
Ладно, а ради чего все это делается в Обероне - с одной стороны, есть возможности создания обьектов с почти такими же свойствами (временем существования, степенью изолированности), с другой стороны, семантика Оберона ограничена...- более точно формулирую вопрос следующим образом: имеет ли смысл вводить замыкания не расширяя Оберон (по крайней мере его семантику)?

Э... Не расширив семантику ввести не получится - там явно прописано, что с локальными процедурами нельзя ничего делать :) По поводу смысла я там писал выше для maliya - меньше городить на ровном месте. Представь простейший, классический и часто употребимый случай - фабрика. Ты спускаешь фабрику какой-то компоненте, чтоб она могла создавать другие компоненты ничего не зная о них. В текущем состоянии языка (ББ) это делается через абстрактную запись с методом Create. Запись надо описать, потом расширить, создать... Горка кода. Если бы были полноценные замыкания, то потребовалось бы только процедурная переменная.

P.S. Это на ББ горка кода. На обероне-07 - вообще ужос-ужос. Запись с процедурным полем + последующие касты... В общем переборщил Вирт с простотой, переборщил...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 26, 2013, 05:03:04 pm
Although closures do not open something new comparing to classical "objects" (qp's quote has a good reflection on this) they can make source code much more clearer.

Что за "qp's quote"?
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 05:05:57 pm
Что за "qp's quote"?

http://oberspace.dyndns.org/index.php/topic,518.msg17552.html#msg17552
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 26, 2013, 05:07:52 pm
P.S. Это на ББ горка кода. На обероне-07 - вообще ужос-ужос. Запись с процедурным полем + последующие касты... В общем переборщил Вирт с простотой, переборщил...

Цитата: http://nponeccop.livejournal.com/333439.html?thread=3087743#t3087743
"Язык, который был проще, чем нужно"

Давным-давно кто-то из людей, делавший компилятор из Оберона в байт-код.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 05:14:22 pm
P.S. Это на ББ горка кода. На обероне-07 - вообще ужос-ужос. Запись с процедурным полем + последующие касты... В общем переборщил Вирт с простотой, переборщил...

Поэтому если пилить О7 в сторону большей человечности, то добавление замыканий залечит вот такие вот проблемы с недо-ООП (можно будет хотя бы писать "object.method()"). При этом описание языка практически не пострадает. Правда эффективность с точки зрения машины ухудшится, да.
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 26, 2013, 05:17:21 pm
Цитата: http://nponeccop.livejournal.com/333439.html?thread=3087743#t3087743
"Язык, который был проще, чем нужно"

Угу - это хороший эпиграф к O7 :)
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: vlad от Июль 27, 2013, 05:21:28 am
При этом описание языка практически не пострадает. Правда эффективность с точки зрения машины ухудшится, да.

На самом деле еще VAR параметры перестанут быть эффективными. Нельзя будет передавать стековые пемеменные как VAR - они могут попасть в closure (ниже по стеку) и поэтому обязаны быть в куче.

С другой стороны, если внизу жабаскрипт, а не микроконтроллер, то все эти замечания об эффективность не актуальны...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 27, 2013, 06:41:54 am
При этом описание языка практически не пострадает. Правда эффективность с точки зрения машины ухудшится, да.

На самом деле еще VAR параметры перестанут быть эффективными. Нельзя будет передавать стековые пемеменные как VAR - они могут попасть в closure (ниже по стеку) и поэтому обязаны быть в куче.

Кстати, в сишарпе out-параметры нельзя передавать в замыкание, в эфшарпе, если не ошибаюсь, вообще мутабельные переменные елльзя замыкать...
Название: Re: [Oberon7] "Man or Boy test" by Donald Knuth
Отправлено: Geniepro от Июль 27, 2013, 08:12:02 am
Цитата: http://nponeccop.livejournal.com/333439.html?thread=3087743#t3087743
"Язык, который был проще, чем нужно"

Угу - это хороший эпиграф к O7 :)

Скорее -- эпитафия ))