Closed TonitaN closed 3 years ago
Я никого не прикрепляю к этой заявке, но поскольку @StepanBog будет загружен резолюциями ещё достаточно долго, похоже, что кодогенерацию придётся делать @ylyxa . Если решите иначе --- тоже ок.
Даже при кодогенерации код лучше форматировать по-человечески:
Equal {
(e.1)(e.1) = True;
(e.1)(e.2) = False;
}
Inequal {
(e.1)(e.1) = False;
(e.1)(e.2) = True;
}
Infix_[Const] {
e.1 [Const] e.2 = True;
e.Z = False;
}
No_[Const] {
e.1 [Const] e.2 = False;
e.Z = True;
}
Repl_[Const1]_[Const2] {
e.1 [Const1] e.2 = e.1 [Const2] <Repl_[Const1]_[Const2] e.2>;
e.Z = e.Z;
}
https://github.com/bmstu-iu9/refal-5-lambda/blob/master/doc/style-guide.md
@Mazdaywik , спасибо!
@ylyxa, придётся прикрепить вас к заявкам по кодогенерации. Если будет неохота делать оптимизации (расшаривание аргумента в заявке #8 ), не делайте, это не повлияет на оценку, на вас и так много заданий.
Теперь уже можно реализовывать последний этап преобразования - кодогенерацию. Поскольку подразумевается, что все формулы модели приведены к КНФ (а значит, и вся модель описывается с помощью КНФ), можно генерировать код, рассчитывая, что формула имеет вид либо
(AND F1 ... Fn)
, либо(OR L1 ... Ln)
, гдеFi
--- это дизъюнкты, аLi
--- литералы. В этой заявке рассматривается преобразование только последних в Рефал-форму. Желательно это делать в двух формах --- перевод в базисный Рефал и перевод в расширенный Рефал. Сейчас сосредоточимся только на расширенном. Отличия для базисного Рефала будут только в форме функций (на это будет отдельная заявка), всё остальное абсолютно такое же. Для каждой переменной, определённой в блокеdeclare_fun
, порождаем соответствующее имя е-переменной. Определимconvert([VarName]) = e.[VarName']
, где[VarName']
получается из[VarName]
заменой всех символов, кроме латинских букв, цифр, знаков подчёркивания и дефисов, на буквенные идентификаторы.(= S1 S2)
, заводим функциюEqual
следующего содержания.Тогда
convert( (= S1 S2) ) = <Equal (convert(S1)) (convert(S2))>
. Аргументы заключены в структурные скобки.(not (= S1 S2))
, заводим функциюInequal
следующего содержания.Тогда
convert( (not (= S1 S2)) ) = <Inequal (convert(S1)) (convert(S2))>
.(str.contains S1 [Const])
, заводим функциюInfix_[Const]
(с уникальным именем и содержанием для всех различных констант [Const]).Тогда
convert( (str.contains S1 [Const]) ) = <Infix_[Const] convert(S1)>
. В названии функции[Const]
не закавычен, в аргументе[Const]
пишем как'Const'
(апострофы вместо двойных кавычек вsmt
). Если в[Const]
есть символы кроме латинских букв и цифр, экранируем их в имени функции --- заменяем на уникальный буквенный идентификатор и выделяем знаками подчёркивания. Если в[Const]
есть апострофы или бэкслеш --- экранируем их бэкслешем в теле функции.(not (str.contains S1 [Const]))
, заводим функциюNo_[Const]
(с уникальным именем и содержанием для всех различных констант [Const]).Тогда
convert( (not (str.contains S1 [Const])) ) = <No_[Const] convert(S1)>
. Экранирование и кодировка та же, что в пункте 3.(str.replace_all S1 [Const1] [Const2])
, тогда заводим функциюRepl_[Const1]_[Const2]
(уникальную для каждой пары[Const1]
+[Const2]
).Тогда
convert( (str.replace_all S1 [Const1] [Const2]) ) = <Repl_[Const1]_[Const2] convert(S1)>
. Замечания про экранирование те же, что в пункте 3.convert (str.++ S1 F1) = S1 convert(F1)
.convert ([const]) = 'screen_const([const])'
, где[const]
--- это токен "константа", аscreen_const
--- экранирование апострофа и бэкслэша с помощью бэкслэша (как в п.3).Это базовый алгоритм кодогенерации, в котором самое сложное --- это экранировать символы в именах. У него будет одна оптимизация, связанная с особыми дизъюнктами в КНФ --- теми, в которых есть как минимум два литерала вида либо
(str.contains S P)
, либо(not (str.contains S Q))
(где строкиP
иQ
могут быть разными, а вот первый аргумент,S
, один и тот же). Но эта оптимизация будет описана уже в следующей заявке по кодогенерации.