Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 20 июн 2025, 22:11

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу Пред.  1, 2, 3  След.
Автор Сообщение
СообщениеДобавлено: 21 июн 2014, 07:11 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Zorko писал(а):
На базе этого решения придумывается такая идея (думаю, легко будет реализовать):
Код: "OBERON"
  1. Asm.Code4(
  2. " LD A, #1 ",
  3. " OUT (#0xFE), A ",
  4. " LD B, #123 ",
  5. " METKA$: DJNZ METKA$ "
  6. );
Так ещё чище асм-код будет смотреться.
Может быть специально для таких системных случаев добавить специальный вид процедур (не в Оберон, а в Ofront, навроде PROCEDURE-)?
Введем процедуры с переменным числом параметров вида
Код: "OBERON"
  1. PROCEDURE Proc (a: T; .. );
Такая процедура имеет единственный параметр и не может возвращать значение (не функция). Знак ".." после этого параметра означает, что можно вызывать не только Proc(exp1), но и Proc(exp1,exp2) или Proc(exp1,exp2,exp3,exp4,exp5). Т.е. процедура может иметь любое количество фактических параметров (не менее одного), но все эти параметры должны быть одинакового типа.
Вызов Proc(exp1,exp2,...,expN) понимается как Proc(exp1);Proc(exp2);... Proc(expN)
Тогда можно было бы сделать и Asm.Code с любым числом строчек и еще много чего полезного.

P.S. По терминологии. Наверно лучше назвать это не "процедура с переменным числом параметров" (как в С, где доп.параметры могут быть любых типов), а "процедура с мультипараметром", потому что формальный параметр один (при описании процедуры), хотя и может повторяться сколько угодно раз при вызове.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 июн 2014, 08:57 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Начать можно с модуля OPP:
Код: "OBERON"
  1. (* module visibility of objects *)
  2. internal = 0; external = 1; externalR = 2; inPar = 3; multiPar = 4;
  3. ...
  4. PROCEDURE FormalParameters(VAR firstPar: OPT.Object; VAR resTyp: OPT.Struct);
  5. VAR mode, vis: BYTE;
  6. par, first, last, res: OPT.Object; typ: OPT.Struct;
  7. BEGIN first := NIL; last := firstPar;
  8. IF (sym = ident) OR (sym = var) OR (sym = in) THEN
  9. LOOP
  10. vis := 0;
  11. IF sym = var THEN OPS.Get(sym); mode := VarPar
  12. ELSIF sym = in THEN OPS.Get(sym); mode := VarPar; vis := inPar
  13. ELSIF sym = upto THEN
  14. IF (first # NIL) & (first = last) THEN (* перед .. есть ровно 1 параметр *)
  15. OPT.Insert(OPS.name, par); OPS.Get(sym); (* вставим фиктивный параметр *)
  16. mode := VarPar; vis := multiPar;
  17. par^.mode := mode; par^.vis := vis;
  18. par^.link := last; (* указывает на предшествующий параметр *)
  19. last^.link := par; last := par;
  20. EXIT
  21. ELSE err(ident)
  22. END
  23. ELSE mode := Var
  24. END ;
  25. ...
  26. PROCEDURE ActualParameters(VAR aparlist: OPT.Node; fpar: OPT.Object);
  27. VAR apar, last: OPT.Node;
  28. BEGIN aparlist := NIL; last := NIL;
  29. IF sym # rparen THEN
  30. LOOP Expression(apar);
  31. IF fpar # NIL THEN
  32. OPB.Param(apar, fpar); OPB.Link(aparlist, last, apar);
  33. fpar := fpar^.link;
  34. IF (fpar # NIL) & (fpar^.vis = multiPar) THEN fpar := fpar^.link END (* зацикливание мультипараметра*)
  35. ELSE err(64)
  36. END ;
  37. IF sym = comma THEN OPS.Get(sym)
  38. ELSIF (lparen <= sym) & (sym <= ident) THEN err(comma)
  39. ELSE EXIT
  40. END
  41. END
  42. END ;
  43. IF (fpar # NIL) & (fpar^.link^.vis # multiPar) THEN err(65) END (* учтем мультипараметр*)
  44. END ActualParameters;

Конечно, это только начало. Остальное надо дописывать.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 июн 2014, 11:36 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Олежка, прошу не обижаться, но мне эта фишка кажется излишней. :) Так теряется дополнительный контроль количества байтов, слов, строк. А число в Asm.CodeN даже добавляет строгости. Можно потом сказать: моя процедура занимает N строк на асме. :)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 июн 2014, 12:27 
Не в сети

Сообщения: 25
Зато проще при редактировании вставлять-удалять строки, не пересчитывая.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 июн 2014, 12:32 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Зато сложнее пересчитывать глазками строки, если понадобится. ;)

