aboutsummaryrefslogtreecommitdiffstats
path: root/alv/copilot.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-04-13 18:40:35 +0000
committers-ol <s-ol@users.noreply.github.com>2020-04-14 08:46:54 +0000
commit1a8debe87762072b3a63b769aa515ebf63b4c70d (patch)
tree33b42866307d11d2c0878b23e0ec0bb8925d3fcc /alv/copilot.moon
parentspec base.match __tostring (diff)
downloadalive-1a8debe87762072b3a63b769aa515ebf63b4c70d.tar.gz
alive-1a8debe87762072b3a63b769aa515ebf63b4c70d.zip
move into proper Lua module (`alv`)
Diffstat (limited to 'alv/copilot.moon')
-rw-r--r--alv/copilot.moon85
1 files changed, 85 insertions, 0 deletions
diff --git a/alv/copilot.moon b/alv/copilot.moon
new file mode 100644
index 0000000..478cbae
--- /dev/null
+++ b/alv/copilot.moon
@@ -0,0 +1,85 @@
+----
+-- File watcher and CLI entrypoint.
+--
+-- @classmod Copilot
+lfs = require 'lfs'
+import Scope from require 'alv.scope'
+import Registry from require 'alv.registry'
+import Error from require 'alv.error'
+import program from require 'alv.parsing'
+globals = Scope.from_table require 'alv.builtin'
+
+slurp = (file) ->
+ file = io.open file, 'r'
+ with file\read '*all'
+ file\close!
+
+spit = (file, str) ->
+ file = io.open file, 'w'
+ file\write str
+ file\close!
+
+class Copilot
+--- static functions
+-- @section static
+
+ --- create a new Copilot.
+ -- @classmethod
+ -- @tparam string file name/path of the alive file to watch and execute
+ new: (@file) =>
+ @registry = Registry!
+
+ @last_modification = 0
+
+ mode = lfs.attributes @file, 'mode'
+ if mode != 'file'
+ error "not a file: #{@file}"
+
+--- members
+-- @section members
+
+ --- poll for changes and tick.
+ tick: =>
+ @poll!
+
+ if @root
+ @registry\begin_tick!
+ ok, error = Error.try "updating", ->
+ @root\tick_io!
+ @root\tick!
+ if not ok
+ print error
+ @registry\end_tick!
+
+ eval: =>
+ @registry\begin_eval!
+ ok, ast = Error.try "parsing '#{@file}'", program\match, slurp @file
+ if not (ok and ast)
+ print ast or Error 'syntax', "failed to parse"
+ @registry\rollback_eval!
+ return
+
+ scope = Scope globals
+ ok, root = Error.try "evaluating '#{@file}'", ast\eval, scope, @registry
+ if not ok
+ print root
+ @registry\rollback_eval!
+ return
+
+ @registry\end_eval!
+ @root = root
+ spit @file, ast\stringify!
+
+ poll: =>
+ { :mode, :modification } = (lfs.attributes @file) or {}
+ if mode != 'file'
+ return
+
+ if @last_modification < modification
+ L\log "#{@file} changed at #{modification}"
+ @eval!
+ @last_modification = os.time!
+
+{
+ :Copilot
+}