From f3e869d0246e956399ec31a074c6c6299ff73602 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Thu, 8 Jul 2021 23:59:00 -0400 Subject: Made sure the "phase" parameter of extensions is always usable (even across language boundaries) --- stdlib/source/lux/control/parser.lux | 2 +- stdlib/source/lux/data/format/xml.lux | 75 +- stdlib/source/lux/target/jvm.lux | 9 +- stdlib/source/lux/time.lux | 33 +- stdlib/source/lux/tool/compiler/default/init.lux | 22 +- .../source/lux/tool/compiler/default/platform.lux | 1018 ++++++++++---------- .../tool/compiler/language/lux/phase/extension.lux | 6 +- .../language/lux/phase/extension/analysis/jvm.lux | 135 +-- stdlib/source/lux/world/file.lux | 6 +- stdlib/source/program/aedifex/artifact.lux | 23 +- stdlib/source/program/aedifex/command/deps.lux | 23 +- stdlib/source/program/aedifex/dependency.lux | 20 +- .../program/aedifex/dependency/resolution.lux | 4 +- stdlib/source/program/aedifex/metadata.lux | 4 +- .../source/program/aedifex/metadata/snapshot.lux | 29 +- stdlib/source/program/aedifex/parser.lux | 68 +- stdlib/source/program/compositor.lux | 4 +- stdlib/source/test/lux/extension.lux | 151 +-- stdlib/source/test/lux/time.lux | 154 ++- 19 files changed, 1026 insertions(+), 760 deletions(-) (limited to 'stdlib/source') diff --git a/stdlib/source/lux/control/parser.lux b/stdlib/source/lux/control/parser.lux index d22627fb5..4c95b5ee6 100644 --- a/stdlib/source/lux/control/parser.lux +++ b/stdlib/source/lux/control/parser.lux @@ -276,7 +276,7 @@ (All [s a] (-> (-> a Bit) (Parser s a) (Parser s a))) (do ..monad [output parser - _ (assert "Constraint failed." (test output))] + _ (..assert "Constraint failed." (test output))] (wrap output))) (def: #export (parses? parser) diff --git a/stdlib/source/lux/data/format/xml.lux b/stdlib/source/lux/data/format/xml.lux index 4409c3ab5..5d4252cfc 100644 --- a/stdlib/source/lux/data/format/xml.lux +++ b/stdlib/source/lux/data/format/xml.lux @@ -98,11 +98,14 @@ (def: tag^ namespaced_symbol^) (def: attr_name^ namespaced_symbol^) +(def: white_space^ + (Parser Text) + (.some .space)) + (def: spaced^ (All [a] (-> (Parser a) (Parser a))) - (let [white_space^ (<>.some .space)] - (|>> (<>.before white_space^) - (<>.after white_space^)))) + (|>> (<>.before ..white_space^) + (<>.after ..white_space^))) (def: attr_value^ (Parser Text) @@ -114,15 +117,15 @@ (Parser Attrs) (<| (\ <>.monad map (dictionary.from_list name.hash)) <>.some - (<>.and (spaced^ attr_name^)) + (<>.and (..spaced^ attr_name^)) (<>.after (.this "=")) - (spaced^ attr_value^))) + (..spaced^ attr_value^))) (def: (close_tag^ expected) (-> Tag (Parser [])) (do <>.monad [actual (|> tag^ - spaced^ + ..spaced^ (<>.after (.this "/")) (.enclosed ["<" ">"]))] (<>.assert ($_ text\compose "Close tag does not match open tag." text.new_line @@ -135,14 +138,14 @@ (|> (.not (.this "--")) .some (.enclosed [""]) - spaced^)) + ..spaced^)) (def: xml_header^ (Parser Attrs) - (|> (spaced^ attrs^) + (|> (..spaced^ attrs^) (<>.before (.this "?>")) (<>.after (.this " (.some (.not end)) (<>.after end) (<>.after (.this " (<>.rec (function (_ node^) - (|> (spaced^ - (do <>.monad - [_ (.this "<") - tag (spaced^ tag^) - attrs (spaced^ attrs^) - #let [no_children^ (do <>.monad - [_ (.this "/>")] - (wrap (#Node tag attrs (list)))) - ## TODO: Find a way to make do without this hack. Without it, some POM files fail when parsing them in Aedifex. Something like this fails: - alternative_no_children^ (do <>.monad - [_ (.this ">") - _ (<>.some .space) - _ (..close_tag^ tag)] - (wrap (#Node tag attrs (list)))) - with_children^ (do <>.monad - [_ (.this ">") - children (<>.some node^) - _ (..close_tag^ tag)] - (wrap (#Node tag attrs children)))]] - ($_ <>.either - no_children^ - alternative_no_children^ - with_children^))) + (|> (do <>.monad + [_ (.this "<") + tag (..spaced^ tag^) + attrs (..spaced^ attrs^) + #let [no_children^ (do <>.monad + [_ (.this "/>")] + (wrap (#Node tag attrs (list)))) + ## TODO: Find a way to make do without this hack. Without it, some POM files fail when parsing them in Aedifex. Something like this fails: + alternative_no_children^ (do <>.monad + [_ (.this ">") + _ (<>.some .space) + _ (..close_tag^ tag)] + (wrap (#Node tag attrs (list)))) + with_children^ (do <>.monad + [_ (.this ">") + children (<>.either (<>.many node^) + (<>.after (<>.some ..comment^) + (wrap (: (List XML) (list))))) + _ (..close_tag^ tag)] + (wrap (#Node tag attrs children)))]] + ($_ <>.either + no_children^ + alternative_no_children^ + with_children^)) + ..spaced^ (<>.before (<>.some ..comment^)) (<>.after (<>.some ..comment^)) - (<>.either text^)))) + (<>.either ..text^)))) (<>.before (<>.some ..null^)) - (<>.after (<>.maybe xml_header^)))) + (<>.after (<>.maybe ..xml_header^)))) (def: read (-> Text (Try XML)) diff --git a/stdlib/source/lux/target/jvm.lux b/stdlib/source/lux/target/jvm.lux index 3cc306cd9..4250bf705 100644 --- a/stdlib/source/lux/target/jvm.lux +++ b/stdlib/source/lux/target/jvm.lux @@ -265,7 +265,7 @@ (#Concurrency Concurrency) (#Return Return)) -(type: #export (Instruction label) +(type: #export (Instruction embedded label) #NOP (#Constant Constant) (#Arithmetic Arithmetic) @@ -276,7 +276,8 @@ (#Local Local) (#Stack Stack) (#Comparison Comparison) - (#Control (Control label))) + (#Control (Control label)) + (#Embedded embedded)) -(type: #export (Bytecode label) - (Row (Instruction label))) +(type: #export (Bytecode embedded label) + (Row (Instruction embedded label))) diff --git a/stdlib/source/lux/time.lux b/stdlib/source/lux/time.lux index f1600bc56..3a737f113 100644 --- a/stdlib/source/lux/time.lux +++ b/stdlib/source/lux/time.lux @@ -7,10 +7,11 @@ [codec (#+ Codec)] [monad (#+ Monad do)]] [control + [pipe (#+ case>)] ["." try (#+ Try)] ["." exception (#+ exception:)] ["<>" parser - ["" text (#+ Parser)]]] + ["<.>" text (#+ Parser)]]] [data ["." text ("#\." monoid)]] [math @@ -45,13 +46,13 @@ (def: parse_section (Parser Nat) - (<>.codec n.decimal (.exactly 2 .decimal))) + (<>.codec n.decimal (.exactly 2 .decimal))) -(def: parse_millis' +(def: parse_millis (Parser Nat) - (<>.either (|> (.at_most 3 .decimal) + (<>.either (|> (.at_most 3 .decimal) (<>.codec n.decimal) - (<>.after (.this "."))) + (<>.after (.this "."))) (\ <>.monad wrap 0))) (template [ ] @@ -65,15 +66,13 @@ (Parser Nat) (do <>.monad [value ] - (if (and (n.>= 0 value) - (n.< value)) + (if (n.< value) (wrap value) (<>.lift (exception.throw [value])))))] [..hours parse_hour invalid_hour ..parse_section] [..minutes parse_minute invalid_minute ..parse_section] [..seconds parse_second invalid_second ..parse_section] - [..milli_seconds parse_millis invalid_milli_second ..parse_millis'] ) (abstract: #export Time @@ -116,12 +115,14 @@ (def: &order ..order) (def: succ - (|>> :representation (n.% ..limit) :abstraction)) + (|>> :representation inc (n.% ..limit) :abstraction)) - (def: (pred time) - (:abstraction (dec (case (:representation time) - 0 ..limit - millis millis)))))) + (def: pred + (|>> :representation + (case> 0 ..limit + millis millis) + dec + :abstraction)))) (def: #export parser (Parser Time) @@ -133,9 +134,9 @@ millis (to_millis duration.milli_second)] (do {! <>.monad} [utc_hour ..parse_hour - _ (.this ..separator) + _ (.this ..separator) utc_minute ..parse_minute - _ (.this ..separator) + _ (.this ..separator) utc_second ..parse_second utc_millis ..parse_millis] (wrap (:abstraction @@ -212,4 +213,4 @@ (Codec Text Time) (def: encode ..encode) - (def: decode (.run ..parser))) + (def: decode (.run ..parser))) diff --git a/stdlib/source/lux/tool/compiler/default/init.lux b/stdlib/source/lux/tool/compiler/default/init.lux index e697f62a9..2803398e0 100644 --- a/stdlib/source/lux/tool/compiler/default/init.lux +++ b/stdlib/source/lux/tool/compiler/default/init.lux @@ -49,7 +49,7 @@ ["." artifact] ["." document]]]]]) -(def: #export (state target module expander host_analysis host generate generation_bundle host_directive_bundle program anchorT,expressionT,directiveT extender) +(def: #export (state target module expander host_analysis host generate generation_bundle) (All [anchor expression directive] (-> Target Module @@ -58,17 +58,13 @@ (///generation.Host expression directive) (///generation.Phase anchor expression directive) (///generation.Bundle anchor expression directive) - (///directive.Bundle anchor expression directive) - (Program expression directive) - [Type Type Type] Extender (///directive.State+ anchor expression directive))) (let [synthesis_state [synthesisE.bundle ///synthesis.init] generation_state [generation_bundle (///generation.state host module)] eval (///analysis/evaluation.evaluator expander synthesis_state generation_state generate) analysis_state [(analysisE.bundle eval host_analysis) (///analysis.state (///analysis.info ///version.version target))]] - [(dictionary.merge host_directive_bundle - (luxD.bundle expander host_analysis program anchorT,expressionT,directiveT extender)) + [extension.empty {#///directive.analysis {#///directive.state analysis_state #///directive.phase (analysisP.phase expander)} #///directive.synthesis {#///directive.state synthesis_state @@ -76,6 +72,20 @@ #///directive.generation {#///directive.state generation_state #///directive.phase generate}}])) +(def: #export (with_default_directives expander host_analysis program anchorT,expressionT,directiveT extender) + (All [anchor expression directive] + (-> Expander + ///analysis.Bundle + (Program expression directive) + [Type Type Type] + Extender + (-> (///directive.State+ anchor expression directive) + (///directive.State+ anchor expression directive)))) + (function (_ [directive_extensions sub_state]) + [(dictionary.merge directive_extensions + (luxD.bundle expander host_analysis program anchorT,expressionT,directiveT extender)) + sub_state])) + (type: Reader (-> Source (Either [Source Text] [Source Code]))) diff --git a/stdlib/source/lux/tool/compiler/default/platform.lux b/stdlib/source/lux/tool/compiler/default/platform.lux index d43259443..1e7f643ac 100644 --- a/stdlib/source/lux/tool/compiler/default/platform.lux +++ b/stdlib/source/lux/tool/compiler/default/platform.lux @@ -7,7 +7,7 @@ ["." monad (#+ Monad do)]] [control ["." function] - ["." try (#+ Try)] + ["." try (#+ Try) ("#\." functor)] ["." exception (#+ exception:)] [concurrency ["." promise (#+ Promise Resolver) ("#\." monad)] @@ -31,7 +31,7 @@ ["." // #_ ["#." init] ["/#" // - ["#." phase] + ["#." phase (#+ Phase)] [language [lux [program (#+ Program)] @@ -61,499 +61,541 @@ ["." static (#+ Static)] ["." import (#+ Import)]]]) -(type: #export (Platform anchor expression directive) - {#&file_system (file.System Promise) - #host (///generation.Host expression directive) - #phase (///generation.Phase anchor expression directive) - #runtime (///generation.Operation anchor expression directive [Registry Output]) - #write (-> directive Binary)}) - -## TODO: Get rid of this -(type: (Action a) - (Promise (Try a))) - -## TODO: Get rid of this -(def: monad - (:coerce (Monad Action) - (try.with promise.monad))) - (with_expansions [ (as_is anchor expression directive) - (as_is (Platform )) - (as_is (///directive.State+ )) - (as_is (///generation.Bundle ))] - - (def: writer - (Writer [Descriptor (Document .Module)]) - (_.and descriptor.writer - (document.writer $.writer))) - - (def: (cache_module static platform module_id [descriptor document output]) - (All [] - (-> Static archive.ID [Descriptor (Document Any) Output] - (Promise (Try Any)))) - (let [system (get@ #&file_system platform) - write_artifact! (: (-> [artifact.ID Binary] (Action Any)) - (function (_ [artifact_id content]) - (ioW.write system static module_id artifact_id content)))] - (do {! ..monad} - [_ (ioW.prepare system static module_id) - _ (for {@.python (|> output - row.to_list - (list.chunk 128) - (monad.map ! (monad.map ! write_artifact!)) - (: (Action (List (List Any)))))} - (|> output - row.to_list - (monad.map ..monad write_artifact!) - (: (Action (List Any))))) - document (\ promise.monad wrap - (document.check $.key document))] - (ioW.cache system static module_id - (_.run ..writer [descriptor document]))))) - - ## TODO: Inline ASAP - (def: initialize_buffer! - (All [] - (///generation.Operation Any)) - (///generation.set_buffer ///generation.empty_buffer)) - - ## TODO: Inline ASAP - (def: (compile_runtime! platform) - (All [] - (-> (///generation.Operation [Registry Output]))) - (do ///phase.monad - [_ ..initialize_buffer!] - (get@ #runtime platform))) - - (def: (runtime_descriptor registry) - (-> Registry Descriptor) - {#descriptor.hash 0 - #descriptor.name archive.runtime_module - #descriptor.file "" - #descriptor.references (set.new text.hash) - #descriptor.state #.Compiled - #descriptor.registry registry}) + (as_is ///generation.Operation )] + (type: #export Phase_Wrapper + (All [s i o] (-> (Phase s i o) Any))) - (def: runtime_document - (Document .Module) - (document.write $.key (module.new 0))) - - (def: (process_runtime archive platform) - (All [] - (-> Archive - (///directive.Operation - [Archive [Descriptor (Document .Module) Output]]))) - (do ///phase.monad - [[registry payload] (///directive.lift_generation - (..compile_runtime! platform)) - #let [[descriptor document] [(..runtime_descriptor registry) ..runtime_document]] - archive (///phase.lift (if (archive.reserved? archive archive.runtime_module) - (archive.add archive.runtime_module [descriptor document payload] archive) - (do try.monad - [[_ archive] (archive.reserve archive.runtime_module archive)] - (archive.add archive.runtime_module [descriptor document payload] archive))))] - (wrap [archive [descriptor document payload]]))) - - (def: (initialize_state extender - [analysers - synthesizers - generators - directives] - analysis_state - state) - (All [] - (-> Extender - [(Dictionary Text ///analysis.Handler) - (Dictionary Text ///synthesis.Handler) - (Dictionary Text ///generation.Handler) - (Dictionary Text ///directive.Handler)] - .Lux - - (Try ))) - (|> (:share [] - - state - - (///directive.Operation Any) - (do ///phase.monad - [_ (///directive.lift_analysis - (///analysis.install analysis_state)) - _ (///directive.lift_analysis - (extension.with extender analysers)) - _ (///directive.lift_synthesis - (extension.with extender synthesizers)) - _ (///directive.lift_generation - (extension.with extender (:assume generators))) - _ (extension.with extender (:assume directives))] - (wrap []))) - (///phase.run' state) - (\ try.monad map product.left))) - - (def: #export (initialize static module expander host_analysis platform generation_bundle host_directive_bundle program anchorT,expressionT,directiveT extender - import compilation_sources) - (All [] - (-> Static - Module - Expander - ///analysis.Bundle - - - (///directive.Bundle ) - (Program expression directive) - [Type Type Type] Extender - Import (List Context) - (Promise (Try [ Archive])))) - (do (try.with promise.monad) - [#let [state (//init.state (get@ #static.host static) - module - expander - host_analysis - (get@ #host platform) - (get@ #phase platform) - generation_bundle - host_directive_bundle - program - anchorT,expressionT,directiveT - extender)] - _ (ioW.enable (get@ #&file_system platform) static) - [archive analysis_state bundles] (ioW.thaw (get@ #host platform) (get@ #&file_system platform) static import compilation_sources) - state (promise\wrap (initialize_state extender bundles analysis_state state))] - (if (archive.archived? archive archive.runtime_module) - (wrap [state archive]) - (do (try.with promise.monad) - [[state [archive payload]] (|> (..process_runtime archive platform) - (///phase.run' state) - promise\wrap) - _ (..cache_module static platform 0 payload)] - (wrap [state archive]))))) - - (def: compilation_log_separator - (format text.new_line text.tab)) - - (def: (module_compilation_log module) - (All [] - (-> Module Text)) - (|>> (get@ [#extension.state - #///directive.generation - #///directive.state - #extension.state - #///generation.log]) - (row\fold (function (_ right left) - (format left ..compilation_log_separator right)) - module))) - - (def: with_reset_log - (All [] - (-> )) - (set@ [#extension.state - #///directive.generation - #///directive.state - #extension.state - #///generation.log] - row.empty)) - - (def: empty - (Set Module) - (set.new text.hash)) - - (type: Mapping - (Dictionary Module (Set Module))) - - (type: Dependence - {#depends_on Mapping - #depended_by Mapping}) - - (def: independence - Dependence - (let [empty (dictionary.new text.hash)] - {#depends_on empty - #depended_by empty})) - - (def: (depend module import dependence) - (-> Module Module Dependence Dependence) - (let [transitive_dependency (: (-> (-> Dependence Mapping) Module (Set Module)) - (function (_ lens module) - (|> dependence - lens - (dictionary.get module) - (maybe.default ..empty)))) - transitive_depends_on (transitive_dependency (get@ #depends_on) import) - transitive_depended_by (transitive_dependency (get@ #depended_by) module) - update_dependence (: (-> [Module (Set Module)] [Module (Set Module)] - (-> Mapping Mapping)) - (function (_ [source forward] [target backward]) - (function (_ mapping) - (let [with_dependence+transitives - (|> mapping - (dictionary.upsert source ..empty (set.add target)) - (dictionary.update source (set.union forward)))] - (list\fold (function (_ previous) - (dictionary.upsert previous ..empty (set.add target))) - with_dependence+transitives - (set.to_list backward))))))] - (|> dependence - (update@ #depends_on - (update_dependence - [module transitive_depends_on] - [import transitive_depended_by])) - (update@ #depended_by - ((function.flip update_dependence) - [module transitive_depends_on] - [import transitive_depended_by]))))) - - (def: (circular_dependency? module import dependence) - (-> Module Module Dependence Bit) - (let [dependence? (: (-> Module (-> Dependence Mapping) Module Bit) - (function (_ from relationship to) - (let [targets (|> dependence - relationship - (dictionary.get from) - (maybe.default ..empty))] - (set.member? targets to))))] - (or (dependence? import (get@ #depends_on) module) - (dependence? module (get@ #depended_by) import)))) - - (exception: #export (module_cannot_import_itself {module Module}) - (exception.report - ["Module" (%.text module)])) - - (exception: #export (cannot_import_circular_dependency {importer Module} - {importee Module}) - (exception.report - ["Importer" (%.text importer)] - ["importee" (%.text importee)])) - - (def: (verify_dependencies importer importee dependence) - (-> Module Module Dependence (Try Any)) - (cond (text\= importer importee) - (exception.throw ..module_cannot_import_itself [importer]) - - (..circular_dependency? importer importee dependence) - (exception.throw ..cannot_import_circular_dependency [importer importee]) - - ## else - (#try.Success []))) - - (with_expansions [ (as_is [Archive ]) - (as_is (Try )) - (as_is (Promise )) - (as_is (Resolver )) - (as_is [ ]) - (as_is (-> Module Module )) - (as_is (-> Module archive.ID Module ))] - (def: (parallel initial) + (type: #export (Platform ) + {#&file_system (file.System Promise) + #host (///generation.Host expression directive) + #phase (///generation.Phase ) + #runtime ( [Registry Output]) + #phase_wrapper (-> Archive ( Phase_Wrapper)) + #write (-> directive Binary)}) + + ## TODO: Get rid of this + (type: (Action a) + (Promise (Try a))) + + ## TODO: Get rid of this + (def: monad + (:coerce (Monad Action) + (try.with promise.monad))) + + (with_expansions [ (as_is (Platform )) + (as_is (///directive.State+ )) + (as_is (///generation.Bundle ))] + + (def: writer + (Writer [Descriptor (Document .Module)]) + (_.and descriptor.writer + (document.writer $.writer))) + + (def: (cache_module static platform module_id [descriptor document output]) (All [] - (-> - (-> ))) - (let [current (stm.var initial) - pending (:share [] - - initial - - (Var (Dictionary Module )) - (:assume (stm.var (dictionary.new text.hash)))) - dependence (: (Var Dependence) - (stm.var ..independence))] - (function (_ compile) - (function (import! importer module) - (do {! promise.monad} - [[return signal] (:share [] - - initial - - (Promise [ (Maybe [ - archive.ID - ])]) - (:assume - (stm.commit - (do {! stm.monad} - [dependence (if (text\= archive.runtime_module importer) - (stm.read dependence) - (do ! - [[_ dependence] (stm.update (..depend importer module) dependence)] - (wrap dependence)))] - (case (..verify_dependencies importer module dependence) - (#try.Failure error) - (wrap [(promise.resolved (#try.Failure error)) - #.None]) - - (#try.Success _) - (do ! - [[archive state] (stm.read current)] - (if (archive.archived? archive module) - (wrap [(promise\wrap (#try.Success [archive state])) - #.None]) - (do ! - [@pending (stm.read pending)] - (case (dictionary.get module @pending) - (#.Some [return signal]) - (wrap [return - #.None]) - - #.None - (case (if (archive.reserved? archive module) - (do try.monad - [module_id (archive.id module archive)] - (wrap [module_id archive])) - (archive.reserve module archive)) - (#try.Success [module_id archive]) - (do ! - [_ (stm.write [archive state] current) - #let [[return signal] (:share [] - - initial - - - (promise.promise []))] - _ (stm.update (dictionary.put module [return signal]) pending)] - (wrap [return - (#.Some [[archive state] - module_id - signal])])) - - (#try.Failure error) - (wrap [(promise\wrap (#try.Failure error)) - #.None]))))))))))) - _ (case signal - #.None - (wrap []) - - (#.Some [context module_id resolver]) - (do ! - [result (compile importer import! module_id context module) - result (case result - (#try.Failure error) - (wrap result) - - (#try.Success [resulting_archive resulting_state]) - (stm.commit (do stm.monad - [[_ [merged_archive _]] (stm.update (function (_ [archive state]) - [(archive.merge resulting_archive archive) - state]) - current)] - (wrap (#try.Success [merged_archive resulting_state]))))) - _ (promise.future (resolver result))] - (wrap [])))] - return))))) - - ## TODO: Find a better way, as this only works for the Lux compiler. - (def: (updated_state archive state) + (-> Static archive.ID [Descriptor (Document Any) Output] + (Promise (Try Any)))) + (let [system (get@ #&file_system platform) + write_artifact! (: (-> [artifact.ID Binary] (Action Any)) + (function (_ [artifact_id content]) + (ioW.write system static module_id artifact_id content)))] + (do {! ..monad} + [_ (ioW.prepare system static module_id) + _ (for {@.python (|> output + row.to_list + (list.chunk 128) + (monad.map ! (monad.map ! write_artifact!)) + (: (Action (List (List Any)))))} + (|> output + row.to_list + (monad.map ..monad write_artifact!) + (: (Action (List Any))))) + document (\ promise.monad wrap + (document.check $.key document))] + (ioW.cache system static module_id + (_.run ..writer [descriptor document]))))) + + ## TODO: Inline ASAP + (def: initialize_buffer! (All [] - (-> Archive (Try ))) - (do {! try.monad} - [modules (monad.map ! (function (_ module) - (do ! - [[descriptor document output] (archive.find module archive) - lux_module (document.read $.key document)] - (wrap [module lux_module]))) - (archive.archived archive)) - #let [additions (|> modules - (list\map product.left) - (set.from_list text.hash))]] - (wrap (update@ [#extension.state - #///directive.analysis - #///directive.state - #extension.state] - (function (_ analysis_state) - (|> analysis_state - (:coerce .Lux) - (update@ #.modules (function (_ current) - (list\compose (list.filter (|>> product.left - (set.member? additions) - not) - current) - modules))) - :assume)) - state)))) - - (def: (set_current_module module state) + (///generation.Operation Any)) + (///generation.set_buffer ///generation.empty_buffer)) + + ## TODO: Inline ASAP + (def: (compile_runtime! platform) + (All [] + (-> (///generation.Operation [Registry Output]))) + (do ///phase.monad + [_ ..initialize_buffer!] + (get@ #runtime platform))) + + (def: (runtime_descriptor registry) + (-> Registry Descriptor) + {#descriptor.hash 0 + #descriptor.name archive.runtime_module + #descriptor.file "" + #descriptor.references (set.new text.hash) + #descriptor.state #.Compiled + #descriptor.registry registry}) + + (def: runtime_document + (Document .Module) + (document.write $.key (module.new 0))) + + (def: (process_runtime archive platform) + (All [] + (-> Archive + (///directive.Operation + [Archive [Descriptor (Document .Module) Output]]))) + (do ///phase.monad + [[registry payload] (///directive.lift_generation + (..compile_runtime! platform)) + #let [[descriptor document] [(..runtime_descriptor registry) ..runtime_document]] + archive (///phase.lift (if (archive.reserved? archive archive.runtime_module) + (archive.add archive.runtime_module [descriptor document payload] archive) + (do try.monad + [[_ archive] (archive.reserve archive.runtime_module archive)] + (archive.add archive.runtime_module [descriptor document payload] archive))))] + (wrap [archive [descriptor document payload]]))) + + (def: (initialize_state extender + [analysers + synthesizers + generators + directives] + analysis_state + state) (All [] - (-> Module )) - (|> (///directive.set_current_module module) + (-> Extender + [(Dictionary Text ///analysis.Handler) + (Dictionary Text ///synthesis.Handler) + (Dictionary Text (///generation.Handler )) + (Dictionary Text (///directive.Handler ))] + .Lux + + (Try ))) + (|> (:share [] + + state + + (///directive.Operation Any) + (do ///phase.monad + [_ (///directive.lift_analysis + (///analysis.install analysis_state)) + _ (///directive.lift_analysis + (extension.with extender analysers)) + _ (///directive.lift_synthesis + (extension.with extender synthesizers)) + _ (///directive.lift_generation + (extension.with extender (:assume generators))) + _ (extension.with extender (:assume directives))] + (wrap []))) (///phase.run' state) - try.assume - product.left)) + (\ try.monad map product.left))) - (def: #export (compile import static expander platform compilation context) + (def: (phase_wrapper archive platform state) (All [] - (-> Import Static Expander Compilation )) - (let [[compilation_sources compilation_libraries compilation_target compilation_module] compilation - base_compiler (:share [] - - context - - (///.Compiler .Module Any) - (:assume - ((//init.compiler expander syntax.prelude (get@ #write platform)) $.key (list)))) - compiler (..parallel - context - (function (_ importer import! module_id [archive state] module) - (do {! (try.with promise.monad)} - [#let [state (..set_current_module module state)] - input (context.read (get@ #&file_system platform) - importer - import - compilation_sources - (get@ #static.host_module_extension static) - module)] - (loop [[archive state] [archive state] - compilation (base_compiler (:coerce ///.Input input)) - all_dependencies (: (List Module) - (list))] - (let [new_dependencies (get@ #///.dependencies compilation) - all_dependencies (list\compose new_dependencies all_dependencies) - continue! (:share [] - - platform - - (-> (///.Compilation .Module Any) (List Module) - (Action [Archive ])) - (:assume - recur))] - (do ! - [[archive state] (case new_dependencies - #.Nil - (wrap [archive state]) - - (#.Cons _) - (do ! - [archive,document+ (|> new_dependencies - (list\map (import! module)) - (monad.seq ..monad)) - #let [archive (|> archive,document+ - (list\map product.left) - (list\fold archive.merge archive))]] - (wrap [archive (try.assume - (..updated_state archive state))])))] - (case ((get@ #///.process compilation) - ## TODO: The "///directive.set_current_module" below shouldn't be necessary. Remove it ASAP. - ## TODO: The context shouldn't need to be re-set either. - (|> (///directive.set_current_module module) + (-> Archive (Try [ Phase_Wrapper]))) + (let [phase_wrapper (get@ #phase_wrapper platform)] + (|> archive + phase_wrapper + ///directive.lift_generation + (///phase.run' state)))) + + (def: (complete_extensions host_directive_bundle phase_wrapper [analysers synthesizers generators directives]) + (All [] + (-> (-> Phase_Wrapper (///directive.Bundle )) + Phase_Wrapper + [(Dictionary Text ///analysis.Handler) + (Dictionary Text ///synthesis.Handler) + (Dictionary Text (///generation.Handler )) + (Dictionary Text (///directive.Handler ))] + [(Dictionary Text ///analysis.Handler) + (Dictionary Text ///synthesis.Handler) + (Dictionary Text (///generation.Handler )) + (Dictionary Text (///directive.Handler ))])) + [analysers + synthesizers + generators + (dictionary.merge directives (host_directive_bundle phase_wrapper))]) + + (def: #export (initialize static module expander host_analysis platform generation_bundle host_directive_bundle program anchorT,expressionT,directiveT extender + import compilation_sources) + (All [] + (-> Static + Module + Expander + ///analysis.Bundle + + + (-> Phase_Wrapper (///directive.Bundle )) + (Program expression directive) + [Type Type Type] (-> Phase_Wrapper Extender) + Import (List Context) + (Promise (Try [ Archive])))) + (do {! (try.with promise.monad)} + [#let [state (//init.state (get@ #static.host static) + module + expander + host_analysis + (get@ #host platform) + (get@ #phase platform) + generation_bundle)] + _ (ioW.enable (get@ #&file_system platform) static) + [archive analysis_state bundles] (ioW.thaw (get@ #host platform) (get@ #&file_system platform) static import compilation_sources) + #let [with_missing_extensions + (: (All [] + (-> (Program expression directive) (Promise (Try )))) + (function (_ platform program state) + (promise\wrap + (do try.monad + [[state phase_wrapper] (..phase_wrapper archive platform state)] + (|> state + (initialize_state (extender phase_wrapper) + (:assume (..complete_extensions host_directive_bundle phase_wrapper (:assume bundles))) + analysis_state) + (try\map (//init.with_default_directives expander host_analysis program anchorT,expressionT,directiveT (extender phase_wrapper))))))))]] + (if (archive.archived? archive archive.runtime_module) + (do ! + [state (with_missing_extensions platform program state)] + (wrap [state archive])) + (do ! + [[state [archive payload]] (|> (..process_runtime archive platform) (///phase.run' state) - try.assume - product.left) - archive) - (#try.Success [state more|done]) - (case more|done - (#.Left more) - (continue! [archive state] more all_dependencies) - - (#.Right [descriptor document output]) - (do ! - [#let [_ (debug.log! (..module_compilation_log module state)) - descriptor (set@ #descriptor.references (set.from_list text.hash all_dependencies) descriptor)] - _ (..cache_module static platform module_id [descriptor document output])] - (case (archive.add module [descriptor document output] archive) - (#try.Success archive) - (wrap [archive - (..with_reset_log state)]) - - (#try.Failure error) - (promise\wrap (#try.Failure error))))) - - (#try.Failure error) + promise\wrap) + _ (..cache_module static platform 0 payload) + + state (with_missing_extensions platform program state)] + (wrap [state archive]))))) + + (def: compilation_log_separator + (format text.new_line text.tab)) + + (def: (module_compilation_log module) + (All [] + (-> Module Text)) + (|>> (get@ [#extension.state + #///directive.generation + #///directive.state + #extension.state + #///generation.log]) + (row\fold (function (_ right left) + (format left ..compilation_log_separator right)) + module))) + + (def: with_reset_log + (All [] + (-> )) + (set@ [#extension.state + #///directive.generation + #///directive.state + #extension.state + #///generation.log] + row.empty)) + + (def: empty + (Set Module) + (set.new text.hash)) + + (type: Mapping + (Dictionary Module (Set Module))) + + (type: Dependence + {#depends_on Mapping + #depended_by Mapping}) + + (def: independence + Dependence + (let [empty (dictionary.new text.hash)] + {#depends_on empty + #depended_by empty})) + + (def: (depend module import dependence) + (-> Module Module Dependence Dependence) + (let [transitive_dependency (: (-> (-> Dependence Mapping) Module (Set Module)) + (function (_ lens module) + (|> dependence + lens + (dictionary.get module) + (maybe.default ..empty)))) + transitive_depends_on (transitive_dependency (get@ #depends_on) import) + transitive_depended_by (transitive_dependency (get@ #depended_by) module) + update_dependence (: (-> [Module (Set Module)] [Module (Set Module)] + (-> Mapping Mapping)) + (function (_ [source forward] [target backward]) + (function (_ mapping) + (let [with_dependence+transitives + (|> mapping + (dictionary.upsert source ..empty (set.add target)) + (dictionary.update source (set.union forward)))] + (list\fold (function (_ previous) + (dictionary.upsert previous ..empty (set.add target))) + with_dependence+transitives + (set.to_list backward))))))] + (|> dependence + (update@ #depends_on + (update_dependence + [module transitive_depends_on] + [import transitive_depended_by])) + (update@ #depended_by + ((function.flip update_dependence) + [module transitive_depends_on] + [import transitive_depended_by]))))) + + (def: (circular_dependency? module import dependence) + (-> Module Module Dependence Bit) + (let [dependence? (: (-> Module (-> Dependence Mapping) Module Bit) + (function (_ from relationship to) + (let [targets (|> dependence + relationship + (dictionary.get from) + (maybe.default ..empty))] + (set.member? targets to))))] + (or (dependence? import (get@ #depends_on) module) + (dependence? module (get@ #depended_by) import)))) + + (exception: #export (module_cannot_import_itself {module Module}) + (exception.report + ["Module" (%.text module)])) + + (exception: #export (cannot_import_circular_dependency {importer Module} + {importee Module}) + (exception.report + ["Importer" (%.text importer)] + ["importee" (%.text importee)])) + + (def: (verify_dependencies importer importee dependence) + (-> Module Module Dependence (Try Any)) + (cond (text\= importer importee) + (exception.throw ..module_cannot_import_itself [importer]) + + (..circular_dependency? importer importee dependence) + (exception.throw ..cannot_import_circular_dependency [importer importee]) + + ## else + (#try.Success []))) + + (with_expansions [ (as_is [Archive ]) + (as_is (Try )) + (as_is (Promise )) + (as_is (Resolver )) + (as_is [ ]) + (as_is (-> Module Module )) + (as_is (-> Module archive.ID Module ))] + (def: (parallel initial) + (All [] + (-> + (-> ))) + (let [current (stm.var initial) + pending (:share [] + + initial + + (Var (Dictionary Module )) + (:assume (stm.var (dictionary.new text.hash)))) + dependence (: (Var Dependence) + (stm.var ..independence))] + (function (_ compile) + (function (import! importer module) + (do {! promise.monad} + [[return signal] (:share [] + + initial + + (Promise [ (Maybe [ + archive.ID + ])]) + (:assume + (stm.commit + (do {! stm.monad} + [dependence (if (text\= archive.runtime_module importer) + (stm.read dependence) + (do ! + [[_ dependence] (stm.update (..depend importer module) dependence)] + (wrap dependence)))] + (case (..verify_dependencies importer module dependence) + (#try.Failure error) + (wrap [(promise.resolved (#try.Failure error)) + #.None]) + + (#try.Success _) + (do ! + [[archive state] (stm.read current)] + (if (archive.archived? archive module) + (wrap [(promise\wrap (#try.Success [archive state])) + #.None]) + (do ! + [@pending (stm.read pending)] + (case (dictionary.get module @pending) + (#.Some [return signal]) + (wrap [return + #.None]) + + #.None + (case (if (archive.reserved? archive module) + (do try.monad + [module_id (archive.id module archive)] + (wrap [module_id archive])) + (archive.reserve module archive)) + (#try.Success [module_id archive]) + (do ! + [_ (stm.write [archive state] current) + #let [[return signal] (:share [] + + initial + + + (promise.promise []))] + _ (stm.update (dictionary.put module [return signal]) pending)] + (wrap [return + (#.Some [[archive state] + module_id + signal])])) + + (#try.Failure error) + (wrap [(promise\wrap (#try.Failure error)) + #.None]))))))))))) + _ (case signal + #.None + (wrap []) + + (#.Some [context module_id resolver]) + (do ! + [result (compile importer import! module_id context module) + result (case result + (#try.Failure error) + (wrap result) + + (#try.Success [resulting_archive resulting_state]) + (stm.commit (do stm.monad + [[_ [merged_archive _]] (stm.update (function (_ [archive state]) + [(archive.merge resulting_archive archive) + state]) + current)] + (wrap (#try.Success [merged_archive resulting_state]))))) + _ (promise.future (resolver result))] + (wrap [])))] + return))))) + + ## TODO: Find a better way, as this only works for the Lux compiler. + (def: (updated_state archive state) + (All [] + (-> Archive (Try ))) + (do {! try.monad} + [modules (monad.map ! (function (_ module) (do ! - [_ (ioW.freeze (get@ #&file_system platform) static archive)] - (promise\wrap (#try.Failure error))))))))))] - (compiler archive.runtime_module compilation_module))) - )) + [[descriptor document output] (archive.find module archive) + lux_module (document.read $.key document)] + (wrap [module lux_module]))) + (archive.archived archive)) + #let [additions (|> modules + (list\map product.left) + (set.from_list text.hash))]] + (wrap (update@ [#extension.state + #///directive.analysis + #///directive.state + #extension.state] + (function (_ analysis_state) + (|> analysis_state + (:coerce .Lux) + (update@ #.modules (function (_ current) + (list\compose (list.filter (|>> product.left + (set.member? additions) + not) + current) + modules))) + :assume)) + state)))) + + (def: (set_current_module module state) + (All [] + (-> Module )) + (|> (///directive.set_current_module module) + (///phase.run' state) + try.assume + product.left)) + + (def: #export (compile import static expander platform compilation context) + (All [] + (-> Import Static Expander Compilation )) + (let [[compilation_sources compilation_libraries compilation_target compilation_module] compilation + base_compiler (:share [] + + context + + (///.Compiler .Module Any) + (:assume + ((//init.compiler expander syntax.prelude (get@ #write platform)) $.key (list)))) + compiler (..parallel + context + (function (_ importer import! module_id [archive state] module) + (do {! (try.with promise.monad)} + [#let [state (..set_current_module module state)] + input (context.read (get@ #&file_system platform) + importer + import + compilation_sources + (get@ #static.host_module_extension static) + module)] + (loop [[archive state] [archive state] + compilation (base_compiler (:coerce ///.Input input)) + all_dependencies (: (List Module) + (list))] + (let [new_dependencies (get@ #///.dependencies compilation) + all_dependencies (list\compose new_dependencies all_dependencies) + continue! (:share [] + + platform + + (-> (///.Compilation .Module Any) (List Module) + (Action [Archive ])) + (:assume + recur))] + (do ! + [[archive state] (case new_dependencies + #.Nil + (wrap [archive state]) + + (#.Cons _) + (do ! + [archive,document+ (|> new_dependencies + (list\map (import! module)) + (monad.seq ..monad)) + #let [archive (|> archive,document+ + (list\map product.left) + (list\fold archive.merge archive))]] + (wrap [archive (try.assume + (..updated_state archive state))])))] + (case ((get@ #///.process compilation) + ## TODO: The "///directive.set_current_module" below shouldn't be necessary. Remove it ASAP. + ## TODO: The context shouldn't need to be re-set either. + (|> (///directive.set_current_module module) + (///phase.run' state) + try.assume + product.left) + archive) + (#try.Success [state more|done]) + (case more|done + (#.Left more) + (continue! [archive state] more all_dependencies) + + (#.Right [descriptor document output]) + (do ! + [#let [_ (debug.log! (..module_compilation_log module state)) + descriptor (set@ #descriptor.references (set.from_list text.hash all_dependencies) descriptor)] + _ (..cache_module static platform module_id [descriptor document output])] + (case (archive.add module [descriptor document output] archive) + (#try.Success archive) + (wrap [archive + (..with_reset_log state)]) + + (#try.Failure error) + (promise\wrap (#try.Failure error))))) + + (#try.Failure error) + (do ! + [_ (ioW.freeze (get@ #&file_system platform) static archive)] + (promise\wrap (#try.Failure error))))))))))] + (compiler archive.runtime_module compilation_module))) + ))) diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension.lux index 9803de0e4..7004b8d1a 100644 --- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension.lux +++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension.lux @@ -45,6 +45,10 @@ (type: #export (Bundle s i o) )) +(def: #export empty + Bundle + (dictionary.new text.hash)) + (type: #export (State s i o) {#bundle (Bundle s i o) #state s}) @@ -95,7 +99,7 @@ (def: #export (with extender extensions) (All [s i o] - (-> Extender (Dictionary Text (Handler s i o)) (Operation s i o Any))) + (-> Extender (Bundle s i o) (Operation s i o Any))) (|> extensions dictionary.entries (monad.fold //.monad diff --git a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/jvm.lux b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/jvm.lux index bb5587dfe..0c88ae795 100644 --- a/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/jvm.lux +++ b/stdlib/source/lux/tool/compiler/language/lux/phase/extension/analysis/jvm.lux @@ -9,8 +9,8 @@ ["." try (#+ Try) ("#\." monad)] ["." exception (#+ exception:)] ["<>" parser - ["" code (#+ Parser)] - ["" text]]] + ["<.>" code (#+ Parser)] + ["<.>" text]]] [data ["." maybe] ["." product] @@ -191,7 +191,7 @@ (def: member (Parser Member) - ($_ <>.and .text .text)) + ($_ <>.and .text .text)) (type: Method_Signature {#method .Type @@ -397,7 +397,7 @@ [objectJ (jvm_type objectT)] (|> objectJ ..signature - (.run jvm_parser.array) + (.run jvm_parser.array) phase.lift))) (def: (primitive_array_length_handler primitive_type) @@ -826,7 +826,7 @@ (def: object::instance? Handler (..custom - [($_ <>.and .text .any) + [($_ <>.and .text .any) (function (_ extension_name analyse archive [sub_class objectC]) (do phase.monad [_ (..ensure_fresh_class! sub_class) @@ -842,7 +842,7 @@ (template [ ] [(def: ( mapping typeJ) (-> Mapping (Type ) (Operation .Type)) - (case (|> typeJ ..signature (.run ( mapping))) + (case (|> typeJ ..signature (.run ( mapping))) (#try.Success check) (typeA.with_env check) @@ -998,7 +998,7 @@ (def: put::static Handler (..custom - [($_ <>.and ..member .any) + [($_ <>.and ..member .any) (function (_ extension_name analyse archive [[class field] valueC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1022,7 +1022,7 @@ (def: get::virtual Handler (..custom - [($_ <>.and ..member .any) + [($_ <>.and ..member .any) (function (_ extension_name analyse archive [[class field] objectC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1046,7 +1046,7 @@ (def: put::virtual Handler (..custom - [($_ <>.and ..member .any .any) + [($_ <>.and ..member .any .any) (function (_ extension_name analyse archive [[class field] valueC objectC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1339,7 +1339,7 @@ (template [ ] [(def: #export (Parser (Type )) - (.embed .text))] + (.embed .text))] [var Var jvm_parser.var] [class Class jvm_parser.class] @@ -1349,7 +1349,7 @@ (def: input (Parser (Typed Code)) - (.tuple (<>.and ..type .any))) + (.tuple (<>.and ..type .any))) (def: (decorate_inputs typesT inputsA) (-> (List (Type Value)) (List Analysis) (List Analysis)) @@ -1358,7 +1358,8 @@ (list\map (function (_ [type value]) (/////analysis.tuple (list type value)))))) -(def: type_vars (.tuple (<>.some ..var))) +(def: type_vars + (.tuple (<>.some ..var))) (def: invoke::static Handler @@ -1381,7 +1382,7 @@ (def: invoke::virtual Handler (..custom - [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) + [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) (function (_ extension_name analyse archive [class_tvars [class method] method_tvars objectC argsTC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1406,7 +1407,7 @@ (def: invoke::special Handler (..custom - [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) + [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) (function (_ extension_name analyse archive [class_tvars [class method] method_tvars objectC argsTC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1424,7 +1425,7 @@ (def: invoke::interface Handler (..custom - [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) + [($_ <>.and ..type_vars ..member ..type_vars .any (<>.some ..input)) (function (_ extension_name analyse archive [class_tvars [class_name method] method_tvars objectC argsTC]) (do phase.monad [_ (..ensure_fresh_class! class_name) @@ -1452,7 +1453,7 @@ (def: invoke::constructor (..custom - [($_ <>.and ..type_vars .text ..type_vars (<>.some ..input)) + [($_ <>.and ..type_vars .text ..type_vars (<>.some ..input)) (function (_ extension_name analyse archive [class_tvars class method_tvars argsTC]) (do phase.monad [_ (..ensure_fresh_class! class) @@ -1491,18 +1492,18 @@ (def: annotation_parameter (Parser (Annotation_Parameter Code)) - (.tuple (<>.and .text .any))) + (.tuple (<>.and .text .any))) (type: #export (Annotation a) [Text (List (Annotation_Parameter a))]) (def: #export annotation (Parser (Annotation Code)) - (.form (<>.and .text (<>.some ..annotation_parameter)))) + (.form (<>.and .text (<>.some ..annotation_parameter)))) (def: #export argument (Parser Argument) - (.tuple (<>.and .text ..type))) + (.tuple (<>.and .text ..type))) (def: (annotation_parameter_analysis [name value]) (-> (Annotation_Parameter Analysis) Analysis) @@ -1603,10 +1604,10 @@ (def: #export visibility (Parser Visibility) ($_ <>.or - (.text! ..public_tag) - (.text! ..private_tag) - (.text! ..protected_tag) - (.text! ..default_tag))) + (.text! ..public_tag) + (.text! ..private_tag) + (.text! ..protected_tag) + (.text! ..default_tag))) (def: #export (visibility_analysis visibility) (-> Visibility Analysis) @@ -1631,18 +1632,18 @@ (def: #export constructor_definition (Parser (Constructor Code)) - (<| .form - (<>.after (.text! ..constructor_tag)) + (<| .form + (<>.after (.text! ..constructor_tag)) ($_ <>.and ..visibility - .bit - (.tuple (<>.some ..annotation)) - (.tuple (<>.some ..var)) - (.tuple (<>.some ..class)) - .text - (.tuple (<>.some ..argument)) - (.tuple (<>.some ..input)) - .any))) + .bit + (.tuple (<>.some ..annotation)) + (.tuple (<>.some ..var)) + (.tuple (<>.some ..class)) + .text + (.tuple (<>.some ..argument)) + (.tuple (<>.some ..input)) + .any))) (def: #export (analyse_constructor_method analyse archive selfT mapping method) (-> Phase Archive .Type Mapping (Constructor Code) (Operation Analysis)) @@ -1710,20 +1711,20 @@ (def: #export virtual_method_definition (Parser (Virtual_Method Code)) - (<| .form - (<>.after (.text! ..virtual_tag)) + (<| .form + (<>.after (.text! ..virtual_tag)) ($_ <>.and - .text + .text ..visibility - .bit - .bit - (.tuple (<>.some ..annotation)) - (.tuple (<>.some ..var)) - .text - (.tuple (<>.some ..argument)) + .bit + .bit + (.tuple (<>.some ..annotation)) + (.tuple (<>.some ..var)) + .text + (.tuple (<>.some ..argument)) ..return - (.tuple (<>.some ..class)) - .any))) + (.tuple (<>.some ..class)) + .any))) (def: #export (analyse_virtual_method analyse archive selfT mapping method) (-> Phase Archive .Type Mapping (Virtual_Method Code) (Operation Analysis)) @@ -1786,18 +1787,18 @@ (def: #export static_method_definition (Parser (Static_Method Code)) - (<| .form - (<>.after (.text! ..static_tag)) + (<| .form + (<>.after (.text! ..static_tag)) ($_ <>.and - .text + .text ..visibility - .bit - (.tuple (<>.some ..annotation)) - (.tuple (<>.some ..var)) - (.tuple (<>.some ..class)) - (.tuple (<>.some ..argument)) + .bit + (.tuple (<>.some ..annotation)) + (.tuple (<>.some ..var)) + (.tuple (<>.some ..class)) + (.tuple (<>.some ..argument)) ..return - .any))) + .any))) (def: #export (analyse_static_method analyse archive mapping method) (-> Phase Archive Mapping (Static_Method Code) (Operation Analysis)) @@ -1859,19 +1860,19 @@ (def: #export overriden_method_definition (Parser (Overriden_Method Code)) - (<| .form - (<>.after (.text! ..overriden_tag)) + (<| .form + (<>.after (.text! ..overriden_tag)) ($_ <>.and ..class - .text - .bit - (.tuple (<>.some ..annotation)) - (.tuple (<>.some ..var)) - .text - (.tuple (<>.some ..argument)) + .text + .bit + (.tuple (<>.some ..annotation)) + (.tuple (<>.some ..var)) + .text + (.tuple (<>.some ..argument)) ..return - (.tuple (<>.some ..class)) - .any + (.tuple (<>.some ..class)) + .any ))) (def: #export (analyse_overriden_method analyse archive selfT mapping method) @@ -1984,11 +1985,11 @@ Handler (..custom [($_ <>.and - (.tuple (<>.some ..var)) + (.tuple (<>.some ..var)) ..class - (.tuple (<>.some ..class)) - (.tuple (<>.some ..input)) - (.tuple (<>.some ..overriden_method_definition))) + (.tuple (<>.some ..class)) + (.tuple (<>.some ..input)) + (.tuple (<>.some ..overriden_method_definition))) (function (_ extension_name analyse archive [parameters super_class super_interfaces diff --git a/stdlib/source/lux/world/file.lux b/stdlib/source/lux/world/file.lux index 400cdacb2..ade8e367f 100644 --- a/stdlib/source/lux/world/file.lux +++ b/stdlib/source/lux/world/file.lux @@ -925,10 +925,8 @@ ## ..default_separator) ## )) ## ) - - @.scheme - (as_is) - })) + } + (as_is))) (def: #export (exists? monad fs path) (All [!] (-> (Monad !) (System !) Path (! Bit))) diff --git a/stdlib/source/program/aedifex/artifact.lux b/stdlib/source/program/aedifex/artifact.lux index 9e87988ea..e5d37f7bb 100644 --- a/stdlib/source/program/aedifex/artifact.lux +++ b/stdlib/source/program/aedifex/artifact.lux @@ -2,10 +2,11 @@ [lux (#- Name) [abstract [equivalence (#+ Equivalence)] + [order (#+ Order)] [hash (#+ Hash)]] [data ["." product] - ["." text + ["." text ("#\." order) ["%" format (#+ Format)]] [collection ["." list ("#\." monoid)]]] @@ -40,6 +41,26 @@ (Equivalence Artifact) (\ ..hash &equivalence)) +(implementation: #export order + (Order Artifact) + + (def: &equivalence + ..equivalence) + + (def: (< reference subject) + (<| (or (text\< (get@ #group reference) + (get@ #group subject))) + + (and (text\= (get@ #group reference) + (get@ #group subject))) + (or (text\< (get@ #name reference) + (get@ #name subject))) + + (and (text\= (get@ #name reference) + (get@ #name subject))) + (text\< (get@ #version reference) + (get@ #version subject))))) + (template [ ] [(def: Text diff --git a/stdlib/source/program/aedifex/command/deps.lux b/stdlib/source/program/aedifex/command/deps.lux index de4817ba8..4dcc9d6e1 100644 --- a/stdlib/source/program/aedifex/command/deps.lux +++ b/stdlib/source/program/aedifex/command/deps.lux @@ -46,13 +46,20 @@ (list\fold dictionary.remove resolution) (///dependency/deployment.all local)) _ (console.write_line (exception.report - ["Local successes" (exception.enumerate ..format local_successes)] - ["Local failures" (exception.enumerate ..format local_failures)] - ["Remote successes" (let [remote_successes (|> remote_successes - (set.from_list ///dependency.hash) - (set.difference (set.from_list ///dependency.hash local_successes)) - set.to_list)] - (exception.enumerate ..format remote_successes))] - ["Remote failures" (exception.enumerate ..format remote_failures)]) + ["Local successes" (|> local_successes + (list.sort (\ ///dependency.order <)) + (exception.enumerate ..format))] + ["Local failures" (|> local_failures + (list.sort (\ ///dependency.order <)) + (exception.enumerate ..format))] + ["Remote successes" (|> remote_successes + (set.from_list ///dependency.hash) + (set.difference (set.from_list ///dependency.hash local_successes)) + set.to_list + (list.sort (\ ///dependency.order <)) + (exception.enumerate ..format))] + ["Remote failures" (|> remote_failures + (list.sort (\ ///dependency.order <)) + (exception.enumerate ..format))]) console)] (wrap resolution)))) diff --git a/stdlib/source/program/aedifex/dependency.lux b/stdlib/source/program/aedifex/dependency.lux index b7b605447..f06b00260 100644 --- a/stdlib/source/program/aedifex/dependency.lux +++ b/stdlib/source/program/aedifex/dependency.lux @@ -2,13 +2,14 @@ [lux (#- Type) [abstract [equivalence (#+ Equivalence)] + [order (#+ Order)] [hash (#+ Hash)]] [data ["." product] - ["." text + ["." text ("#\." order) ["%" format (#+ format)]]]] ["." // #_ - ["#" artifact (#+ Artifact) + ["#" artifact (#+ Artifact) ("#\." order) [type (#+ Type)]]]) (type: #export Dependency @@ -25,3 +26,18 @@ (def: #export equivalence (Equivalence Dependency) (\ hash &equivalence)) + +(implementation: #export order + (Order Dependency) + + (def: &equivalence + ..equivalence) + + (def: (< reference subject) + (<| (or (//\< (get@ #artifact reference) + (get@ #artifact subject))) + + (and (//\= (get@ #artifact reference) + (get@ #artifact subject))) + (text\< (get@ #type reference) + (get@ #type subject))))) diff --git a/stdlib/source/program/aedifex/dependency/resolution.lux b/stdlib/source/program/aedifex/dependency/resolution.lux index 326f2ac2d..63c3e930d 100644 --- a/stdlib/source/program/aedifex/dependency/resolution.lux +++ b/stdlib/source/program/aedifex/dependency/resolution.lux @@ -169,8 +169,8 @@ text.new_line)))] ["?" announce_fetching "Fetching" "from"] - ["Y" announce_success "Found" "at"] - ["N" announce_failure "Missed" "from"] + ["O" announce_success "Found" "at"] + ["X" announce_failure "Missed" "from"] ) (def: #export (any console repositories dependency) diff --git a/stdlib/source/program/aedifex/metadata.lux b/stdlib/source/program/aedifex/metadata.lux index 7fbe88cbc..843f2e056 100644 --- a/stdlib/source/program/aedifex/metadata.lux +++ b/stdlib/source/program/aedifex/metadata.lux @@ -17,7 +17,7 @@ (def: #export (remote_artifact_uri artifact) (-> Artifact URI) (let [/ uri.separator] - (format (get@ #//artifact.group artifact) + (format (//artifact.directory / (get@ #//artifact.group artifact)) / (get@ #//artifact.name artifact) / (get@ #//artifact.version artifact) / ..remote_file))) @@ -25,7 +25,7 @@ (def: #export (remote_project_uri artifact) (-> Artifact URI) (let [/ uri.separator] - (format (get@ #//artifact.group artifact) + (format (//artifact.directory / (get@ #//artifact.group artifact)) / (get@ #//artifact.name artifact) / ..remote_file))) diff --git a/stdlib/source/program/aedifex/metadata/snapshot.lux b/stdlib/source/program/aedifex/metadata/snapshot.lux index 6eec0c32c..518e0404a 100644 --- a/stdlib/source/program/aedifex/metadata/snapshot.lux +++ b/stdlib/source/program/aedifex/metadata/snapshot.lux @@ -41,7 +41,8 @@ ["#/." type (#+ Type)] ["#/." versioning (#+ Versioning)] ["#/." snapshot - ["#/." version]]]]]) + ["#/." version] + ["#/." stamp]]]]]) (type: #export Metadata {#artifact Artifact @@ -93,18 +94,22 @@ [group (.somewhere (..text ..)) name (.somewhere (..text ..)) version (.somewhere (..text ..)) - versioning (\ ! map - (update@ #///artifact/versioning.versions - (: (-> (List ///artifact/snapshot/version.Version) - (List ///artifact/snapshot/version.Version)) - (|>> (case> (^ (list)) - (list {#///artifact/snapshot/version.extension ///artifact/type.jvm_library - #///artifact/snapshot/version.value version - #///artifact/snapshot/version.updated ///artifact/time.epoch}) + versioning (with_expansions [ {#///artifact/snapshot/version.extension ///artifact/type.jvm_library + #///artifact/snapshot/version.value version + #///artifact/snapshot/version.updated ///artifact/time.epoch}] + (|> (.somewhere ///artifact/versioning.parser) + (\ ! map + (update@ #///artifact/versioning.versions + (: (-> (List ///artifact/snapshot/version.Version) + (List ///artifact/snapshot/version.Version)) + (|>> (case> (^ (list)) + (list ) - versions - versions)))) - (.somewhere ///artifact/versioning.parser))] + versions + versions))))) + (<>.default {#///artifact/versioning.snapshot #///artifact/snapshot.Local + #///artifact/versioning.last_updated ///artifact/time.epoch + #///artifact/versioning.versions (list )})))] (wrap {#artifact {#///artifact.group group #///artifact.name name #///artifact.version version} diff --git a/stdlib/source/program/aedifex/parser.lux b/stdlib/source/program/aedifex/parser.lux index 60e491dac..835b03729 100644 --- a/stdlib/source/program/aedifex/parser.lux +++ b/stdlib/source/program/aedifex/parser.lux @@ -4,7 +4,7 @@ [monad (#+ do)]] [control ["<>" parser - ["" code (#+ Parser)]]] + ["<.>" code (#+ Parser)]]] [data ["." text] [collection @@ -37,25 +37,25 @@ (def: (singular input tag parser) (All [a] (-> (Dictionary Text Code) Text (Parser a) (Parser a))) - (.local (..as_input (dictionary.get tag input)) - parser)) + (.local (..as_input (dictionary.get tag input)) + parser)) (def: (plural input tag parser) (All [a] (-> (Dictionary Text Code) Text (Parser a) (Parser (List a)))) - (.local (..as_input (dictionary.get tag input)) - (.tuple (<>.some parser)))) + (.local (..as_input (dictionary.get tag input)) + (.tuple (<>.some parser)))) (def: group (Parser //artifact.Group) - .text) + .text) (def: name (Parser //artifact.Name) - .text) + .text) (def: version (Parser //artifact.Version) - .text) + .text) (def: artifact' (Parser //artifact.Artifact) @@ -63,11 +63,11 @@ (def: artifact (Parser //artifact.Artifact) - (.tuple ..artifact')) + (.tuple ..artifact')) (def: url (Parser URL) - .text) + .text) (def: scm (Parser /.SCM) @@ -75,30 +75,30 @@ (def: description (Parser Text) - .text) + .text) (def: license (Parser /.License) (do {! <>.monad} [input (\ ! map (dictionary.from_list text.hash) - (.record (<>.some (<>.and .local_tag - .any))))] + (.record (<>.some (<>.and .local_tag + .any))))] ($_ <>.and (..singular input "name" ..name) (..singular input "url" ..url) (<>.default #/.Repo (..singular input "type" - (<>.or (.this! (' #repo)) - (.this! (' #manual)))))))) + (<>.or (.this! (' #repo)) + (.this! (' #manual)))))))) (def: organization (Parser /.Organization) (do {! <>.monad} [input (\ ! map (dictionary.from_list text.hash) - (.record (<>.some (<>.and .local_tag - .any))))] + (.record (<>.some (<>.and .local_tag + .any))))] ($_ <>.and (..singular input "name" ..name) (..singular input "url" ..url)))) @@ -108,8 +108,8 @@ (do {! <>.monad} [input (\ ! map (dictionary.from_list text.hash) - (.record (<>.some (<>.and .local_tag - .any))))] + (.record (<>.some (<>.and .local_tag + .any))))] ($_ <>.and (..singular input "name" ..name) (..singular input "url" ..url) @@ -125,8 +125,8 @@ (do {! <>.monad} [input (\ ! map (dictionary.from_list text.hash) - (.record (<>.some (<>.and .local_tag - .any))))] + (.record (<>.some (<>.and .local_tag + .any))))] ($_ <>.and (<>.maybe (..singular input "url" ..url)) (<>.maybe (..singular input "scm" ..scm)) @@ -143,11 +143,11 @@ (def: type (Parser //artifact/type.Type) - .text) + .text) (def: dependency (Parser //dependency.Dependency) - (.tuple + (.tuple ($_ <>.and ..artifact' (<>.default //artifact/type.lux_library ..type) @@ -155,32 +155,32 @@ (def: source (Parser /.Source) - .text) + .text) (def: target (Parser /.Target) - .text) + .text) (def: module (Parser Module) - .text) + .text) (def: deploy_repository (Parser (List [Text //repository.Address])) - (.record (<>.some - (<>.and .text - ..repository)))) + (.record (<>.some + (<>.and .text + ..repository)))) (def: profile (Parser /.Profile) (do {! <>.monad} [input (\ ! map (dictionary.from_list text.hash) - (.record (<>.some (<>.and .local_tag - .any)))) + (.record (<>.some (<>.and .local_tag + .any)))) #let [^parents (: (Parser (List /.Name)) (<>.default (list) - (..plural input "parents" .text))) + (..plural input "parents" .text))) ^identity (: (Parser (Maybe Artifact)) (<>.maybe (..singular input "identity" ..artifact))) @@ -236,7 +236,7 @@ multi_profile (: (Parser Project) (\ <>.monad map (dictionary.from_list text.hash) - (.record (<>.many (<>.and .text - ..profile)))))] + (.record (<>.many (<>.and .text + ..profile)))))] (<>.either multi_profile default_profile))) diff --git a/stdlib/source/program/compositor.lux b/stdlib/source/program/compositor.lux index 8b577ec09..b964e6502 100644 --- a/stdlib/source/program/compositor.lux +++ b/stdlib/source/program/compositor.lux @@ -102,10 +102,10 @@ analysis.Bundle (IO (Platform )) (generation.Bundle ) - (directive.Bundle ) + (-> platform.Phase_Wrapper (directive.Bundle )) (Program expression artifact) [Type Type Type] - Extender + (-> platform.Phase_Wrapper Extender) Service [Packager file.Path] (Promise Any))) diff --git a/stdlib/source/test/lux/extension.lux b/stdlib/source/test/lux/extension.lux index 8ff1cdc00..e20189fa3 100644 --- a/stdlib/source/test/lux/extension.lux +++ b/stdlib/source/test/lux/extension.lux @@ -10,18 +10,24 @@ ["." php] ["." scheme]] [abstract - [monad (#+ do)]] + ["." monad (#+ do)]] [control ["." try] ["<>" parser - ["" code] - ["" analysis] - ["" synthesis]]] + ["<.>" code] + ["<.>" analysis] + ["<.>" synthesis]]] [data + ["." product] ["." text ("#\." equivalence) ["%" format (#+ format)]] [collection - ["." row]]] + ["." row] + ["." list ("#\." functor)]]] + [math + ["." random] + [number + ["n" nat]]] [tool [compiler ["." phase] @@ -40,81 +46,96 @@ (def: my_analysis "my analysis") (def: my_synthesis "my synthesis") (def: my_generation "my generation") +(def: dummy_generation "dummy generation") (def: my_directive "my directive") ## Generation (for {@.old (as_is)} - (as_is (analysis: (..my_generation self phase archive {parameters (<>.some .any)}) - (do phase.monad - [_ (type.infer .Text)] - (wrap (#analysis.Extension self (list))))) + (as_is + ## Analysis + (analysis: (..my_analysis self phase archive {pass_through .any}) + (phase archive pass_through)) - (synthesis: (..my_generation self phase archive {parameters (<>.some .any)}) - (do phase.monad - [] - (wrap (#synthesis.Extension self (list))))) - )) + ## Synthesis + (analysis: (..my_synthesis self phase archive {parameters (<>.some .any)}) + (let [! phase.monad] + (|> parameters + (monad.map ! (phase archive)) + (\ ! map (|>> (#analysis.Extension self)))))) -(for {@.old - (as_is)} - - (generation: (..my_generation self phase archive {parameters (<>.some .any)}) - (do phase.monad - [] - (wrap (for {@.jvm - (row.row (#jvm.Constant (#jvm.LDC (#jvm.String self)))) + (synthesis: (..my_synthesis self phase archive {pass_through .any}) + (phase archive pass_through)) - @.js (js.string self) - @.python (python.unicode self) - @.lua (lua.string self) - @.ruby (ruby.string self) - @.php (php.string self) - @.scheme (scheme.string self)}))))) + ## Generation + (analysis: (..my_generation self phase archive {parameters (<>.some .any)}) + (let [! phase.monad] + (|> parameters + (monad.map ! (phase archive)) + (\ ! map (|>> (#analysis.Extension self)))))) -(for {@.old - (as_is)} - - (as_is (analysis: (..my_analysis self phase archive {parameters (<>.some .any)}) - (do phase.monad - [_ (type.infer .Text)] - (wrap (#analysis.Primitive (#analysis.Text self))))) + (synthesis: (..my_generation self phase archive {parameters (<>.some .any)}) + (let [! phase.monad] + (|> parameters + (monad.map ! (phase archive)) + (\ ! map (|>> (#synthesis.Extension self)))))) + + (generation: (..my_generation self phase archive {pass_through .any}) + (for {@.jvm + (\ phase.monad map (|>> #jvm.Embedded row.row) + (phase archive pass_through))} + (phase archive pass_through))) + + (analysis: (..dummy_generation self phase archive) + (\ phase.monad wrap (#analysis.Extension self (list)))) + + (synthesis: (..dummy_generation self phase archive) + (\ phase.monad wrap (#synthesis.Extension self (list)))) + + (generation: (..dummy_generation self phase archive) + (\ phase.monad wrap + (for {@.jvm + (row.row (#jvm.Constant (#jvm.LDC (#jvm.String self)))) - ## Synthesis - (analysis: (..my_synthesis self phase archive {parameters (<>.some .any)}) - (do phase.monad - [_ (type.infer .Text)] - (wrap (#analysis.Extension self (list))))) + @.js (js.string self) + @.python (python.unicode self) + @.lua (lua.string self) + @.ruby (ruby.string self) + @.php (php.string self) + @.scheme (scheme.string self)}))) - (synthesis: (..my_synthesis self phase archive {parameters (<>.some .any)}) - (do phase.monad - [] - (wrap (synthesis.text self)))) - - ## Directive - (directive: (..my_directive self phase archive {parameters (<>.some .any)}) - (do phase.monad - [#let [_ (debug.log! (format "Successfully installed directive " (%.text self) "!"))]] - (wrap directive.no_requirements))) + ## Directive + (directive: (..my_directive self phase archive {parameters (<>.some .any)}) + (do phase.monad + [#let [_ (debug.log! (format "Successfully installed directive " (%.text self) "!"))]] + (wrap directive.no_requirements))) - (`` ((~~ (static ..my_directive)))) - )) + (`` ((~~ (static ..my_directive)))) + )) (def: #export test Test (<| (_.covering /._) - (`` ($_ _.and - (~~ (template [ ] - [(_.cover [] - (for {@.old - false} - (text\= (`` ((~~ (static )))) - )))] + (do random.monad + [expected random.nat] + (`` ($_ _.and + (~~ (template [ ] + [(_.cover [] + (for {@.old + false} + (n.= expected + (`` ((~~ (static )) expected)))))] - [/.analysis: ..my_analysis] - [/.synthesis: ..my_synthesis] - [/.generation: ..my_generation])) - (_.cover [/.directive:] - true) - )))) + [/.analysis: ..my_analysis] + [/.synthesis: ..my_synthesis])) + (_.cover [/.generation:] + (for {@.old + false} + (and (n.= expected + (`` ((~~ (static ..my_generation)) expected))) + (text\= ..dummy_generation + (`` ((~~ (static ..dummy_generation)))))))) + (_.cover [/.directive:] + true) + ))))) diff --git a/stdlib/source/test/lux/time.lux b/stdlib/source/test/lux/time.lux index cc18c20e0..b22823626 100644 --- a/stdlib/source/test/lux/time.lux +++ b/stdlib/source/test/lux/time.lux @@ -1,21 +1,155 @@ (.module: [lux #* - ["_" test (#+ Test)]] + ["_" test (#+ Test)] + [abstract + [monad (#+ do)] + {[0 #spec] + [/ + ["$." equivalence] + ["$." order] + ["$." enum] + ["$." codec]]}] + [control + [pipe (#+ case>)] + ["." try ("#\." functor)] + ["." exception] + [parser + ["<.>" text]]] + [data + ["." text + ["%" format (#+ format)]]] + [math + ["." random] + [number + ["n" nat]]]] ["." / #_ ["#." date] ["#." day] ["#." duration] ["#." instant] ["#." month] - ["#." year]]) + ["#." year]] + {1 + ["." / + ["." duration]]}) -(def: #export test +(def: for_implementation Test ($_ _.and - /date.test - /day.test - /duration.test - /instant.test - /month.test - /year.test - )) + (_.for [/.equivalence] + ($equivalence.spec /.equivalence random.time)) + (_.for [/.order] + ($order.spec /.order random.time)) + (_.for [/.enum] + ($enum.spec /.enum random.time)) + (_.for [/.codec] + ($codec.spec /.equivalence /.codec random.time)))) + +(def: for_clock + Test + (do {! random.monad} + [expected random.time] + (_.cover [/.clock /.time] + (|> expected + /.clock + /.time + (try\map (\ /.equivalence = expected)) + (try.default false))))) + +(def: for_ranges + Test + (do {! random.monad} + [valid_hour (\ ! map (|>> (n.% /.hours) (n.max 10)) random.nat) + valid_minute (\ ! map (|>> (n.% /.minutes) (n.max 10)) random.nat) + valid_second (\ ! map (|>> (n.% /.seconds) (n.max 10)) random.nat) + valid_milli_second (\ ! map (n.% /.milli_seconds) random.nat) + + #let [invalid_hour (|> valid_hour (n.+ /.hours)) + invalid_minute (|> valid_minute (n.+ /.minutes) (n.min 99)) + invalid_second (|> valid_second (n.+ /.seconds) (n.min 99))]] + (`` ($_ _.and + (~~ (template [ ] + [(_.cover [ ] + (let [valid! + (|> + %.nat + (text.prefix ) + (text.suffix ) + (\ /.codec decode) + (case> (#try.Success _) true + (#try.Failure error) false)) + + invalid! + (|> + %.nat + (text.prefix ) + (text.suffix ) + (\ /.codec decode) + (case> (#try.Success _) + false + + (#try.Failure error) + (exception.match? error)))] + (and valid! + invalid!)))] + + [/.hours /.invalid_hour "" ":00:00.000" valid_hour invalid_hour] + [/.minutes /.invalid_minute "00:" ":00.000" valid_minute invalid_minute] + [/.seconds /.invalid_second "00:00:" ".000" valid_second invalid_second] + )) + (_.cover [/.milli_seconds] + (|> valid_milli_second + %.nat + (format "00:00:00.") + (\ /.codec decode) + (case> (#try.Success _) true + (#try.Failure error) false))) + )))) + +(def: #export test + Test + (<| (_.covering /._) + (_.for [/.Time]) + (do {! random.monad} + [#let [day (.nat (duration.to_millis duration.day))] + expected random.time + + out_of_bounds (\ ! map (|>> /.to_millis (n.+ day)) + random.time)] + (`` ($_ _.and + ..for_implementation + + (_.cover [/.to_millis /.from_millis] + (|> expected + /.to_millis + /.from_millis + (try\map (\ /.equivalence = expected)) + (try.default false))) + (_.cover [/.time_exceeds_a_day] + (case (/.from_millis out_of_bounds) + (#try.Success _) + false + + (#try.Failure error) + (exception.match? /.time_exceeds_a_day error))) + (_.cover [/.midnight] + (|> /.midnight + /.to_millis + (n.= 0))) + (_.cover [/.parser] + (|> expected + (\ /.codec encode) + (.run /.parser) + (try\map (\ /.equivalence = expected)) + (try.default false))) + ..for_ranges + (_.for [/.Clock] + ..for_clock) + + /date.test + /day.test + /duration.test + /instant.test + /month.test + /year.test + ))))) -- cgit v1.2.3