PtcRunner.Lisp.DataKeys (PtcRunner v0.14.0)

Copy Markdown View Source

Static analysis to extract data keys accessed by a PTC-Lisp program.

Walks the Core AST to find all {:data, key} nodes, which represent data/xxx access patterns in the source code.

This enables context optimization by loading only the datasets actually needed by the program, reducing memory pressure during execution.

Example

iex> {:ok, ast} = PtcRunner.Lisp.Parser.parse("(count data/products)")
iex> {:ok, core_ast} = PtcRunner.Lisp.Analyze.analyze(ast)
iex> PtcRunner.Lisp.DataKeys.extract(core_ast)
MapSet.new([:products])

Summary

Functions

Extracts all data keys accessed by a program.

Filters a context map to only include keys accessed by the program.

Returns the sorted data/<name> source forms for the keys of data that can be written as a data/<name> reference.

Functions

extract(ast)

@spec extract(term()) :: MapSet.t()

Extracts all data keys accessed by a program.

Returns a MapSet of atoms/strings representing the keys accessed via data/xxx.

Examples

iex> {:ok, ast} = PtcRunner.Lisp.Parser.parse("(+ (count data/foo) (count data/bar))")
iex> {:ok, core_ast} = PtcRunner.Lisp.Analyze.analyze(ast)
iex> keys = PtcRunner.Lisp.DataKeys.extract(core_ast)
iex> Enum.sort(keys)
[:bar, :foo]

filter_context(ast, ctx)

@spec filter_context(term(), map()) :: map()

Filters a context map to only include keys accessed by the program.

Keys not present in the context are silently ignored (the program may reference data that doesn't exist, which will be handled at runtime).

Examples

iex> {:ok, ast} = PtcRunner.Lisp.Parser.parse("(count data/products)")
iex> {:ok, core_ast} = PtcRunner.Lisp.Analyze.analyze(ast)
iex> ctx = %{"products" => [1,2,3], "orders" => [4,5,6], "question" => "test"}
iex> PtcRunner.Lisp.DataKeys.filter_context(core_ast, ctx)
%{"products" => [1,2,3], "question" => "test"}

source_referenceable_forms(data)

@spec source_referenceable_forms(map()) :: [binary()]

Returns the sorted data/<name> source forms for the keys of data that can be written as a data/<name> reference.

Names that cannot be parsed as that form are omitted. Every granted-name list the runtime publishes or prints comes from here: mission inventory entries and the mission and workflow missing-grant diagnostics all consume this rather than selecting forms independently, so the list a user is shown always matches the list that resolves.

Examples

iex> PtcRunner.Lisp.DataKeys.source_referenceable_forms(%{"b" => 1, "a" => 2})
["data/a", "data/b"]

iex> PtcRunner.Lisp.DataKeys.source_referenceable_forms(%{"not a symbol" => 1})
[]