Плюсы у такого переменного числа параметров тоже есть, не буду спорить. :) Но это уход от строгости Оберона и Модулы, хоть и для системных целей, но всё же.

Ну да бог с вами, можно сделать. Особенно если поможете. :)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 21 июн 2014, 16:22 
Не в сети

Сообщения: 25
Предпоследняя строка.

IF (fpar # NIL) & (fpar^.link^.vis # multiPar) THEN err(65) END (* учтем мультипараметр*)

Если fpar^.link=NIL, то ошибки левой не даст? Предлагаю:

IF (fpar # NIL) & ~((fpar^.link#NIL) & (fpar^.link^.vis = multiPar)) THEN err(65) END (* учтем мультипараметр*)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 22 июн 2014, 15:36 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Reobne писал(а):
Предпоследняя строка.

IF (fpar # NIL) & (fpar^.link^.vis # multiPar) THEN err(65) END (* учтем мультипараметр*)

Если fpar^.link=NIL, то ошибки левой не даст? Предлагаю:

IF (fpar # NIL) & ~((fpar^.link#NIL) & (fpar^.link^.vis = multiPar)) THEN err(65) END (* учтем мультипараметр*)

Да, верно. Если формальных параметров ровно на 1 больше, и это не мультипараметр, то fpar^.link=NIL, что даст ошибку.
Действительно, нужно внести такое исправление, спасибо.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 22 июн 2014, 17:35 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Zorko писал(а):
Так теряется дополнительный контроль количества байтов, слов, строк. А число в Asm.CodeN даже добавляет строгости. Можно потом сказать: моя процедура занимает N строк на асме. :)
...
Зато сложнее пересчитывать глазками строки, если понадобится. ;)
А зачем нужен контроль количества строк? Я понимаю, если байты, слова или еще какие-то элементы. Тогда можно написать "я размещаю в этом буфере 512 байтов, вот они...". И если далее указать иное количество, то контроль должен это обнаружить. Но строки в листинге ассемлера... Ведь каждая из них может порождать 1, 2, 3 или даже более байтов , или 0 (комментарий например или макрос). Вообще, часто ли программисту приходится считать строки или операторы? Разве что для оплаты (столько-то центов за строчку) или в конкурсе "программа из наименьшего числа строк".
Контроль - это когда сравнивается информация, полученная разными путями. Например, контрольная сумма, вычисленная для принятых данных, сравнивается с КС, которая передана с этими данными. Или END, соответствующий по вложенности BEGIN-у процедуры, сравниваестя с END-ом, помеченным именем этой процедуры.
Контроль бы работал, если бы программист заранее знал точное число строчек ассемблера. "Ага, чтобы перекрасить спрайт, мне надо 5 строчек. Ставим 5, пишем строчки, запускаем... Ошибка - я уложился в 4. Какую строчку я забыл?" Никто заранее не вычисляет количество строк. Если мы введем контроль по количеству, то программист как и раньше будет писать строки программы не задумываясь об их количестве , потом пальцем пересчитает строчки и поставит результат подсчета в нужное место. Что даст такой контроль, кроме развития начальных арифметических навыков?
Zorko писал(а):
Плюсы у такого переменного числа параметров тоже есть, не буду спорить. :) Но это уход от строгости Оберона и Модулы, хоть и для системных целей, но всё же.
Но ассемблерная вставка - это не Оберон и не Модула, это Ассемблер! :) Эти текстовые строчки по смыслу именно операторы Ассемблера, следующие друг за другом, как и в программе на Обероне операторы Оберона идут друг за другом через ";". Оберон в разумной строгости своей не требует "для контроля" указывать в скобках после BEGIN количество операторов, которые идут до соответствующего END. В любом ЯП можно свободно соединять сколько угодно операторов, не пересчитывая их вручную. Но мы не можем писать в программе на Обероне операторы ассемблера напрямую и приходится использовать специальную процедуру, у которой эти операторы выражаются через фактические параметры. А параметров у процедуры не может быть переменное количество.
Так что "строгость, простота и контроль" относятся к требованию Оберона иметь у процедуры фиксированное количество параметров. Это весьма разумное требование само по себе, но нам оно мешает потому, что вызов процедуры Asm.Code - это программа на ассемблере и параметры - это операторы ассемблера.


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 22 июн 2014, 20:16 
Не в сети
Администратор
Аватара пользователя

