Предыдущая серия про Кумир тут: Компилятор русского языка программирования Кумир
Если кратко то я добавил поддержку корутин. На синтаксисе это никак не отразилось, а вот во внутреннем языке оно есть. Это позволило в частности сделать нормальную анимацию в браузере.
Например, есть код анимации задачи n-тел:
использовать Рисователь
алг
нач
вещ таб x[0:N-1], y[0:N-1], vx[0:N-1], vy[0:N-1]
вещ таб tx[0:N-1, 0:TAIL-1], ty[0:N-1, 0:TAIL-1]
цел frame
инициализировать(x, y, vx, vy, tx, ty)
новый лист(W, H, чёрный)
frame := 0
нц пока да
шаг_физики(x, y, vx, vy, tx, ty)
нарисовать(frame, x, y, tx, ty)
frame := frame + 1
кц
кон
алг шаг_физики(...)
нач
| обычный CPU-код, без команд Рисователя
кон
алг нарисовать(...)
нач
| рисуем кадр
окружность(int(CX), int(CY), 12)
...
окружность(int(x[i]), int(y[i]), 2)
| граница кадра / suspend point
новый лист(W, H, чёрный)
кон
Трансляция во внутренний язык (ast, core-lang):
(fun <main> void () ()
(block
...
(call инициализировать x y vx vy tx ty)
(call |новый лист| W H чёрный)
(= frame 0)
(while
#t
(block
(call шаг_физики x y vx vy tx ty)
(call нарисовать frame x y tx ty)
(= frame (+ frame 1))))))
(fun шаг_физики void (...) ()
(block
...))
(fun нарисовать void (...) ()
(block
...
(call окружность (call int CX) (call int CY) 12)
...
(call окружность (call int (index i x)) (call int (index i y)) 2)
(call |новый лист| W H чёрный)))
Тут «новый лист» это на самом деле переход к новому фрейму. Это корутина. Данный ast трансформируется в
(fun <main> <future void> () ()
(block
...
(call инициализировать x y vx vy tx ty)
;; прямой suspend point: painter_new_sheet / "новый лист"
(await (call |новый лист| W H (: 4278190080 <named цвет i64>)))
(= frame 0)
(while
(cast 1 bool)
(block
;; обычная функция: не стала корутиной
(call шаг_физики x y vx vy tx ty)
;; транзитивный await:
;; main ждёт нарисовать, потому что нарисовать внутри вызывает новый лист
(await (call нарисовать frame x y tx ty))
(= frame (+ frame 1))))))
(fun шаг_физики void (...) ()
(block
...))
(fun нарисовать <future void> (...) ()
(block
...
(call окружность (call int CX) (call int CY) 12)
...
(call окружность (call int (index i x)) (call int (index i y)) 2)
;; локальный suspend point, из-за него вся функция стала Future<void>
(await (call |новый лист| W H (: 4278190080 <named цвет i64>)))))
То есть автоматом ставится await и все вызывающие функции транзитивно становятся корутинами. Это позволяет прыгнуть в js, сделать отрисовку, а потом прыгнуть назад в кумир.
Демка: http://qumir.dev/s/ZTZjYjM2NzRk
Звезды ставить сюда: https://github.com/resetius/qumir







