The dash AST itself is defined in src/nodes.h and src/parser.h
-
union nodeinsrc/nodes.hon line 146 for commands/statements node.type type tagnode.nbinary (AND, OR, SEMI)
-
special characters and codes in
parser.hon lines 40-64CTL* for control codes in words breaks multibyte characters/UTF-8 :(
VS* for variable format metadata
The parser in src/parser.c is not easy to read, but is a good place
to see dash ASTs being constructed.
Input sources come in a stack (to support, e.g., the source/.
command). Dash has some subtle invariants around its own string
allocation stack... it took quite some time to get it right in Smoosh,
so don't try to "optimize" things! (See
mgree/smoosh#18 for test cases.)
To get a gist for how they're used, look at evaltree at line 200 in
src/eval.c. To see how the special characters and codes are used,
see argstr at line 23 in src/expand.c.
The core OCaml bindings are in ocaml/dash.ml. The bindings are
dynamically loaded by ctypes. (It's a longstanding TODO to make these
bindings static, as it would significantly simplify the build process.)
Lines 69 through 233 are just copying the definitions from
src/nodes.h.
The primary API entry point is parse_next, which returns one of a
few results:
-
Donewhen EOF (dash returns the special nodeneof, notNULL!) has been reached for the current input. -
Errorwhen parsing failed (dash returns the special nodenerr, notNULL!). -
Nullwhen there was no command, e.g., a blank line (dash returnsNULLhere). -
Parsed nfor somenode,n. Note thatnis a dash AST, i.e., a ctypes structure.
These nodes are dash AST nodes not yet a usable OCaml structure.
See ocaml/ast.ml (or Smoosh's src/shim.ml for a more
battle-hardened, nearly but not quite identical version of the same
code) for the of_node entry point that converts dash AST nodes to
OCaml structures.
parse_arg is a funny a stack machine, best thought of as a for loop
with an explicit stack. There are some tricky extra bits of
information to track (i.e., when tildes are possible, whether we're in
an assignment).
Call Dash.initialize, then Dash.parse with the string you
have. Call Ast.of_node on the resulting dash AST to get a nice OCaml
structure. Look at ocaml/rt.sh (and the binaries it calls) and
python/rt.py for examples.
To cut a new release, you must update the version numbers in
setup.py, pyproject.toml, and dune-workspace. A CI lint job will
check to ensure that they are the same.
PyPI releases are automatic via GH CI. OCaml releases are via
dune-release.