From e53c1a090eb9cfac3cb23d10d981648d02518ed1 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Fri, 13 Aug 2021 04:18:57 -0400 Subject: Made program: specify its bindings the same way as syntax:. --- stdlib/source/library/lux.lux | 328 ++++++++++++++++++++++++------------------ 1 file changed, 190 insertions(+), 138 deletions(-) (limited to 'stdlib/source/library/lux.lux') diff --git a/stdlib/source/library/lux.lux b/stdlib/source/library/lux.lux index 8b03f390b..16123c586 100644 --- a/stdlib/source/library/lux.lux +++ b/stdlib/source/library/lux.lux @@ -1283,40 +1283,40 @@ (failure "Wrong syntax for list&")} (list\reverse xs))) -(macro:' .public (Tuple tokens) +(macro:' .public (Variant tokens) (#Item [(tag$ ["library/lux" "doc"]) (text$ ("lux text concat" - ("lux text concat" "... Tuple types:" __paragraph) + ("lux text concat" "... Variant types:" __paragraph) ("lux text concat" - ("lux text concat" "(Tuple Text Int Bit)" __paragraph) + ("lux text concat" "(Variant Text Int Bit)" __paragraph) ("lux text concat" - ("lux text concat" "... Any." __paragraph) - "(&)"))))] + ("lux text concat" "... Nothing." __paragraph) + "(Variant)"))))] #End) ({#End - (in_meta (list (identifier$ ["library/lux" "Any"]))) + (in_meta (list (identifier$ ["library/lux" "Nothing"]))) (#Item last prevs) - (in_meta (list (list\fold (function'' [left right] (form$ (list (tag$ ["library/lux" "Product"]) left right))) + (in_meta (list (list\fold (function'' [left right] (form$ (list (tag$ ["library/lux" "Sum"]) left right))) last prevs)))} (list\reverse tokens))) -(macro:' .public (Variant tokens) +(macro:' .public (Tuple tokens) (#Item [(tag$ ["library/lux" "doc"]) (text$ ("lux text concat" - ("lux text concat" "... Variant types:" __paragraph) + ("lux text concat" "... Tuple types:" __paragraph) ("lux text concat" - ("lux text concat" "(Variant Text Int Bit)" __paragraph) + ("lux text concat" "(Tuple Text Int Bit)" __paragraph) ("lux text concat" - ("lux text concat" "... Nothing." __paragraph) - "(Variant)"))))] + ("lux text concat" "... Any." __paragraph) + "(&)"))))] #End) ({#End - (in_meta (list (identifier$ ["library/lux" "Nothing"]))) + (in_meta (list (identifier$ ["library/lux" "Any"]))) (#Item last prevs) - (in_meta (list (list\fold (function'' [left right] (form$ (list (tag$ ["library/lux" "Sum"]) left right))) + (in_meta (list (list\fold (function'' [left right] (form$ (list (tag$ ["library/lux" "Product"]) left right))) last prevs)))} (list\reverse tokens))) @@ -1380,12 +1380,16 @@ tokens)) (def:''' .public Or - #End + (#Item [(tag$ ["library/lux" "doc"]) + (text$ "An alias for the Variant type constructor.")] + #End) Macro ..Variant) (def:''' .public And - #End + (#Item [(tag$ ["library/lux" "doc"]) + (text$ "An alias for the Tuple type constructor.")] + #End) Macro ..Tuple) @@ -1463,7 +1467,7 @@ (form$ (list op a1 a2))} op)) -(def:''' .private (function\flip func) +(def:''' .private (function\flipped func) #End (All [a b c] (-> (-> a b c) (-> b a c))) @@ -1482,7 +1486,7 @@ #End) ({(#Item op tokens') ({(#Item first nexts) - (in_meta (list (list\fold (function\flip (right_associativity op)) first nexts))) + (in_meta (list (list\fold (function\flipped (right_associativity op)) first nexts))) _ (failure "Wrong syntax for _$")} @@ -1653,14 +1657,14 @@ Type (All [a] ($' List (Tuple Text a)))) -(def:''' .private (get k plist) +(def:''' .private (plist\value k plist) #End (All [a] (-> Text ($' PList a) ($' Maybe a))) ({(#Item [[k' v] plist']) (if (text\= k k') (#Some v) - (get k plist')) + (plist\value k plist')) #End #None} @@ -1679,33 +1683,6 @@ _ ($_ text\compose module "." name)} module))) -(def:''' .private (get_meta tag def_meta) - #End - (-> Name Code ($' Maybe Code)) - (let' [[module name] tag] - ({[_ (#Record def_meta)] - ({(#Item [key value] def_meta') - ({[_ (#Tag [module' name'])] - ({[#1 #1] - (#Some value) - - _ - (get_meta tag (record$ def_meta'))} - [(text\= module module') - (text\= name name')]) - - _ - (get_meta tag (record$ def_meta'))} - key) - - #End - #None} - def_meta) - - _ - #None} - def_meta))) - (def:''' .private (global_identifier full_name state) #End (-> Name ($' Meta Name)) @@ -1725,11 +1702,11 @@ #None (#Left ($_ text\compose "Unknown definition: " (name\encode full_name)))} - (get name definitions)) + (plist\value name definitions)) #None (#Left ($_ text\compose "Unknown module: " module " @ " (name\encode full_name)))} - (get module modules)))) + (plist\value module modules)))) (def:''' .private (code_list expression) #End @@ -2011,7 +1988,7 @@ (-> (-> b c) (-> a b) (-> a c))) (function' [x] (f (g x)))) -(def:''' .private (get_name x) +(def:''' .private (identifier_name x) #End (-> Code ($' Maybe Name)) ({[_ (#Identifier sname)] @@ -2021,7 +1998,7 @@ #None} x)) -(def:''' .private (get_tag x) +(def:''' .private (tag_name x) #End (-> Code ($' Maybe Name)) ({[_ (#Tag sname)] @@ -2031,7 +2008,7 @@ #None} x)) -(def:''' .private (get_short x) +(def:''' .private (identifier_short x) #End (-> Code ($' Maybe Text)) ({[_ (#Identifier "" sname)] @@ -2149,7 +2126,7 @@ _ (failure "Wrong syntax for template")} - [(monad\map maybe_monad get_short bindings) + [(monad\map maybe_monad identifier_short bindings) (monad\map maybe_monad tuple_list data)]) _ @@ -2282,9 +2259,9 @@ Text Text Text ($' Maybe Macro)) (do maybe_monad - [$module (get module modules) + [$module (plist\value module modules) gdef (let' [{#module_hash _ #module_aliases _ #definitions bindings #imports _ #tags tags #types types #module_annotations _ #module_state _} ("lux type check" Module $module)] - (get name bindings))] + (plist\value name bindings))] ({(#Left [r_module r_name]) (macro' modules current_module r_module r_name) @@ -3265,7 +3242,7 @@ #.None (failure "Wrong syntax for macro:"))) -(def: (find f xs) +(def: (list\one f xs) (All [a b] (-> (-> a (Maybe b)) (List a) (Maybe b))) (case xs @@ -3275,7 +3252,7 @@ (#Item x xs') (case (f x) #None - (find f xs') + (list\one f xs') (#Some y) (#Some y)))) @@ -3329,7 +3306,7 @@ _ (#Left "Wrong syntax for else"))) -(def: (text\split_all_with splitter input) +(def: (text\all_split_by splitter input) (-> Text Text (List Text)) (case (..index splitter input) #None @@ -3337,12 +3314,12 @@ (#Some idx) (list& ("lux text clip" 0 idx input) - (text\split_all_with splitter - (let [after_offset ("lux i64 +" 1 idx) - after_length ("lux i64 -" - after_offset - ("lux text size" input))] - ("lux text clip" after_offset after_length input)))))) + (text\all_split_by splitter + (let [after_offset ("lux i64 +" 1 idx) + after_length ("lux i64 -" + after_offset + ("lux text size" input))] + ("lux text clip" after_offset after_length input)))))) (def: (item idx xs) (All [a] @@ -3481,25 +3458,19 @@ #scopes scopes #type_context types #host host #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} state] - (case (get name modules) + (case (plist\value name modules) (#Some module) (#Right state module) _ (#Left ($_ text\compose "Unknown module: " name)))))) -(def: get_current_module - (Meta Module) - (do meta_monad - [module_name current_module_name] - (module module_name))) - (def: (type_tag [module name]) (-> Name (Meta [Nat (List Name) Bit Type])) (do meta_monad [=module (..module module) .let [{#module_hash _ #module_aliases _ #definitions bindings #imports _ #tags tags_table #types types #module_annotations _ #module_state _} =module]] - (case (get name tags_table) + (case (plist\value name tags_table) (#Some output) (in_meta output) @@ -3522,7 +3493,7 @@ (do meta_monad [=module (..module module) .let [{#module_hash _ #module_aliases _ #definitions bindings #imports _ #tags tags #types types #module_annotations _ #module_state _} =module]] - (case (get name types) + (case (plist\value name types) (#Some [tags exported? (#Named _ _type)]) (case (interface_methods _type) (#Some members) @@ -3537,7 +3508,7 @@ _ (in_meta #None))) -(def: get_expected_type +(def: expected_type (Meta Type) (function (_ state) (let [{#info info #source source #current_module _ #modules modules @@ -3552,10 +3523,25 @@ (#Left "Not expecting any type."))))) (macro: .public (implementation tokens) - {#.doc "Not meant to be used directly. Prefer 'implementation:'."} + {#.doc (text$ ($_ "lux text concat" + "... Express a value that implements an interface." ..\n + "(: (Order Int)" ..\n + " (implementation" ..\n + " (def: &equivalence equivalence)" ..\n + " (def: (< test subject)" ..\n + " (< test subject))" ..\n + " (def: (<= test subject)" ..\n + " (or (< test subject)" ..\n + " (= test subject)))" ..\n + " (def: (> test subject)" ..\n + " (> test subject))" ..\n + " (def: (>= test subject)" ..\n + " (or (> test subject)" ..\n + " (= test subject)))" ..\n + " ))"))} (do meta_monad [tokens' (monad\map meta_monad expansion tokens) - struct_type get_expected_type + struct_type ..expected_type tags+type (record_slots struct_type) tags (: (Meta (List Name)) (case tags+type @@ -3572,7 +3558,7 @@ (function (_ token) (case token (^ [_ (#Form (list [_ (#Text "lux def")] [_ (#Identifier "" tag_name)] value meta export_policy))]) - (case (get tag_name tag_mappings) + (case (plist\value tag_name tag_mappings) (#Some tag) (in [tag value]) @@ -3640,9 +3626,10 @@ (macro: .public (implementation: tokens) {#.doc (text$ ($_ "lux text concat" - "... Definition of structures ala ML." ..\n + "... Interface implementation." ..\n "(implementation: .public order" ..\n " (Order Int)" ..\n + ..\n " (def: &equivalence equivalence)" ..\n " (def: (< test subject)" ..\n " (< test subject))" ..\n @@ -3814,7 +3801,7 @@ (macro: .public (interface: tokens) {#.doc (text$ ($_ "lux text concat" - "... Definition of interfaces/signatures ala ML." ..\n + "... Interface definition." ..\n "(interface: .public (Order a)" ..\n " (: (Equivalence a)" ..\n " &equivalence)" ..\n @@ -3855,6 +3842,7 @@ (template [ ] [(def: .public ( value) + {#.doc "Safe type-casting for I64 values."} (-> (I64 Any) ) (:as value))] @@ -3947,24 +3935,24 @@ _ (in_meta [#.End parts]))) -(def: (text\split! at x) +(def: (text\split_at' at x) (-> Nat Text [Text Text]) [("lux text clip" 0 at x) ("lux text clip" at (|> x "lux text size" ("lux i64 -" at)) x)]) -(def: (text\split_with token sample) +(def: (text\split_by token sample) (-> Text Text (Maybe [Text Text])) (do ..maybe_monad [index (..index token sample) - .let [[pre post'] (text\split! index sample) - [_ post] (text\split! ("lux text size" token) post')]] + .let [[pre post'] (text\split_at' index sample) + [_ post] (text\split_at' ("lux text size" token) post')]] (in [pre post]))) (def: (replaced pattern replacement template) (-> Text Text Text Text) ((: (-> Text Text Text) (function (recur left right) - (case (..text\split_with pattern right) + (case (..text\split_by pattern right) (#.Some [pre post]) (recur ($_ "lux text concat" left pre replacement) post) @@ -3982,6 +3970,7 @@ (replaced ..contextual_reference context))) (def: .public module_separator + {#.doc "Character used to separate the parts of module names."} "/") (def: parallel_hierarchy_sigil @@ -3989,8 +3978,8 @@ (def: (normal_parallel_path' hierarchy root) (-> Text Text Text) - (case [(text\split_with ..module_separator hierarchy) - (text\split_with ..parallel_hierarchy_sigil root)] + (case [(text\split_by ..module_separator hierarchy) + (text\split_by ..parallel_hierarchy_sigil root)] [(#.Some [_ hierarchy']) (#.Some ["" root'])] (normal_parallel_path' hierarchy' root') @@ -4002,7 +3991,7 @@ (def: (normal_parallel_path hierarchy root) (-> Text Text (Maybe Text)) - (case (text\split_with ..parallel_hierarchy_sigil root) + (case (text\split_by ..parallel_hierarchy_sigil root) (#.Some ["" root']) (#.Some (normal_parallel_path' hierarchy root')) @@ -4047,7 +4036,7 @@ module)) relatives - (let [parts (text\split_all_with ..module_separator relative_root) + (let [parts (text\all_split_by ..module_separator relative_root) jumps ("lux i64 -" 1 relatives)] (if (n/< (list\size parts) jumps) (let [prefix (|> parts @@ -4150,7 +4139,7 @@ #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} [current_module modules])] - (case (get module modules) + (case (plist\value module modules) (#Some =module) (let [to_alias (list\map (: (-> [Text Global] (List Text)) @@ -4217,21 +4206,21 @@ #scopes scopes #type_context types #host host #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} - (find (: (-> Scope (Maybe Type)) - (function (_ env) - (case env - {#name _ - #inner _ - #locals {#counter _ #mappings locals} - #captured {#counter _ #mappings closure}} - (on_either (find (: (-> [Text [Type Any]] (Maybe Type)) - (function (_ [bname [type _]]) - (if (text\= name bname) - (#Some type) - #None)))) - (: (List [Text [Type Any]]) locals) - (: (List [Text [Type Any]]) closure))))) - scopes))) + (list\one (: (-> Scope (Maybe Type)) + (function (_ env) + (case env + {#name _ + #inner _ + #locals {#counter _ #mappings locals} + #captured {#counter _ #mappings closure}} + (on_either (list\one (: (-> [Text [Type Any]] (Maybe Type)) + (function (_ [bname [type _]]) + (if (text\= name bname) + (#Some type) + #None)))) + (: (List [Text [Type Any]]) locals) + (: (List [Text [Type Any]]) closure))))) + scopes))) (def: (definition_type name state) (-> Name Lux (Maybe Type)) @@ -4240,12 +4229,12 @@ #scopes scopes #type_context types #host host #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} state] - (case (get v_module modules) + (case (plist\value v_module modules) #None #None (#Some {#definitions definitions #module_hash _ #module_aliases _ #imports _ #tags tags #types types #module_annotations _ #module_state _}) - (case (get v_name definitions) + (case (plist\value v_name definitions) #None #None @@ -4264,12 +4253,12 @@ #scopes scopes #type_context types #host host #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} state] - (case (get v_module modules) + (case (plist\value v_module modules) #None (#Left (text\compose "Unknown definition: " (name\encode name))) (#Some {#definitions definitions #module_hash _ #module_aliases _ #imports _ #tags tags #types types #module_annotations _ #module_state _}) - (case (get v_name definitions) + (case (plist\value v_name definitions) #None (#Left (text\compose "Unknown definition: " (name\encode name))) @@ -4698,7 +4687,7 @@ list\join)]] (in (list\compose defs openings)))) -(macro: .public (refer tokens) +(macro: (refer tokens) (case tokens (^ (list& [_ (#Text module_name)] options)) (do meta_monad @@ -4731,9 +4720,9 @@ (form$ (list& (text$ (..replaced ..contextual_reference module_alias alias)) (list\map local_identifier$ structs)))) r_opens)] - (` (..refer (~ (text$ module_name)) - (~+ localizations) - (~+ openings))))) + (` ((~! ..refer) (~ (text$ module_name)) + (~+ localizations) + (~+ openings))))) (macro: .public (module: tokens) {#.doc (text$ ($_ "lux text concat" @@ -5000,7 +4989,7 @@ branches)) (case (: (Maybe (List Code)) (do maybe_monad - [bindings' (monad\map maybe_monad get_short bindings) + [bindings' (monad\map maybe_monad identifier_short bindings) data' (monad\map maybe_monad tuple_list data)] (let [num_bindings (list\size bindings')] (if (every? (|>> ("lux i64 =" num_bindings)) @@ -5156,7 +5145,7 @@ (case fragment (#Documentation_Comment comment) (|> comment - (text\split_all_with ..\n) + (text\all_split_by ..\n) (list\map (function (_ line) ($_ text\compose "... " line ..\n))) (text\join_with "")) @@ -5262,11 +5251,11 @@ (if (every? identifier? inits) (do meta_monad [inits' (: (Meta (List Name)) - (case (monad\map maybe_monad get_name inits) + (case (monad\map maybe_monad identifier_name inits) (#Some inits') (in_meta inits') #None (failure "Wrong syntax for loop"))) init_types (monad\map meta_monad type_definition inits') - expected get_expected_type] + expected ..expected_type] (in_meta (list (` (("lux type check" (-> (~+ (list\map type_code init_types)) (~ (type_code expected))) @@ -5297,8 +5286,8 @@ [slots (: (Meta [Name (List Name)]) (case (: (Maybe [Name (List Name)]) (do maybe_monad - [hslot (get_tag hslot') - tslots (monad\map maybe_monad get_tag tslots')] + [hslot (..tag_name hslot') + tslots (monad\map maybe_monad ..tag_name tslots')] (in [hslot tslots]))) (#Some slots) (in_meta slots) @@ -5318,7 +5307,7 @@ pattern (record$ (list\map (: (-> Name [Code Code]) (function (_ [module name]) (let [tag (tag$ [module name])] - (case (get name slot_pairings) + (case (plist\value name slot_pairings) (#Some binding) [tag binding] #None [tag g!_])))) tags))]] @@ -5483,6 +5472,27 @@ )) (macro: .public (static tokens) + {#.doc (example "Resolves the names of definitions to their values at compile-time, assuming their values are either:" + "* Bit" + "* Nat" + "* Int" + "* Rev" + "* Frac" + "* Text" + (def: my_nat 123) + (def: my_text "456") + (and (case [my_nat my_text] + (^ (static [..my_nat ..my_text])) + true + + _ + false) + (case [my_nat my_text] + (^ [(static ..my_nat) (static ..my_text)]) + true + + _ + false)))} (case tokens (^ (list pattern)) (do meta_monad @@ -5567,7 +5577,7 @@ _ #0)] - expected get_expected_type + expected ..expected_type g!temp (..identifier "temp")] (let [output (list g!temp (` ({(#Some (~ g!temp)) @@ -5610,18 +5620,18 @@ _ (failure (..wrong_syntax_error ["library/lux" "name_of"])))) -(def: (get_scope_type_vars state) +(def: (scope_type_vars state) (Meta (List Nat)) (case state {#info info #source source #current_module _ #modules modules #scopes scopes #type_context types #host host #seed seed #expected expected #location location #extensions extensions #scope_type_vars scope_type_vars} - (#Right state scope_type_vars) - )) + (#Right [state scope_type_vars]))) (macro: .public (:parameter tokens) - {#.doc (example "Allows you to refer to the type-variables in a polymorphic function's type, by their index." + {#.doc (example "NOTE: Please stay away from this macro. It's very likely to be removed in a future version of Lux." + "Allows you to refer to the type-variables in a polymorphic function's type, by their index." "In the example below, 0 corresponds to the 'a' variable." (def: .public (of_list list) (All [a] (-> (List a) (Row a))) @@ -5632,7 +5642,7 @@ (case tokens (^ (list [_ (#Nat idx)])) (do meta_monad - [stvs get_scope_type_vars] + [stvs ..scope_type_vars] (case (..item idx (list\reverse stvs)) (#Some var_id) (in (list (` (#Ex (~ (nat$ var_id)))))) @@ -5643,14 +5653,14 @@ _ (failure (..wrong_syntax_error (name_of ..$))))) -(def: .public (is? reference sample) +(def: .public (same? reference sample) {#.doc (example "Tests whether the 2 values are identical (not just 'equal')." "This one should succeed:" (let [value +5] - (is? value value)) + (same? value value)) "This one should fail:" - (is? +5 (+ +2 +3)))} + (same? +5 (+ +2 +3)))} (All [a] (-> a a Bit)) ("lux is" reference sample)) @@ -5686,17 +5696,19 @@ _ (failure (..wrong_syntax_error (name_of ..^|>))))) -(macro: .public (:assume tokens) +(macro: .public (:expected tokens) {#.doc (example "Coerces the given expression to the type of whatever is expected." - (: Dinosaur (:assume (list +1 +2 +3))))} + (: Dinosaur + (:expected (: (List Nat) + (list 1 2 3)))))} (case tokens (^ (list expr)) (do meta_monad - [type get_expected_type] + [type ..expected_type] (in (list (` ("lux type as" (~ (type_code type)) (~ expr)))))) _ - (failure (..wrong_syntax_error (name_of ..:assume))))) + (failure (..wrong_syntax_error (name_of ..:expected))))) (def: location {#.doc "The location of the current expression being analyzed."} @@ -5823,9 +5835,21 @@ (failure (..wrong_syntax_error (name_of ..template:))))) (macro: .public (as_is tokens compiler) + {#.doc (example "Given a (potentially empty) list of codes, just returns them immediately, without any work done." + "This may seen useless, but it has its utility when dealing with controlled-macro-expansion macros." + (with_expansions [ (as_is 1 + 2 + 3 + 4)] + (+ )))} (#Right [compiler tokens])) (macro: .public (char tokens compiler) + {#.doc (example "If given a 1-character text literal, yields the char-code of the sole character." + (: Nat + (char "A")) + "=>" + 65)} (case tokens (^multi (^ (list [_ (#Text input)])) (|> input "lux text size" ("lux i64 =" 1))) @@ -5886,6 +5910,12 @@ (target_pick target options' default))))) (macro: .public (for tokens) + {#.doc (example "Selects the appropriate code for a given target-platform when compiling Lux to it." + (def: js "JavaScript") + (for {"JVM" (do jvm stuff) + ..js (do js stuff)} + (do default stuff)) + "Look-up the available targets in library/lux/target.")} (do meta_monad [target ..target] (case tokens @@ -5940,6 +5970,10 @@ (in_meta [(list) code]))) (macro: .public (`` tokens) + {#.doc (example "Delimits a controlled (spliced) macro-expansion." + "Uses a (~~) special form to specify where to expand." + (`` (some expression + (~~ (some macro which may yield 0 or more results)))))} (case tokens (^ (list raw)) (do meta_monad @@ -6033,6 +6067,14 @@ ))) (macro: .public (^code tokens) + {#.doc (example "Generates pattern-matching code for Code values in a way that looks like code-templating." + (: (Maybe Nat) + (case (` (#0 123 +456.789)) + (^code (#0 (~ [_ (#.Nat number)]) +456.789)) + (#.Some number) + + _ + #.None)))} (case tokens (^ (list& [_meta (#Form (list template))] body branches)) (do meta_monad @@ -6048,14 +6090,19 @@ (failure (..wrong_syntax_error (name_of ..^code))))) (def: .public false + {#.doc "The boolean FALSE value."} Bit #0) (def: .public true + {#.doc "The boolean TRUE value."} Bit #1) (macro: .public (:let tokens) + {#.doc (example "Local bindings for types." + (:let [side (Either Int Frac)] + (List [side side])))} (case tokens (^ (list [_ (#Tuple bindings)] bodyT)) (if (multiple? 2 (list\size bindings)) @@ -6071,12 +6118,17 @@ (..failure (..wrong_syntax_error (name_of ..:let))))) (macro: .public (try tokens) - {#.doc (example (case (try (risky_computation input)) - (#.Right success) - (do_something success) - - (#.Left error) - (recover_from_failure error)))} + {#.doc (example (: Foo + (case (: (Either Text Bar) + (try (: Bar + (risky computation which may panic)))) + (#.Right success) + (: Foo + (do something after success)) + + (#.Left error) + (: Foo + (recover from error)))))} (case tokens (^ (list expression)) (do meta_monad -- cgit v1.2.3