Автор Тема: [Oberon7] "Man or Boy test" by Donald Knuth  (Прочитано 46477 раз)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #15 : Июль 06, 2013, 02:04:42 pm »
Народ, сабжевая задача, мягко говоря, не является приоритетом.

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

PS. Полагаю решить эту задачу на Оберон-07/11 можно. Вечером подумаю.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #16 : Июль 06, 2013, 02:59:15 pm »
Задача Кнута показывает, что Оберон-07, вроде бы продолжающий алголовскую традицию языков, является тем не менее "детским" (Boy) языком, и это при том что уже в 60-х гг. прошлого века были "взрослые" (Man) реализации Алгола-60...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #17 : Июль 06, 2013, 04:01:46 pm »
Код из первого поста в А2 отработал 11 раз (каждая процедура) и трапнулся с access violation

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #18 : Июль 06, 2013, 04:20:06 pm »
Код из первого поста в А2 отработал 11 раз (каждая процедура) и трапнулся с access violation

Не совсем понял, что это значит, но там явно что-то не то в А2.
Количество вызовов процедуры А должно быть равно 722 раз, результат = -67.
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #19 : Июль 06, 2013, 05:01:39 pm »
ну что происходит - при вызове A из B происходит реальный вызов A

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #20 : Июль 06, 2013, 05:12:51 pm »
ну что происходит - при вызове A из B происходит реальный вызов A

А версия контекста процедуры А при этом какая? Новая для каждого вызова В или одна общая для всех вызовов А?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #21 : Июль 06, 2013, 05:15:51 pm »
Я взял из статьи код для М3, адаптировал для запуска в А2, и у меня получился совсем другой результат, чем при использовании кода из первого поста.
результат - stack overflow
проверь таки код

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #22 : Июль 06, 2013, 05:33:29 pm »
Я взял из статьи код для М3, адаптировал для запуска в А2, и у меня получился совсем другой результат, чем при использовании кода из первого поста.
результат - stack overflow
проверь таки код

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

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

Приведи свой код для A2, посмотрим, в чём отличия...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #23 : Июль 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.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #24 : Июль 06, 2013, 09:04:17 pm »
Собственно реализовать то что там есть, можно хоть на Обероне-07/11 хоть на Си. Проблем не вижу. Но, еще раз, тест не про это. Тест про корректность компилятора Алгола-60.

Не могу согласиться. Да, в те годы у Кнута выбор был небольшой, поэтому он и ограничился Алголом. Однако это не значит, что нельзя использовать этот тест для оценки реализаций других языков, имеющих необходимые для этого теста средства -- передачу процедур (в том числе локальных) как параметры с сохранением их контекста.
Другое дело, что Оберон-07 (а также Компонентный Паскаль) такой возможности не имеет, поэтому для него этот тест не имеет смысла...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #25 : Июль 07, 2013, 04:33:25 am »
ну что происходит - при вызове A из B происходит реальный вызов A

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

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #26 : Июль 07, 2013, 06:05:17 am »
Подумал над задачкой. Самое смешное, что на Обероне (Oberon/Oberon-07/Oberon-2/CP) похоже не удастся обойтись без использования динамической памяти (кучи), стека не достаточно. Ведь в Обероне нельзя получить указатель на переменную, что на стеке. Поэтому решение в стиле Си не прокатит.

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

Так что NEW в зубы и руками городить рядом с нормальным стеком, стек своих фреймов, в куче.
Y = λf.(λx.f (x x)) (λx.f (x x))

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #27 : Июль 07, 2013, 07:44:56 am »
Какой код проверить? Мой Обероновский (переделанный из варианта для Модулы-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
« Последнее редактирование: Июль 07, 2013, 07:47:31 am от Kemet »

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #28 : Июль 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 ~

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [Oberon7] "Man or Boy test" by Donald Knuth
« Ответ #29 : Июль 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
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…