packages feed

atomo-0.2.1: prelude/continuation.atomo

{ define: *dynamic-winds* as: []

  (o: Object) call/cc := o call/cc: []
  (o: Object) call/cc: as :=
    { cc |
      winds = *dynamic-winds* _?

      new = cc clone do:
        { yield: v :=
            { dynamic-unwind: winds
                delta: (*dynamic-winds* _? length - winds length)

              cc yield: v
            } call
        }

      o call: (new . as)
    } raw-call/cc

  (v: Block) before: (b: Block) := v before: b after: { @ok }
  (v: Block) after: (a: Block) := v before: { @ok } after: a

  (v: Block) before: (b: Block) after: (a: Block) :=
    { b call

      *dynamic-winds* =! ((b -> a) . *dynamic-winds* _?)

      res = v call

      a call

      *dynamic-winds* =! *dynamic-winds* _? tail

      res
    } call

  (init: Block) wrap: cleanup do: action :=
    { action call: [x] } before: { x = init call } in-context after: { cleanup call: [x] }

  dynamic-unwind: to delta: d :=
    condition: {
      (*dynamic-winds* _? == to) -> @ok

      (d < 0) ->
        { dynamic-unwind: to tail delta: (d + 1)
          to head from call
          *dynamic-winds* =! to
          @ok
        } call

      otherwise ->
        { post = *dynamic-winds* _? head to
          *dynamic-winds* =! *dynamic-winds* _? tail
          post call
          dynamic-unwind: to delta: (d - 1)
        } call
    }
} call