aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/program/aedifex/command
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/program/aedifex/command.lux8
-rw-r--r--stdlib/source/program/aedifex/command/auto.lux141
-rw-r--r--stdlib/source/program/aedifex/command/build.lux (renamed from stdlib/source/program/aedifex/build.lux)72
-rw-r--r--stdlib/source/program/aedifex/command/test.lux29
4 files changed, 215 insertions, 35 deletions
diff --git a/stdlib/source/program/aedifex/command.lux b/stdlib/source/program/aedifex/command.lux
new file mode 100644
index 000000000..8b4432a97
--- /dev/null
+++ b/stdlib/source/program/aedifex/command.lux
@@ -0,0 +1,8 @@
+(.module:
+ [lux #*]
+ ["." // #_
+ ["#" project]
+ ["#." action (#+ Action)]])
+
+(type: #export (Command a)
+ (-> //.Project (Action a)))
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/build.lux b/stdlib/source/program/aedifex/command/build.lux
index 74f64cb59..0e5d1e229 100644
--- a/stdlib/source/program/aedifex/build.lux
+++ b/stdlib/source/program/aedifex/command/build.lux
@@ -2,13 +2,13 @@
[lux (#- Name)
["." host (#+ import:)]
[abstract
- [monad (#+ Monad do)]]
+ [monad (#+ do)]]
[control
["." try (#+ Try)]
["." exception (#+ exception:)]
["." io (#+ IO)]
[concurrency
- ["." promise (#+ Promise) ("#@." monad)]]]
+ ["." promise ("#@." monad)]]]
[data
["." product]
["." maybe]
@@ -19,17 +19,15 @@
["." dictionary]]]
[world
["." file (#+ Path)]]]
- ["." // #_
+ ["." /// #_
["#" project]
- ["#." action (#+ Action)]
+ ["#." action]
+ ["#." command (#+ Command)]
["#." local]
["#." artifact (#+ Group Name Artifact)]
["#." dependency (#+ Dependency Resolution)]
["#." shell]])
-(type: #export (Command a)
- (-> //.Project (Action a)))
-
(type: Finder
(-> Resolution (Maybe Dependency)))
@@ -37,8 +35,8 @@
(-> 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)))
+ (if (and (text@= group (get@ [#///dependency.artifact #///artifact.group] dependency))
+ (text@= name (get@ [#///dependency.artifact #///artifact.name] dependency)))
(#.Some dependency)
#.None)))))
@@ -58,7 +56,7 @@
(exception: #export no-available-compiler)
(exception: #export no-specified-program)
-(type: Compiler
+(type: #export Compiler
(#JVM Artifact)
(#JS Artifact))
@@ -66,7 +64,7 @@
(-> Dependency (-> Resolution Resolution))
(|>> dictionary.entries
(list.filter (|>> product.left (is? dependency) not))
- (dictionary.from-list //dependency.hash)))
+ (dictionary.from-list ///dependency.hash)))
(def: (compiler resolution)
(-> Resolution (Try [Resolution Compiler]))
@@ -74,11 +72,11 @@
(..js-compiler resolution)]
[(#.Some dependency) _]
(#try.Success [(..remove-dependency dependency resolution)
- (#JVM (get@ #//dependency.artifact dependency))])
+ (#JVM (get@ #///dependency.artifact dependency))])
[_ (#.Some dependency)]
(#try.Success [(..remove-dependency dependency resolution)
- (#JS (get@ #//dependency.artifact dependency))])
+ (#JS (get@ #///dependency.artifact dependency))])
_
(exception.throw ..no-available-compiler [])))
@@ -86,8 +84,8 @@
(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)))))
+ (list.filter (|>> (get@ #///dependency.type) (text@= ///dependency.lux-library)))
+ (list@map (|>> (get@ #///dependency.artifact) (///local.path file.system)))))
(import: #long java/lang/String)
@@ -95,7 +93,7 @@
(import: #long java/lang/System
(#static getProperty [java/lang/String] #io #? java/lang/String))
-(def: working-directory
+(def: #export working-directory
(IO (Try Text))
(do io.monad
[?value (java/lang/System::getProperty "user.dir")]
@@ -110,35 +108,39 @@
(|> values (list@map (|>> (format name " "))) (text.join-with " ")))
(def: #export (do! project)
- (Command Any)
- (case (get@ #//.program 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)
+ (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)
+ (///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 (case compiler
- (#JVM artifact) (format "java -jar " (//local.path file.system artifact))
- (#JS artifact) (format "node --stack_size=8192 " (//local.path file.system artifact)))
- cache-directory (format working-directory (:: file.system separator) (get@ #//.target project))
+ [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))
+ " " (..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 END]")]]
- (wrap []))
+ 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 [])))