(.using [library [lux (.except Type static has) [abstract [monad (.only do)] [monoid (.only Monoid)]] [control ["[0]" try (.only Try)] ["[0]" exception (.only exception:)]]]] [/ ["/[0]" limit (.only Limit) ["/[0]" stack (.only Stack)] ["/[0]" registry (.only Registry)]] [/// [encoding [unsigned (.only U2)]] [type (.only Type) [category (.only Method)]]]]) (type: .public Environment (Record [#limit Limit #stack (Maybe Stack)])) (template [ ] [(def: .public ( type) (-> (Type Method) (Try Environment)) (do try.monad [limit ( type)] (in [#limit limit #stack {.#Some /stack.empty}])))] [static /limit.static] [virtual /limit.virtual] ) (type: .public Condition (-> Environment (Try Environment))) (implementation: .public monoid (Monoid Condition) (def: identity (|>> {try.#Success})) (def: (composite left right) (function (_ environment) (do try.monad [environment (left environment)] (right environment))))) (exception: .public discontinuity) (def: .public (stack environment) (-> Environment (Try Stack)) (case (the ..#stack environment) {.#Some stack} {try.#Success stack} {.#None} (exception.except ..discontinuity []))) (def: .public discontinue (-> Environment Environment) (.has ..#stack {.#None})) (exception: .public (mismatched_stacks [expected Stack actual Stack]) (exception.report "Expected" (/stack.format expected) "Actual" (/stack.format actual))) (def: .public (continue expected environment) (-> Stack Environment (Try [Stack Environment])) (case (the ..#stack environment) {.#Some actual} (if (# /stack.equivalence = expected actual) {try.#Success [actual environment]} (exception.except ..mismatched_stacks [expected actual])) {.#None} {try.#Success [expected (.has ..#stack {.#Some expected} environment)]})) (def: .public (consumes amount) (-> U2 Condition) ... TODO: Revisit this definition once lenses/optics have been implemented, ... since it can probably be simplified with them. (function (_ environment) (do try.monad [previous (..stack environment) current (/stack.pop amount previous)] (in (.has ..#stack {.#Some current} environment))))) (def: .public (produces amount) (-> U2 Condition) (function (_ environment) (do try.monad [previous (..stack environment) current (/stack.push amount previous) .let [limit (|> environment (the [..#limit /limit.#stack]) (/stack.max current))]] (in (|> environment (.has ..#stack {.#Some current}) (.has [..#limit /limit.#stack] limit)))))) (def: .public (has registry) (-> Registry Condition) (|>> (revised [..#limit /limit.#registry] (/registry.has registry)) {try.#Success}))