aboutsummaryrefslogtreecommitdiffstats
path: root/core/cell.moon
diff options
context:
space:
mode:
Diffstat (limited to 'core/cell.moon')
-rw-r--r--core/cell.moon121
1 files changed, 91 insertions, 30 deletions
diff --git a/core/cell.moon b/core/cell.moon
index 850a9db..4d46b64 100644
--- a/core/cell.moon
+++ b/core/cell.moon
@@ -1,12 +1,60 @@
--- ALV Cell type
+----
+-- S-Expression Cell, implements the `AST` interface.
+--
+-- Consists of a head expression and any number of tail expressions (both `AST`
+-- nodes), a `Tag`, and optionally the internal whitespace as parsed.
+--
+-- @classmod Cell
import Value from require 'core.value'
import op_invoke, fn_invoke from require 'core.invoke'
import Tag from require 'core.tag'
--- An S-Expression with a head expression and any number of tail expressions,
--- an optional tag, and optionally the internal whitespace as parsed.
+local RootCell
+
class Cell
--- AST interface
+--- methods
+-- @section methods
+
+ -- tag: the parsed Tag
+ -- children: sequence of child AST Nodes
+ -- white: optional sequence of whitespace segments ([0 .. #@children])
+ new: (@tag=Tag.blank!, @children, @white) =>
+ if not @white
+ @white = [' ' for i=1,#@children]
+ @white[0] = ''
+
+ assert #@white == #@children, "mismatched whitespace length"
+
+ --- get the head of the cell.
+ --
+ -- @treturn AST
+ head: => @children[1]
+
+ --- get the tail of the cell.
+ --
+ -- @treturn {AST,...}
+ tail: => [c for c in *@children[2,]]
+
+ __tostring: => @stringify 2
+
+--- AST interface
+--
+-- `Cell` implements the `AST` interface.
+-- @section ast
+
+ --- evaluate this Cell.
+ --
+ -- `\eval`uates the head of the expression, and finds the appropriate
+ -- `Action` to invoke:
+ --
+ -- - if head is an `opdef`, use `invoke.op_invoke`
+ -- - if head is a `fndef`, use `invoke.fn_invoke`
+ -- - if head is a `builtin`, unwrap it
+ --
+ -- then calls `\eval_cell` on the `Action`.
+ --
+ -- @tparam Scope scope the scope to evaluate in
+ -- @treturn Result the evaluation result
eval: (scope) =>
head = assert @head!, "cannot evaluate expr without head"
head = (head\eval scope)\const!
@@ -24,19 +72,36 @@ class Cell
Action\eval_cell scope, @tag, head, @tail!
- -- quoting a Cell recursively quotes children, but preserves identity. This
- -- means that a quoted Cell may only be 'used' once. Use :clone() otherwise.
+ --- quote this Cell, preserving its identity.
+ --
+ -- Recursively quotes children, but preserves identity (i.e, shares the
+ -- `Tag`). A quoted Cell may only be 'used' once. If you want to `\eval` a
+ -- `Cell` multiple times, use `\clone`.
+ --
+ -- @treturn Cell quoted
quote: (scope) =>
children = [child\quote scope for child in *@children]
Cell @tag, children, @white
+ --- create a clone with its own identity.
+ --
-- creates a clone of this Cell with its own identity by prepending a `parent`
- -- tag and cloning all child expressoins recursively.
+ -- to `@tag` and cloning all child expressoins recursively.
+ --
+ -- @treturn Cell clone
clone: (parent) =>
tag = @tag\clone parent
children = [child\clone parent for child in *@children]
Cell tag, children, @white
+ --- stringify this Cell.
+ --
+ -- if `depth` is passed, does not faithfully recreate the original string but
+ -- rather create useful debug output.
+ --
+ -- @tparam[opt] int depth the maximum depth, defaults to infinite
+ -- @treturn string the exact string this Cell was parsed from, unless `@tag`
+ -- changed
stringify: (depth=-1) =>
buf = ''
buf ..= if depth > 0 then '' else @white[0]
@@ -54,22 +119,8 @@ class Cell
'(' .. tag .. buf .. ')'
--- internal
- -- tag: the parsed Tag
- -- children: sequence of child AST Nodes
- -- white: optional sequence of whitespace segments ([0 .. #@children])
- new: (@tag=Tag.blank!, @children, @white) =>
- if not @white
- @white = [' ' for i=1,#@children]
- @white[0] = ''
-
- assert #@white == #@children, "mismatched whitespace length"
-
- head: => @children[1]
- tail: => [c for c in *@children[2,]]
-
--- static
- __tostring: => @stringify 2
+--- static functions
+-- @section static
parse_args = (tag, parts) ->
if not parts
@@ -82,13 +133,26 @@ class Cell
white[i/2] = parts[i+1]
tag, children, white
- @parse: (...) =>
+ --- parse a Cell (for parsing with Lpeg).
+ --
+ -- @tparam[opt] Tag tag
+ -- @tparam table parts
+ -- @treturn Cell
+ parse: (...) =>
tag, children, white = parse_args ...
@ tag, children, white
--- A parenthesis-less Cell (root of an ALV document).
---
--- has an implicit head of 'do'.
+ --- parse a root Cell (for parsing with Lpeg).
+ --
+ -- Root-Cells are at the root of an ALV document.
+ -- They have an implicit head of 'do' and a `[0]` tag.
+ --
+ -- @tparam table parts
+ -- @treturn Cell
+ parse_root: (parts) =>
+ RootCell.parse RootCell, (Tag\parse '0'), parts
+
+-- @type RootCell
class RootCell extends Cell
head: => Value.sym 'do'
tail: => @children
@@ -103,9 +167,6 @@ class RootCell extends Cell
buf
- @parse: (...) =>
- @__parent.parse @, (Tag\parse '0'), ...
-
{
:Cell
:RootCell