memory heap
343 subscribers
2.31K photos
471 videos
52 files
2.94K links
science ∩ art = wonder

all memory blocks here are allocated by @a_v_p

GitHub: https://github.com/artyom-poptsov
Mastodon: https://fosstodon.org/@avp

https://memory-heap.org/~avp/
Download Telegram
Работаю над новой функциональностью для моего компилятора машин состояний — Guile-SMC.

Итоги работы: получилось сделать преобразование ДКА в код на Scheme, который никаким образом не зависит от самого Guile-SMC. На выходе получается самодостаточный код (который можно записать в одном файле), который похож на тот, который я мог бы написать руками.

Для того, чтобы получить подобный самодостаточный код, я копирую ядро Guile-SMC в выходной код, при этом сам ДКА преобразуется в подобное представление (реальный пример):
(define (run-fsm context)
""
(define (DEFAULT context)
"Count parenthesis."
(let ((event (event-source context)))
(cond ((guard:eof-object? context event)
(let ((context (action:validate context event)))
(log-debug "[~a] -> [*]" 'DEFAULT)
context))
((guard:semicolon? context event)
(let ((context (action:no-op context event)))
(log-debug "[~a] -> [~a]" 'DEFAULT 'COMMENT)
(COMMENT context)))
((guard:double-quote? context event)
(let ((context (action:no-op context event)))
(log-debug "[~a] -> [~a]" 'DEFAULT 'STRING)
(STRING context)))
((#{guard:#t}# context event)
(let ((context (action:count context event)))
(DEFAULT context))))))
(define (STRING context)
"Skip a string."
(let ((event (event-source context)))
(cond ((guard:double-quote? context event)
(let ((context (action:no-op context event)))
(log-debug "[~a] -> [~a]" 'STRING 'DEFAULT)
(DEFAULT context)))
((#{guard:#t}# context event)
(let ((context (action:no-op context event)))
(STRING context))))))
(define (COMMENT context)
"Skip a comment."
(let ((event (event-source context)))
(cond ((guard:newline? context event)
(let ((context (action:no-op context event)))
(log-debug "[~a] -> [~a]" 'COMMENT 'DEFAULT)
(DEFAULT context)))
((#{guard:#t}# context event)
(let ((context (action:no-op context event)))
(COMMENT context))))))
(DEFAULT context))


Из интересного: получилось также сделать некую "оптимизацию" выходного кода путём удаления неиспользуемых процедур.

Теперь у Guile-SMC три режима (цели) компиляции:
- guile — обычный режим компиляции, который выбирается по-умолчанию. В этом случае выходной код зависит от наличия Guile-SMC в системе и без него выполняться не будет.
- guile-standalone-copy — моя первая попытка сделать самодостаточный код. В этом случае все необходимые модули Guile-SMC копируются в отдельный каталог рядом с выходным ДКА, и зависимости ДКА переписываются так, чтобы они указывали на скопированные модули.
- guile-standalone — вторая (текущая) попытка сделать самодостаточный код, и похоже самая успешная (хотя я решил оставить guile-standalone-copy как вариант, т.к. в некотроых случаях он может быть удобнее.)

Пример запуска с указанием цели компиляции:
$ cat fsm.puml | smc compile -L .  -U "((context))" -t guile-standalone -m "(custom-fsm)"  > custom-fsm.scm


#projects #guile #smc #compiler
👍1