Различия между версиями 13 и 14
Версия 13 от 2021-12-05 17:05:58
Размер: 12729
Редактор: FrBrGeorge
Комментарий:
Версия 14 от 2022-09-04 16:36:42
Размер: 12736
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 1: Строка 1:
= Макроязыки = = Макроязыки (2021) =

Макроязыки (2021)

Стрим на YouTube

(Про что не будет разговора)

Программирование, обусловленное средой — изначально среда представлена готовым набором объектов и команд над ними

  • DSL-языки
  • Языки склейки — shell, perl,и т. п. — от командной строки к сценарию

Контекстно обусловленная обработка данных — как правило, текстов, или domain-specific:

  • Чистая теория: НАМ
  • Императивная модель на основе регулярных выражений: sedawkperl

  • БНФ и им подобные

Принцип макроподстановки

Задача: параметризовать текст.

  • На входе:
    1. Определения нетерминалов (макросов)

    2. Текст, содержащий эти нетерминалы
  • Принцип макроподстановки: нетрерминал заменяется на тело его определения

  • На выходе — гладкий текст

Свойства области применения:

  • Часто: выходной текст похож на входной (cpp, *roff и т. п.; но: autoconf)

  • Почти всегда: выходной текст воспроизводит структуру входного (текст как поток)

Все? А алгоритмическая полнота?

  1. Аллегирование
    • Данные: по связыванию (как в ФП)
      • Параметризация определения и подстановки

    • Контекст: имена макросов
  2. Действия, определяемые свойствами данных
    • Пустой/непустой контекст, сравнение двух контекстов, …
  3. …в том числе возможность итерации
    • Проверка на наличие нетерминалов в макроподстановке ⇒ рекурсия!

Что может ещё потребоваться:

  • Экранирование
    • Параметризация + экранирование = передача макросов в качестве параметров
  • Манипуляция несколькими потоками
  • Отказаться от построчной обработки

  • Вообще отказаться от понимания текста как слова и т. п., DSL

Практические элементы:

  • Лишние символы (например, красивое форматирование определений)
  • Арифметика
  • О/С
  • Строковые функции
  • Файлы и каталоги (в т. ч. globbing)

Немного истории

General-purpose macro processor и Macro_(computer_science).

  • TRAC

  • ML/I

  • GMP / PAGEN / ... — system generators
  • m4

Самый популярный вариант — препроцессор Си и другие макронадстройки над языками, однако это DSL (и таких бездна).

Более общий вариант — маркосы в Lisp, но и там макроподстановка не замещает функциональную парадигму и служит в первую очередь повышению читаемости.

M4

Чуть ли не единственный из известных.

Принцип:

  • На входе — текст, содержащий команды M4
  • Каждая команда, по мере поступления, выполняется, подставляя вместо себя результат своего выполнения (операция макроподстановки)
  • Этот результат может, в свою очередь, содержать команды M4, поэтому анализ текста возобновляется с позиции, в которую была сделана подстановка
  • На выходе — текст, не содержащий команд M4

Вот этот текст разумный http://mbreen.com/m4.html

Примеры просьба прощёлкивать! Если нет linux под рукой — можно воспользоваться любым online linux-окружением, например http://repl.it. При открытии редактора там в правой части запускается натуральная linux-консоль.

В ней можно запустить m4, но лучше что-нибудь вроде cat > o; echo "===="; m4 < o, чтобы ввод и вывод не перемешивались. Ввод заканчивается новой строкой и Ctrl+D для обозначения конца файла.

Макроопределение и макроподстановка

define(AUTHOR, W. Shakespeare)
`AUTHOR' is AUTHOR
  • Однако

define(AUTHOR, Me)
define(AUTHOR, A. Maclean)
`AUTHOR' is AUTHOR or Me?
  • А это не заработает:

