miller/pkg/dsl/cst
John Kerl a55327c7ef
Add sparkline DSL function and mlr sparkline verb (#166) (#2177)
Adds a sparkline(array|map) built-in that renders numeric values as a
Unicode block-character string (▁▂▃▄▅▆▇█), plus a new `mlr sparkline`
verb that summarizes each field's values in record order -- useful for
eyeballing trends without external plotting tools.

Also adds `-s` to `mlr histogram` to sparkline a field's binned counts
(its distribution shape) rather than emitting one record per bin. This
is a different chart from `mlr sparkline` (order-independent binning
vs. record-order values), and the docs for each cross-reference the
other to avoid conflating them.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 15:47:01 -04:00
..
assignments.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
ast_types.go Add a first-class bytes type to the DSL, with b"..." literals and base64/hex codecs (#2122) 2026-07-03 11:58:44 -04:00
block_exit.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
blocks.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
builtin_function_manager.go Add sparkline DSL function and mlr sparkline verb (#166) (#2177) 2026-07-07 15:47:01 -04:00
builtin_function_manager_json.go Switch to --as-json (#2106) 2026-06-28 17:04:10 -04:00
builtin_functions.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
collections.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
cond.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
doc.go Export library code in pkg/ (#1391) 2023-09-10 17:15:13 -04:00
dump.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
emit1.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
emit_emitp.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
emitf.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
env.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
evaluable.go Add a first-class bytes type to the DSL, with b"..." literals and base64/hex codecs (#2122) 2026-07-03 11:58:44 -04:00
filter.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
for.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
functions.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
hofs.go Experiment with mlr script (#2009) 2026-03-05 20:14:32 -05:00
if.go Convert if/else-if chains to typed switch statements (staticcheck QF1003) (#2112) 2026-06-28 18:27:42 -04:00
keyword_usage.go Shell tab-completion for bash and zsh (#2096) 2026-06-21 12:47:54 -04:00
keyword_usage_json.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
leaves.go Add a first-class bytes type to the DSL, with b"..." literals and base64/hex codecs (#2122) 2026-07-03 11:58:44 -04:00
lvalues.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
print.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
README.md Update performance docs (#1991) 2026-02-22 17:04:35 -05:00
root.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
signature.go Multiple style updates (#1974) 2026-02-16 15:49:21 -05:00
statements.go Next batch of lint fixes (#2108) 2026-06-28 17:36:36 -04:00
subroutines.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
tee.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
types.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
udf.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
uds.go Lint round 5+6: staticcheck and errcheck to zero (#2130) 2026-07-03 11:42:08 -04:00
validate.go Next batch of lint fixes (#2108) 2026-06-28 17:36:36 -04:00
warn.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00
while.go Replace GOCC parser-generator with PGPG (#2015) 2026-03-15 22:28:57 -04:00

See ../dsl/README.md for more information about Miller's use of abstract syntax trees (ASTs) and concrete syntax trees (CSTs) within the Miller put/filter domain-specific language (DSL).

Files

  • types.go is a starting point for seeing datatypes involved in the concrete syntax tree.
    • IExecutable is the interface for executable nodes, such as assignment statements, or statement blocks (if-bodies, etc.).
    • IEvaluable is the interface for evaluable expressions (e.g. right-hand sides of assignment statements).
  • root.go contains the top-level logic for building a CST from an AST at parse time (cstRoot, err := cst.Build(astRoot)), as well as executing the CST on a per-record basis (cstRoot.Execute(runtimeState)). See also the put transformer.

Notes

Go is a strongly typed language, but the AST is polymorphic. This results in if/else or switch statements as an AST is walked.

Also, when we modify code, there can be changes in the BNF grammar not yet reflected in the AST. Likewise, there can be AST changes not yet reflected here. (Example: you are partway through adding a new binary operator to the grammar.)

As a result, throughout the code, there are error checks which may seem redundant but which are in place to make incremental development more pleasant and robust.

During CST build from an AST, one starts from the AST root and walks down through the nodes of the AST. Within a caller method, there is an if/else or switch statement on the AST node type. (Example: is this a leaf node, like the string literal "abcd", int literal 3, field-name $x? Or a binary operator like +, or function call like cos?).

Different builder methods are invoked for leaves, operators, etc. There is also, redundantly, a precondition assertion within each builder method: the leaf-builder method checks to make sure it's given an AST leaf node to build from; the operator-builder method checks to make sure it's given an AST operator node to build from; etc. The caller and the callee are doing the same kinds of check, which might seem redundant. The callees return Go error in case there is something new in the caller which has not yet been implemented in the callee.

This is all done to make development more happy: when you see things like CST build: AST unary operator node unhandled you can check the code here and see what you need to do next to continue development.