aboutsummaryrefslogtreecommitdiffstats
path: root/core/base/action.moon
diff options
context:
space:
mode:
Diffstat (limited to 'core/base/action.moon')
-rw-r--r--core/base/action.moon95
1 files changed, 95 insertions, 0 deletions
diff --git a/core/base/action.moon b/core/base/action.moon
new file mode 100644
index 0000000..0b9dc77
--- /dev/null
+++ b/core/base/action.moon
@@ -0,0 +1,95 @@
+----
+-- Builtin / Special Form / `Cell`-evaluation Strategy.
+--
+-- Responsible for quoting/evaluating subexpressions, instantiating and patching
+-- `Op`s, updating the current `Scope`, etc.
+-- See `builtin` and `invoke` for examples.
+--
+-- @classmod Action
+
+class Action
+--- Action interface.
+--
+-- methods that have to be implemented by `Action` implementations.
+-- @section interface
+
+ --- create a new instance
+ -- @tparam Value head the (`\eval`d) head of the Cell to evaluate
+ -- @tparam Tag tag the Tag of the expression to evaluate
+ new: (head, @tag) =>
+ @patch head
+
+ --- perform the actual evaluation
+ --
+ -- Implementations should:
+ --
+ -- - eval or quote `tail` values
+ -- - perform scope effects
+ -- - wrap all child-results
+ --
+ -- @tparam Scope scope the active scope
+ -- @tparam {AST,...} tail the arguments to this expression
+ -- @treturn Result the result of this evaluation
+ eval: (scope, tail) => error "not implemented"
+
+ --- free resources
+ destroy: =>
+
+ --- attempt to update this instance with a new `@head` prior to `\eval`.
+ --
+ -- If `\patch` returns `false`, this instance is `\destroy`ed and recreated.
+ -- Must *not* return `false` when called immediately after `\new`.
+ -- Only considered if Action types of old and new expression match.
+ --
+ -- @tparam AST head the new head value
+ -- @treturn bool whether patching was successful
+ patch: (head) =>
+ if head == @head
+ true
+
+ @head = head
+
+--- static functions
+-- @section static
+
+ --- get-or-update an `Action` for a given tag, then evaluate it.
+ --
+ -- Find the action for the expression with `Tag` `tag` if it exists,
+ -- and is compatible with the new `head`, otherwise instantiate one.
+ -- Register the `Action` with `tag`, evaluate it and return the `Result`.
+ --
+ -- @tparam Scope scope the active scope
+ -- @tparam Tag tag the tag of the `Cell` being evaluated
+ -- @tparam Value head the (`\eval`d) head of the `Cell` being evaluated
+ -- @tparam {Ast,...} tail the raw AST parameters to the `Cell` being evaluated
+ -- @treturn Result the result of evaluation
+ eval_cell: (scope, tag, head, tail) =>
+ last = tag\last!
+ compatible = last and
+ (last.__class == @) and
+ (last\patch head) and
+ last
+
+ L\trace if compatible
+ "reusing #{last} for #{tag} <#{@__name} #{head}>"
+ else if last
+ "replacing #{last} with new #{tag} <#{@__name} #{head}>"
+ else
+ "initializing #{tag} <#{@__name} #{head}>"
+
+ action = if compatible
+ tag\keep compatible
+ compatible
+ else
+ last\destroy! if last
+ with next = @ head, tag
+ tag\replace next
+
+ action\eval scope, tail
+
+ __tostring: => "<#{@@__name} #{@head}>"
+ __inherited: (cls) => cls.__base.__tostring = @__tostring
+
+{
+ :Action
+}