(.module: lux (lux (control ["p" parser] ["ex" exception #+ exception:] [monad #+ Monad do] (monad [indexed #+ IxMonad])) (data [identity #+ Identity] [maybe] [product] [number] text/format (coll (dictionary ["dict" unordered #+ Dict]) (set ["set" unordered]) [sequence #+ Sequence] [list "list/" Functor Fold])) (concurrency [promise #+ Promise]) [macro] (macro ["s" syntax #+ Syntax syntax:]) (type abstract) [io #+ IO])) (type: #export (Procedure monad input output value) (-> input (monad [output value]))) (type: #export (Linear monad value) (All [keys] (Procedure monad keys keys value))) (type: #export (Affine monad permissions value) (All [keys] (Procedure monad keys [permissions keys] value))) (type: #export (Relevant monad permissions value) (All [keys] (Procedure monad [permissions keys] keys value))) (struct: (IxMonad Monad) (All [m] (-> (Monad m) (IxMonad (Procedure m)))) (def: (wrap value) (function (_ keys) (:: Monad wrap [keys value]))) (def: (bind f input) (function (_ keysI) (do Monad [[keysT value] (input keysI)] ((f value) keysT))))) (do-template [ ] [(def: #export (IxMonad (Procedure )) (IxMonad )) (def: #export ( procedure) (All [v] (-> (Linear v) ( v))) (do [[_ output] (procedure [])] (wrap output))) (def: #export ( procedure) (All [v] (-> ( v) (Linear v))) (function (_ keys) (do [output procedure] (wrap [keys output]))))] [IxMonad Identity identity.Monad run-pure lift-pure] [IxMonad IO io.Monad run-sync lift-sync] [IxMonad Promise promise.Monad run-async lift-async] ) (abstract: #export Ordered {} []) (abstract: #export Commutative {} []) (abstract: #export (Key mode key) {} [] (do-template [ ] [(def: (Ex [k] (-> [] (Key k))) (|>> :abstraction))] [ordered-key Ordered] [commutative-key Commutative] )) (type: #export OK (Key Ordered)) (type: #export CK (Key Commutative)) (abstract: #export (Res key value) {#.doc "A value locked by a key."} value (do-template [ ] [(def: #export ( value) (All [v] (Ex [k] (-> v (Affine (Key k) (Res k v))))) (function (_ keys) (:: wrap [[( []) keys] (:abstraction value)])))] [ordered-pure Identity identity.Monad Ordered ordered-key] [ordered-sync IO io.Monad Ordered ordered-key] [ordered-async Promise promise.Monad Ordered ordered-key] [commutative-sync IO io.Monad Commutative commutative-key] [commutative-pure Identity identity.Monad Commutative commutative-key] [commutative-async Promise promise.Monad Commutative commutative-key]) (do-template [ ] [(def: #export ( resource) (All [v k m] (-> (Res k v) (Relevant (Key m k) v))) (function (_ [key keys]) (:: wrap [keys (:representation resource)])))] [read-pure Identity identity.Monad] [read-sync IO io.Monad] [read-async Promise promise.Monad])) (exception: #export (index-cannot-be-repeated {index Nat}) (%n index)) (exception: #export amount-cannot-be-zero) (def: indices (Syntax (List Nat)) (s.tuple (loop [seen (set.new number.Hash)] (do p.Monad [done? s.end?] (if done? (wrap (list)) (do @ [head s.nat _ (p.assert (ex.construct index-cannot-be-repeated head) (not (set.member? seen head))) tail (recur (set.add head seen))] (wrap (list& head tail)))))))) (def: (no-op Monad) (All [m] (-> (Monad m) (Linear m Any))) (function (_ context) (:: Monad wrap [context []]))) (do-template [ ] [(syntax: #export ( {swaps ..indices}) (macro.with-gensyms [g!_ g!context] (case swaps #.Nil (wrap (list (` ((~! no-op) )))) (#.Cons head tail) (do macro.Monad [#let [max-idx (list/fold n/max head tail)] g!inputs (<| (monad.seq @) (list.repeat (inc max-idx)) (macro.gensym "input")) #let [g!outputs (|> (monad.fold maybe.Monad (function (_ from to) (do maybe.Monad [input (list.nth from g!inputs)] (wrap (sequence.add input to)))) (: (Sequence Code) sequence.empty) swaps) maybe.assume sequence.to-list) g!inputsT+ (list/map (|>> (~) ..CK (`)) g!inputs) g!outputsT+ (list/map (|>> (~) ..CK (`)) g!outputs)]] (wrap (list (` (: (All [(~+ g!inputs) (~ g!context)] (Procedure (~! ) [(~+ g!inputsT+) (~ g!context)] [(~+ g!outputsT+) (~ g!context)] .Any)) (function ((~ g!_) [(~+ g!inputs) (~ g!context)]) (:: (~! ) (~' wrap) [[(~+ g!outputs) (~ g!context)] []]))))))))))] [exchange-pure Identity identity.Monad] [exchange-sync IO io.Monad] [exchange-async Promise promise.Monad]) (def: amount (Syntax Nat) (do p.Monad [raw s.nat _ (p.assert (ex.construct amount-cannot-be-zero []) (n/> +0 raw))] (wrap raw))) (do-template [ ] [(syntax: #export ( {amount ..amount}) (macro.with-gensyms [g!_ g!context] (do macro.Monad [g!keys (<| (monad.seq @) (list.repeat amount) (macro.gensym "keys"))] (wrap (list (` (: (All [(~+ g!keys) (~ g!context)] (Procedure (~! ) [ (~ g!context)] [ (~ g!context)] .Any)) (function ((~ g!_) [ (~ g!context)]) (:: (~! ) (~' wrap) [[ (~ g!context)] []])))))))))] [group-pure Identity identity.Monad (~+ g!keys) [(~+ g!keys)]] [group-sync IO io.Monad (~+ g!keys) [(~+ g!keys)]] [group-async Promise promise.Monad (~+ g!keys) [(~+ g!keys)]] [un-group-pure Identity identity.Monad [(~+ g!keys)] (~+ g!keys)] [un-group-sync IO io.Monad [(~+ g!keys)] (~+ g!keys)] [un-group-async Promise promise.Monad [(~+ g!keys)] (~+ g!keys)] )