Сообщения: 273
Откуда: Россия
Цитата:
Так что "строгость, простота и контроль" относятся к требованию Оберона иметь у процедуры фиксированное количество параметров. Это весьма разумное требование само по себе, но нам оно мешает потому, что вызов процедуры Asm.Code - это программа на ассемблере и параметры - это операторы ассемблера.
Посмотрите, какой механизм процедур с переменным числом параметров у Си. Чтобы извлечь очередной параметр нужно вручную указывать его тип, через макросы передвигать указатель по стеку. Компилятор никак не контролирует ни количество параметров, ни их размер. Вот уж где бескрайний простор для ошибок! Вот чего в Обероне быть не должно!
"Имя процедуры однозначно задает количество параметров"-это наиболее простой принцип. Если бы это было не так, то пришлось бы вводить понятия "профиль процедуры", описывать синтаксис "необязательный параметр", вводить функцию, сообщающую число параметров и пр. Из этого принципа появляется возможность контролировать при вызове соответствие имени процедуры и фактически указанное количество параметров, что выловит некоторые ошибки.
А много ли мы теряем из-за такой строгости? Нет. Если у процедуры может по смыслу быть разное количество параметров, то создайте несколько процедур. А внутри эти процедуры могут вызывать друг друга или вызывать некую общую, скрытую внутри модуля. Если процедура - это некое действие, то иное количество параметров означает немного иное действие.
Простота описания ЯП, простота компилятора, возможность контроля - всё это перевешивает "экономию на именах процедур". Стоит ли нам отходить от этого принципа? Пусть процедура с мультипараметром имеет достаточно ясную и строгую семантику. Но это расширение ЯП Оберон (пусть для системных нужд, но чего лукавить, расширяя Ofront, мы фактически расширяем ЯП, который транслируется Ofront-ом). А внесение фичей в сам язык (тем более новых, не опробованных в родственных компиляторах) - это крайнее средство, к которому нужно прибегать, если иное не сработало и если это расширение сулит значительную выгоду.
Для чего же мы это затеяли, какую значительную выгоду купим введением несовместимого, эзотерического диалекта ? "Так ещё чище асм-код будет смотреться" :shock:

Zorko писал(а):
Олежка, прошу не обижаться, но мне эта фишка кажется излишней. :)
Так не только не обижаюсь, Олежка, но и согласен! :D
Эти мультипараметры - не более чем "синтаксический сахар", причем "слащавый". Впрочем, Asm.Code4 - тоже сахар. Но здесь хотя бы не нужно расширять ЯП и реализовать можно за 5 минут и накладных расходов практически никаких. А мультипараметры когда еще напишем, когда еще отладим. Но тем не менее, по мне так и
Код: "OBERON"
  1. Asm.Code(' PUSH HL ');
  2. Asm.Code(' LD HL,#0h4000 ');
  3. Asm.Code(' LD (HL),#1 ');
  4. Asm.Code(' INC H ');
достаточно наглядно. Повтор имен процедуры слева и ); справа сливаются в некий узор, который может и не будет отвлекать внимание, если привыкнуть (как багет не мешает изучению картины, а занавес просмотру спектакля). Тем более, если редактор выделяет текстовые константы особой раскраской.
Трудно писать каждый раз "Asm.Code("? Так есть буфер обмена, есть контекстная замена, есть автоматический ввод ключевых слов. Можно подумать над каким-то специальным средством IDE, для сокрытия повторяющихся имен процедуры (или замены их на ---"---). Внешний вид кода - это дело редактора IDE, а не синтаксиса и семантики ЯП (в данном случае). Если мы пишем на ассемблере, то главное - это операторы ассемблера, а Asm.Code( - это техническое обрамление.

ИТАК. Процедуры с мультипараметром - фича малополезная, а учитывая сложность реализации и несовместимость ЯП, так и вовсе вредная. Полезность может быть только в том, что дан повод 1)для полезной дискуссии про "Oberon-way" 2)для изучения Ofront.
Если кто-то реализует процедуры с мультипараметром и продемонстрирует великую полезность для чего-то еще, тогда может и будет повод к этому вернуться.
Хотя не представляю пока эту "великую полезность". Задание константного массива или иной структуры, например, где в каждой строке не одна текстовая константа а разное количество параметров, поэтому как-то тут мультипараметры сильно лучше? Вряд ли...
Вообщем, моё мнение - мультипараметрами заниматься не нужно. Прошу прощения за провокацию :)


Вернуться к началу
 Профиль  
Ответить с цитатой  
СообщениеДобавлено: 22 июн 2014, 22:57 
Не в сети
Аватара пользователя

Сообщения: 1019
Откуда: Днепропетровская обл.
Прочитал с внутренним согласием. :)
Да, гораздо полезнее будет развивать другие направления.


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 22 ]  На страницу Пред.  1, 2, 3  След.

Часовой пояс: UTC + 2 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
© VEDAsoft Oberon Club