(defn do-alt [alts clauses]
(assert (even? (count clauses)) "unbalanced clauses")
(let [clauses (core/partition 2 clauses)
opt? #(keyword? (first %))
opts (filter opt? clauses)
clauses (remove opt? clauses)
[clauses bindings]
(core/reduce
(fn [[clauses bindings] [ports expr]]
(let [ports (if (vector? ports) ports [ports])
[ports bindings]
(core/reduce
(fn [[ports bindings] port]
(if (vector? port)
(let [[port val] port
gp (gensym)
gv (gensym)]
[(conj ports [gp gv]) (conj bindings [gp port] [gv val])])
(let [gp (gensym)]
[(conj ports gp) (conj bindings [gp port])])))
[[] bindings] ports)]
[(conj clauses [ports expr]) bindings]))
[[] []] clauses)
gch (gensym "ch")
gret (gensym "ret")]
`(let [~@(mapcat identity bindings)
[val# ~gch :as ~gret] (~alts [~@(apply concat (core/map first clauses))] ~@(apply concat opts))]
(cond
~@(mapcat (fn [[ports expr]]
[`(or ~@(core/map (fn [port]
`(= ~gch ~(if (vector? port) (first port) port)))
ports))
(if (and (seq? expr) (vector? (first expr)))
`(let [~(first expr) ~gret] ~@(rest expr))
expr)])
clauses)
(= ~gch :default) val#))))