aboutsummaryrefslogtreecommitdiffstats
path: root/alv/module.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-04-24 12:14:31 +0000
committers-ol <s-ol@users.noreply.github.com>2020-04-24 12:27:34 +0000
commitf1eb271d4701494e4faa2d71e45ad8ec4aa635a4 (patch)
treefea24fb48fc58a8cd3c8dd8721b9068bc631fb7f /alv/module.moon
parentmove tick-counting into COPILOT (diff)
downloadalive-f1eb271d4701494e4faa2d71e45ad8ec4aa635a4.tar.gz
alive-f1eb271d4701494e4faa2d71e45ad8ec4aa635a4.zip
better (require) implementation
Close #16
Diffstat (limited to 'alv/module.moon')
-rw-r--r--alv/module.moon78
1 files changed, 78 insertions, 0 deletions
diff --git a/alv/module.moon b/alv/module.moon
new file mode 100644
index 0000000..b6244d8
--- /dev/null
+++ b/alv/module.moon
@@ -0,0 +1,78 @@
+----
+-- Per-file execution context.
+--
+-- @classmod Module
+import Registry from require 'alv.registry'
+import Error from require 'alv.error'
+import Scope from require 'alv.scope'
+import program from require 'alv.parsing'
+builtin = require 'alv.builtin'
+
+slurp = (file) ->
+ file = assert (io.open file, 'r'), Error 'io', "couldn't open '#{file}'"
+ with file\read '*all'
+ file\close!
+
+spit = (file, str) ->
+ file = io.open file, 'w'
+ file\write str
+ file\close!
+
+class Module
+--- static functions
+-- @section static
+
+ --- create a new Module.
+ -- @classmethod
+ new: (@file) =>
+ @registry = Registry!
+ @last_modification = 0
+
+--- members
+-- @section members
+
+ --- check whether file was changed.
+ -- @treturn bool whether the file was changed since the last call
+ poll: =>
+ { :mode, :modification } = (lfs.attributes @file) or {}
+ assert mode == 'file', Error 'io', "not a file: '#{file}'"
+
+ if @last_modification < modification
+ true
+
+ --- start an evaluation cycle.
+ --
+ -- If the module has already been evaluated this tick, this is a noop.
+ -- Otherwise, register the module with the `Copilot`. Updates `root`.
+ eval: =>
+ @last_modification = os.time!
+ @ast = Error.wrap "parsing '#{@file}'", -> program\match slurp @file
+ assert @ast, Error 'syntax', "failed to parse"
+
+ scope = Scope builtin
+ @registry\begin_eval!
+ @root = Error.wrap "evaluating '#{@file}'", @ast\eval, scope, @registry
+ @registry\release!
+
+ --- rollback the last evaluation cycle.
+ rollback: => @registry\rollback_eval!
+
+ --- finish the last evaluation cycle.
+ finish: =>
+ tags_changed = @registry\end_eval!
+ if tags_changed
+ spit @file, @ast\stringify!
+
+ --- destroy this module.
+ destroy: =>
+ @registry\destroy!
+
+ --- the last updated AST tree for this module.
+ -- @tfield ?AST ast
+
+ --- the root Result of this module.
+ -- @tfield ?Result root
+
+{
+ :Module
+}