(.using [library [lux (.except global) [control ["<>" parser (.only) ["<[0]>" code (.only Parser)]]] [data [collection ["[0]" list (.open: "[1]#[0]" functor mix)]]] ["[0]" macro (.only) [syntax (.only syntax:)] ["[0]" code]]]] ["[0]" //]) (type: .public (IxMonad m) (Interface (is (All (_ p a) (-> a (m p p a))) in) (is (All (_ ii it io vi vo) (-> (-> vi (m it io vo)) (m ii it vi) (m ii io vo))) then))) (type: Binding [Code Code]) (def: binding (Parser Binding) (<>.and .any .any)) (type: Context (Variant {#Macro Symbol Code} {#Binding Binding})) (def: global (Parser Symbol) (//.do <>.monad [[module short] .symbol _ (<>.assertion "" (case module "" false _ true))] (in [module short]))) (def: context (Parser Context) (<>.or (<>.and ..global .any) binding)) (def: (pair_list [binding value]) (All (_ a) (-> [a a] (List a))) (list binding value)) (def: named_monad (Parser [(Maybe Text) Code]) (<>.either (.tuple (<>.and (# <>.monad each (|>> {.#Some}) .local) .any)) (# <>.monad each (|>> [{.#None}]) .any))) (syntax: .public (do [[?name monad] ..named_monad context (.tuple (<>.some context)) expression .any]) (macro.with_symbols [g!_ g!then] (let [body (list#mix (function (_ context next) (case context {#Macro macro parameter} (` ((~ (code.symbol macro)) (~ parameter) (~ next))) {#Binding [binding value]} (` ((~ g!then) (.function ((~ g!_) (~ binding)) (~ next)) (~ value))))) expression (list.reversed context))] (in (list (case ?name {.#Some name} (let [name (code.local name)] (` (let [(~ name) (~ monad) [..in (~' in) ..then (~ g!then)] (~ name)] (~ body)))) {.#None} (` (let [[..in (~' in) ..then (~ g!then)] (~ monad)] (~ body)))))))))