Как вы создаете переписывающий проход на основе того, ссылаются ли два выражения на одно и то же имя границы?

Как вы находите и переписываете выражения, которые относятся к одному и тому же связанному имени? Например, в выражении

let xs = ...
in ...map f xs...map g xs...

как выражение map f xs, так и выражение map g xs относятся к одному и тому же связанному имени, а именно к xs. Есть ли какой-либо стандартный анализ компилятора, который позволил бы нам идентифицировать эту ситуацию и переписать два выражения map, например,

let xs = ...
    e = unzip (map (f *** g) xs)
in ...fst e...snd e...

Я думал о проблеме с точки зрения обхода дерева. Например, учитывая AST:

data Ast = Map (a -> b) -> Ast -> Ast
         | Var String
         | ...

мы могли бы попытаться написать обход дерева для обнаружения этого случая, но это кажется трудным, так как два узла map, которые относятся к тому же Var, могут появляться в самых разных местах дерева. Этот анализ кажется легче сделать, если вы перевернули все ссылки в AST, сделав его графиком, но я хотел посмотреть, есть ли какие-либо альтернативы этому подходу.

Ответы

Ответ 1

Я думаю, что вы ищете набор программных преобразований, обычно называемых Tupling, Fusion и Supercompilation, которые подпадают под более общую теорию преобразования Unfold/Fold. Вы можете достичь того, чего хотите, следующим образом.

Сначала выполните спекулятивные оценки (разворачивание) путем "управления" определением карты по аргументам, что порождает две новые псевдопрограммы, в зависимости от того, имеет ли xs форму y: ys или []. В псевдокоде:

let y:ys = ...
in ...(f y):(map f ys)...(g y):(map g ys)...

let [] = ...
in ...[]...[]...

Затем выполните абстракции для общей структуры (Tupling) и обобщений (Folding) относительно исходной программы, чтобы иначе остановить вечное разворачивание:

let xs = ...
in ...(fst tuple)...(snd tuple)...
where tuple = generalisation xs
      generalisation [] = ([],[])
      generalisation (y:ys) = let tuple = generalisation ys
                              in ((f y):(fst tuple),(g y):(snd tuple))

Надеюсь, это дает вам представление, но программа tranformation - это поле исследований в своем собственном праве, и ее трудно объяснить, не рисуя ациклические ориентированные графики.