define(AUTHOR, W. Shakespeare)
define(AUTHOR, A. Maclean)
`AUTHOR' is AUTHOR
  • Так что лучше брать макрос в кавычки всегда, и обмазывать dnl от лишних переводов строки

define(`AUTHOR', Me)dnl
define(`AUTHOR', A. Maclean)dnl
`AUTHOR' is AUTHOR or Me?

Вложенность

define(`definenum', `define(`num', `99')')
num
definenum
num
  • В то время как

define(`definenum', define(`num', `99'))
num

Условные операторы

На пространство имён

define(`macro', `--$1--')dnl
ifdef(`macro', QQ, QKRQ)
QQ
undefine(`macro')dnl
ifdef(`macro', QQ, QKRQ)
QKRQ
  • also dumpdef

Только на сопоставление

define(`a', b)dnl
ifelse(a, b, c, d)
ifelse(a, B, c, d)
  • и похитрее

define(`a', d)dnl
define(`e', b)dnl
ifelse(a, b, b-true, c, c-true, d, d-true, all-false)
ifelse(e, b, b-true, c, c-true, d, d-true, all-false)

Типы данных

  • eval() — вычисление арифметических выражений

  • translit(), index(), substr(), len(), regex(), … — строки

translit(`Highgest leet of all', `etl', 371)
  • (кавычки можно не ставить, но мало ли: слева точно литералы, а справа может быть и макро)

Параметрические макросы и циклы

Параметры — это просто $№ в теле макроподствновки

  • $# — количество, $* — все сразу, $@ — все сразу, но закавыченные (без дальнейшей макроподстановки)

define(`NONTERM', non-terminal)dnl
define(`param', `All: $*
All-quoted: $@
Number: $#; Second: $2')dnl
param(one, two by two, NONTERM, three)
param(`one', `two by two', `NONTERM', `three')

Цикл == рекурсия!

  • define(`len',`ifelse($1,,0,`eval(1+len(substr($1,1)))')')dnl
    len(qw qw)
    len()
    len

Остальные циклы (forloop, foreach cмоделированы в соотв. библиотеках)

Управление пространством имён и контексты

GNU m4:

  • запрет на распознавание некоторых встроенных макросов без скобок
  • макросы, имена которых нельзя распознать (но можно вызвать или посмотреть определение)
    define(`dit', `DIT!')
    dit
    define(`$O', `dit dit dit')
    $O
    defn(`$O')
    indir(`$O')
  • Временное переопределение, стек и суперпозиция определений
    define(`eval2', `pushdef(`incr', `eval(2+`$1')')eval(`$1')popdef(`incr')')
    eval2(incr(2)+incr(3))
    incr(3)

Потоки вывода

Часть текста можно перенаправить в синтетический поток, по окончании работы M4 они припишутся в конец в порядке нумерации (0 — основной поток)

one
divert(3)dnl
two
three
divert(1)dnl
four
five
divert(0)dnl
six
seven

Поток -1 не направляется никуда (а определённые макросы остаются!), а ещё поток можно закрыть и вставить по месту с помощью undivert()

divert(-1)
Здесь можно писать что угодно
значение имеют только макроопределения
define(`c', `divnum'> $1)
divert(2)
М. Ю. Лермонтов
divert(0)dnl
c(выхожу один)
divert(1)dnl
c(сквозь туман)
divert(0)dnl
c(я на дорогу)
undivert(1)dnl
c(кремнистый путь блестит)
  • Обратите внимание на отсутствие dnl в 6 строке

Если успеем

  • include()

    • Набор библиотек
  • Поддержка примитивов склейки (syscmd(), esyscmd(), sysval)

Макровзрыв

  • Контекста: актуально конечная последовательность вместо цикла
    • Пример: configure.ac

  • Мозга :)

Д/З

  1. Прощёлкать примеры из лекции и какую-нибудь методичку (например, эту) по M4; иметь под рукой учебник (его тоже можно при желании прочитать и прощёлкать)

  2. Скачать генератор домашнего задания prog1.m4 и запустить его так:

    • m4 -DSEED=произвольный_номер formgen.m4

    • По выбранному номеру будет сгенерирован текст задания. В задании требуется обработать с помощью m4 текстовый файл с произвольными параметрическими формулами, чтобы он превратился в программу на Си или на Паскале, которая их вычисляет. Программа, конечно, должна быть работающая ☺.

    • Задания бывают разной сложности — от 4 до 6 баллов
  3. Решение — программа на m4

    • Присылать на почту frbrgeorge@gmail.com

    • В виде приложенного файла

    • С обязательным указанием номера варианта

    • В поле «Subject» должно присутствовать словосочетание «Курс ПП»

LecturesCMC/AL/2021_11_29 (последним исправлял пользователь FrBrGeorge 2022-09-04 16:36:42)