diff options
author | Eduardo Julian | 2020-08-29 01:06:42 -0400 |
---|---|---|
committer | Eduardo Julian | 2020-08-29 01:06:42 -0400 |
commit | b1f0014dd9080c6643ecd73db5233fbdff032419 (patch) | |
tree | 63650a451b0974a5654b06bf4f33dae7deceef54 /stdlib/source/program/aedifex/command | |
parent | a5a15c191c43a660bb0c8e78e93d097e27966177 (diff) |
Test programs + auti build/test.
Diffstat (limited to 'stdlib/source/program/aedifex/command')
-rw-r--r-- | stdlib/source/program/aedifex/command/auto.lux | 141 | ||||
-rw-r--r-- | stdlib/source/program/aedifex/command/build.lux | 146 | ||||
-rw-r--r-- | stdlib/source/program/aedifex/command/test.lux | 29 |
3 files changed, 316 insertions, 0 deletions
diff --git a/stdlib/source/program/aedifex/command/auto.lux b/stdlib/source/program/aedifex/command/auto.lux new file mode 100644 index 000000000..5bf759a06 --- /dev/null +++ b/stdlib/source/program/aedifex/command/auto.lux @@ -0,0 +1,141 @@ +(.module: + [lux #* + ["." host (#+ import:)] + [abstract + ["." monad (#+ do)]] + [control + ["." try (#+ Try)] + ["." io (#+ IO)] + [concurrency + ["." promise]]] + [data + [collection + ["." array] + ["." list]]] + [world + [file (#+ Path)]]] + ["." // #_ + ["/#" // #_ + ["#" project] + ["#." action (#+ Action)] + ["#." command (#+ Command)]]]) + +(import: #long java/nio/file/WatchKey + (reset [] #io boolean)) + +(import: #long java/util/concurrent/TimeUnit + (#enum SECONDS)) + +(import: #long java/nio/file/WatchService + (poll [long java/util/concurrent/TimeUnit] #io #try #? java/nio/file/WatchKey) + (poll #as fetch [] #io #try #? java/nio/file/WatchKey)) + +(import: #long java/nio/file/FileSystem + (newWatchService [] #io #try java/nio/file/WatchService)) + +(import: #long java/nio/file/FileSystems + (#static getDefault [] java/nio/file/FileSystem)) + +(import: #long java/lang/Object) + +(import: #long java/lang/String) + +(import: #long (java/nio/file/WatchEvent$Kind a)) + +(import: #long java/nio/file/StandardWatchEventKinds + (#static ENTRY_CREATE (java/nio/file/WatchEvent$Kind java/nio/file/Path)) + (#static ENTRY_MODIFY (java/nio/file/WatchEvent$Kind java/nio/file/Path)) + (#static ENTRY_DELETE (java/nio/file/WatchEvent$Kind java/nio/file/Path))) + +(import: #long java/nio/file/Path + (register [java/nio/file/WatchService [(java/nio/file/WatchEvent$Kind ?)]] #io #try java/nio/file/WatchKey)) + +(import: #long java/io/File + (new [java/lang/String]) + (exists [] #io #try boolean) + (isDirectory [] #io #try boolean) + (listFiles [] #io #try [java/io/File]) + (getAbsolutePath [] #io #try java/lang/String) + (toPath [] java/nio/file/Path)) + +(def: (targets path) + (-> Path (Action (List Path))) + (promise.future + (loop [path path] + (let [file (java/io/File::new path)] + (do {@ (try.with io.monad)} + [exists? (java/io/File::exists file) + directory? (java/io/File::isDirectory file)] + (if (and exists? + directory?) + (do @ + [children (java/io/File::listFiles file) + children (|> children + array.to-list + (monad.map @ (|>> java/io/File::getAbsolutePath))) + descendants (monad.map @ recur children)] + (wrap (#.Cons path (list.concat descendants)))) + (wrap (list)))))))) + +(type: Watch-Event + (java/nio/file/WatchEvent$Kind java/lang/Object)) + +(def: watch-events + (List Watch-Event) + (list (:coerce Watch-Event (java/nio/file/StandardWatchEventKinds::ENTRY_CREATE)) + (:coerce Watch-Event (java/nio/file/StandardWatchEventKinds::ENTRY_MODIFY)) + (:coerce Watch-Event (java/nio/file/StandardWatchEventKinds::ENTRY_DELETE)))) + +(def: (watch! watcher path) + (-> java/nio/file/WatchService Path (Action Any)) + (promise.future + (do (try.with io.monad) + [_ (java/nio/file/Path::register watcher + (array.from-list ..watch-events) + (|> path java/io/File::new java/io/File::toPath))] + (wrap [])))) + +(def: (poll! watcher) + (-> java/nio/file/WatchService (Action (Maybe java/nio/file/WatchKey))) + (promise.future + (java/nio/file/WatchService::poll 1 java/util/concurrent/TimeUnit::SECONDS watcher))) + +(def: (drain! watcher) + (-> java/nio/file/WatchService (IO (Try Any))) + (do (try.with io.monad) + [?key (java/nio/file/WatchService::fetch watcher)] + (case ?key + (#.Some key) + (do io.monad + [valid? (java/nio/file/WatchKey::reset key)] + (if valid? + (drain! watcher) + (wrap (:: try.monad wrap [])))) + + #.None + (wrap [])))) + +(def: #export (do! command project) + (All [a] (-> (Command a) (Command Any))) + (do {@ ///action.monad} + [#let [fs (java/nio/file/FileSystems::getDefault)] + watcher (promise.future (java/nio/file/FileSystem::newWatchService fs)) + targets (|> project + (get@ #///.sources) + (monad.map @ ..targets) + (:: @ map list.concat)) + _ (monad.map @ (..watch! watcher) targets) + _ (command project)] + (loop [_ []] + (do @ + [?key (..poll! watcher) + _ (case ?key + (#.Some key) + (do @ + [_ (promise.future (..drain! watcher)) + _ (command project)] + (wrap [])) + + #.None + (wrap []))] + (recur []))))) diff --git a/stdlib/source/program/aedifex/command/build.lux b/stdlib/source/program/aedifex/command/build.lux new file mode 100644 index 000000000..0e5d1e229 --- /dev/null +++ b/stdlib/source/program/aedifex/command/build.lux @@ -0,0 +1,146 @@ +(.module: + [lux (#- Name) + ["." host (#+ import:)] + [abstract + [monad (#+ do)]] + [control + ["." try (#+ Try)] + ["." exception (#+ exception:)] + ["." io (#+ IO)] + [concurrency + ["." promise ("#@." monad)]]] + [data + ["." product] + ["." maybe] + ["." text ("#@." equivalence) + ["%" format (#+ format)]] + [collection + ["." list ("#@." functor)] + ["." dictionary]]] + [world + ["." file (#+ Path)]]] + ["." /// #_ + ["#" project] + ["#." action] + ["#." command (#+ Command)] + ["#." local] + ["#." artifact (#+ Group Name Artifact)] + ["#." dependency (#+ Dependency Resolution)] + ["#." shell]]) + +(type: Finder + (-> Resolution (Maybe Dependency))) + +(def: (dependency-finder group name) + (-> Group Name Finder) + (|>> dictionary.entries + (list.search (function (_ [dependency package]) + (if (and (text@= group (get@ [#///dependency.artifact #///artifact.group] dependency)) + (text@= name (get@ [#///dependency.artifact #///artifact.name] dependency))) + (#.Some dependency) + #.None))))) + +(def: lux-group + Group + "com.github.luxlang") + +(template [<name> <finder>] + [(def: <finder> + Finder + (..dependency-finder ..lux-group <name>))] + + ["lux-jvm" jvm-compiler] + ["lux-js" js-compiler] + ) + +(exception: #export no-available-compiler) +(exception: #export no-specified-program) + +(type: #export Compiler + (#JVM Artifact) + (#JS Artifact)) + +(def: (remove-dependency dependency) + (-> Dependency (-> Resolution Resolution)) + (|>> dictionary.entries + (list.filter (|>> product.left (is? dependency) not)) + (dictionary.from-list ///dependency.hash))) + +(def: (compiler resolution) + (-> Resolution (Try [Resolution Compiler])) + (case [(..jvm-compiler resolution) + (..js-compiler resolution)] + [(#.Some dependency) _] + (#try.Success [(..remove-dependency dependency resolution) + (#JVM (get@ #///dependency.artifact dependency))]) + + [_ (#.Some dependency)] + (#try.Success [(..remove-dependency dependency resolution) + (#JS (get@ #///dependency.artifact dependency))]) + + _ + (exception.throw ..no-available-compiler []))) + +(def: libraries + (-> Resolution (List Path)) + (|>> dictionary.keys + (list.filter (|>> (get@ #///dependency.type) (text@= ///dependency.lux-library))) + (list@map (|>> (get@ #///dependency.artifact) (///local.path file.system))))) + +(import: #long java/lang/String) + +## https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html +(import: #long java/lang/System + (#static getProperty [java/lang/String] #io #? java/lang/String)) + +(def: #export working-directory + (IO (Try Text)) + (do io.monad + [?value (java/lang/System::getProperty "user.dir")] + (wrap (#try.Success (maybe.default "~" ?value))))) + +(def: (singular-parameter name value) + (-> Text Text Text) + (format name " " value)) + +(def: (plural-parameter name values) + (-> Text (List Text) Text) + (|> values (list@map (|>> (format name " "))) (text.join-with " "))) + +(def: #export (do! project) + (Command [Compiler + Path]) + (case (get@ #///.program project) + (#.Some program) + (do ///action.monad + [cache (///local.all-cached (file.async file.system) + (get@ #///.dependencies project) + ///dependency.empty) + resolution (promise.future + (///dependency.resolve-all (get@ #///.repositories project) + (get@ #///.dependencies project) + cache)) + _ (///local.cache-all (file.async file.system) + resolution) + [resolution compiler] (promise@wrap (..compiler resolution)) + working-directory (promise.future ..working-directory) + #let [libraries (..libraries resolution) + [prefix output] (case compiler + (#JVM artifact) [(format "java -jar " (///local.path file.system artifact)) + "program.jar"] + (#JS artifact) [(format "node --stack_size=8192 " (///local.path file.system artifact)) + "program.js"]) + cache-directory (format working-directory (:: file.system separator) (get@ #///.target project)) + command (format prefix " build" + " " (..plural-parameter "--library" libraries) + " " (..plural-parameter "--source" (get@ #///.sources project)) + " " (..singular-parameter "--target" cache-directory) + " " (..singular-parameter "--module" program))] + #let [_ (log! "[BUILD STARTED]")] + outcome (///shell.execute command working-directory) + #let [_ (log! "[BUILD ENDED]")]] + (wrap [compiler + (format cache-directory (:: file.system separator) output)])) + + #.None + (promise@wrap (exception.throw ..no-specified-program [])))) diff --git a/stdlib/source/program/aedifex/command/test.lux b/stdlib/source/program/aedifex/command/test.lux new file mode 100644 index 000000000..a27c07f10 --- /dev/null +++ b/stdlib/source/program/aedifex/command/test.lux @@ -0,0 +1,29 @@ +(.module: + [lux (#- Name) + [abstract + [monad (#+ do)]] + [control + [concurrency + ["." promise]]] + [data + [text + ["%" format (#+ format)]]]] + ["." // #_ + ["#." build] + ["/#" // #_ + ["#." action] + ["#." command (#+ Command)] + ["#." shell]]]) + +(def: #export (do! project) + (Command Any) + (do ///action.monad + [[compiler program] (//build.do! project) + working-directory (promise.future //build.working-directory) + #let [command (case compiler + (#//build.JVM artifact) (format "java -jar " program) + (#//build.JS artifact) (format "node --stack_size=8192 " program))] + #let [_ (log! "[TEST STARTED]")] + outcome (///shell.execute command working-directory) + #let [_ (log! "[TEST ENDED]")]] + (wrap []))) |