module til-cse
imports til-opt-lib
strategies

  io-til-cse = 
    io-wrap(cse)

  cse = 
    CSE
    <+ cse-declaration
    <+ cse-assign 
    <+ cse-if
    <+ cse-block
    <+ cse-while
    <+ all(cse)

  cse-block =
    Block({| CSE : map(cse) |})

  cse-declaration = 
    (?Declaration(x) <+ ?DeclarationTyped(x, t))
    ; new-CSE(|x, x)

  cse-assign = 
    Assign(?x, cse => e)
    ; undefine-CSE(|x)
    ; if <not(contains(|Var(x)))> e then
        where( innermost-scope-CSE => z )
        ; where( get-var-dependencies => deps )
        ; rules( CSE.z : e -> Var(x) depends on deps )
      end

  cse-if =
    IfElse(cse, id, id)
    ; (IfElse(id, cse, id) /CSE\ IfElse(id,id,cse))

  cse-while =
    ?While(_, _)
    ; (/CSE\* While(cse, cse))

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