‮Сдвиг по фазе (kincajou) wrote,
‮Сдвиг по фазе
kincajou

Ботанизм-програмизм (3).



Step 0
Step 1
Step 2
Step 3
Step 4
Step 5
Step 6
Step 7
Step 8
Step 9
result: 9
---[ Context 0x51fc200 BEGIN ]---
Level 0x51fc200:
FOR-TEST-CYCLE: ( FOR ( ( DEFSYM X 0 )
( < X 10 )
( DEFSYM X ( + X 1 )
)
)
( PROGN ( FORMAT "Step ~a~%" X )
X )
)
----[ Context 0x51fc200 END ]----


Синтаксический сахар отсутствует.

FOR автоматически снижает контекст, поэтому создаваемый там символ X наверху не виден. Но, разумеется, само значение X можно вернуть, если вдруг надо: внутри блока PROGN - FORMAT выводит строку, а затем "просто возврат" X - соотв., на последней итерации это значение и будет передано наверх.

Если кому интересно, но ещё не понятно - это мой "игрушечный" лисп-самоделка. Работает как настоящий, просто ещё очень маленький и примитивный сам по себе.


До этого момента контекст был просто списком списков символов и меня всё устраивало. А потом я подумал над тем, как прерывать исполнение, например, тех же циклов - с одной стороны, чтоб не плодить сущности, можно в цикле объявить переменную и проверять её вместе с условием завершения цикла. И если нужно прерывать исполнение где-то посередине, то устанавливать эту переменную в нужное значение. Но это, вообще говоря, роскошь - ещё одно имя в пространстве имён, пусть и в локальном контексте; затрата дополнительных тактов (их и так немало!) на поиск и извлечение значения; анализ этого значения...

В общем, с чего момента контекст исполнения имеет так же флаги. Пока что только один: cycle_break.
Если его установить в 1, то текущий цикл прерывается.
Установить этот флаг можно только оператором BREAK (в будущем, наверное, ещё обработчики ошибок будут это делать).

Step 0
Step 1
Step 2
Step 3
Step 4
Step 5
Break!
result: 5
---[ Context 0x51fc200 BEGIN ]---
Level 0x51fc200:
context flags:0
FOR-TEST-CYCLE: ( FOR ( ( DEFSYM X 0 )
( < X 10 )
( DEFSYM X ( + X 1 )
)
)
( PROGN ( FORMAT "Step ~a~%" X )
( IF ( > X 4 )
( BREAK )
)
X )
)
----[ Context 0x51fc200 END ]----


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

Step 0
Going to next cycle
Step 1
Going to next cycle
Step 2
Going to next cycle
Step 3
Going to next cycle
result: "Cycle early return"
---[ Context 0x51fc200 BEGIN ]---
Level 0x51fc200:
context flags:0
FOR-TEST-CYCLE: ( FOR ( ( DEFSYM X 0 )
( < X 5 )
( DEFSYM X ( + X 1 )
)
)
( PROGN ( FORMAT "Step ~a~%" X )
( IF ( BAR X 3 )
( RETURN "Cycle early return" )
)
( FORMAT "Going to next cycle~%" )
"Cycle is completed" )
)


BAR: ( ( X Y )
-> ( = X Y )
)
----[ Context 0x51fc200 END ]----

В этом примере, в cond-части оператора IF вызывается функция BAR, которая просто сравнивает два числа, и если она возвращает булево T, то внутри true-branch вызывается оператор RETURN, которому передана некая строка - её мы и видим, как результат работы цикла.

Как видно, вызов ( FORMAT "Going to next cycle~%" ) срабатывает и после того, как вроде бы отработал оператор ( RETURN "Cycle early return" ) -- это результат тупого последовательного исполнения инструкций оператором PROGN. Чтобы это предотвратить, добавил в контекст флажок "block_return" и анализирую его внутри PROGN - если флаг установлен, прерываю цикл. И тогда результат прогона программки выглядит уже правильно:
Step 0
Going to next cycle
Step 1
Going to next cycle
Step 2
Going to next cycle
Step 3
result: "Cycle early return"

Блоки исполнения пока никаких имён не имеют, но это легко исправить очередной модификацией структуры контекста - тогда можно будет реализовать не безымянный RETURN, а полноценный RETURN-FROM, который из вложенного блока заставит завершить процесс исполнения блока более верхнего уровня (который и будет найден по имени во время автоматического "развинчивания" контекста).


А ещё через эту же структуру можно, например, исключения (exeptions) пробрасывать. Когда-нибудь, в будущем.
Tags: uncommon lisp
Subscribe

  • Толерантность, равенство и лицемерие.

    Бибиси зачем-то не первый уже день раскручивает американскую историю с гибелью некой Габби Петито. И в своей же статье пишет: Смерть Габби Петито…

  • Спасли!

    Предполагается, что перегруженная мигрантами лодка прибыла к берегам Италии из Ливии, на ней было немало женщин и детей. И в самом деле, глядя на…

  • Разбился самолёт с парашютистами.

    Звучит как начало чернушного анекдота, типа "сгорела пожарная часть" или "чиновник сел за растрату".. эхм... Но - нет, это совсем не анекдот, люди…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 1 comment