diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-04-24 12:14:31 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-04-24 12:27:34 +0000 |
| commit | f1eb271d4701494e4faa2d71e45ad8ec4aa635a4 (patch) | |
| tree | fea24fb48fc58a8cd3c8dd8721b9068bc631fb7f /alv/module.moon | |
| parent | move tick-counting into COPILOT (diff) | |
| download | alive-f1eb271d4701494e4faa2d71e45ad8ec4aa635a4.tar.gz alive-f1eb271d4701494e4faa2d71e45ad8ec4aa635a4.zip | |
better (require) implementation
Close #16
Diffstat (limited to 'alv/module.moon')
| -rw-r--r-- | alv/module.moon | 78 |
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 +} |
