module til-copyprop-rev
imports til-opt-lib
strategies

  io-til-copyprop-rev = 
    io-wrap(copyprop-rev)

  copyprop-rev = 
    CopyPropRev
    <+ copyprop-rev-declaration
    <+ copyprop-rev-assign 
    <+ copyprop-rev-block
    <+ copyprop-rev-if
    <+ copyprop-rev-while
    <+ all(copyprop-rev)

  copyprop-rev-block =
    Block({| CopyPropRev : map(copyprop-rev) |})

  copyprop-rev-declaration = 
    (?Declaration(x) <+ ?DeclarationTyped(x, t))
    ; new-CopyPropRev(|x, x)

  copyprop-rev-assign = 
    Assign(?x, copyprop-rev => e)
    ; undefine-CopyPropRev(|x)
    ; where( innermost-scope-CopyPropRev => z )
    ; if <?Var(y)> e then
        rules( CopyPropRev.z : Var(y) -> Var(x) depends on [(x,x),(y,y)] )
      end

  copyprop-rev-if =
    IfElse(copyprop-rev, id, id)
    ; (IfElse(id, copyprop-rev, id) /CopyPropRev\ IfElse(id,id,copyprop-rev))

  copyprop-rev-while =
    ?While(_, _)
    ; (/CopyPropRev\* While(copyprop-rev, copyprop-rev))

  innermost-scope-CopyPropRev = 
    get-var-names => vars
    ; innermost-scope-CopyPropRev(elem-of(|vars))