Documentation
¶
Overview ¶
Package scriptflow derives a managed script's flow graph from its source (#1906): what the script reads, what it writes, what it produces, and which results feed which calls. The script page draws it on its Flow tab.
Nobody authors the graph. It is read from the parse tree, so a new version of a script has a new graph with nobody updating it, and the graph cannot disagree with the code. That is possible because the dialect is small (internal/platform/scriptdialect): no imports, no classes, no exceptions and no while, so every loop is a for over a value. Recursion is refused by the interpreter when a recursive call is made, so the walk expands a user function at every place it is called except inside its own expansion, where a run would fail.
The rules the graph is built by:
- Every platform.* call is a step, except platform.progress.
- Edges follow values. A value carries the set of steps (and run.state) it was computed from, and a step's inputs are the origins of its arguments. The user functions a value passed through on the way are recorded on the edge.
- A user function is expanded at each call site, so a helper called for three purposes is three steps, each rendered with its caller's arguments.
- A function holding steps is one box per enclosing box, captioned with its author's comment. A function whose only effect is one platform call is not a box: it is folded into the step and named on it.
- Names are rendered from the source: literals and module constants by value, string building with each computed part as {its source}.
- An edge a longer path already implies is removed.
- Parameters are not drawn. Each is listed with the steps its value reaches.
- A connection, destination, tool, table or target the source computes marks its step computed; the graph never names a guessed one.
Index ¶
Constants ¶
const ( RoleInput = "input" RoleReads = "reads" RoleWrites = "writes" RoleOutput = "output" )
Roles a step plays, which the diagram colors it by.
const ( KindQuery = "query" KindAPI = "api" KindTool = "tool" KindWrite = "write" KindExport = "export" KindTable = "table" KindPublishData = "publish_data" KindSaveState = "save_state" KindNotify = "notify" KindPublish = "publish" KindResult = "result" KindState = "state" )
Kinds of step, which name what the step is.
const ( EdgeData = "data" EdgeState = "state" )
Edge kinds: a value passed from one step to the next, or this run saving state for the next run.
const ( ChangeAdded = "added" ChangeChanged = "changed" ChangeRemoved = "removed" )
Change marks on a compared graph's nodes (#1908).
const ( StructStart = "start" StructEnd = "end" StructStop = "stop" StructReturn = "return" StructIf = "if" StructStep = "step" )
Kinds of structure node.
const ( BoxLoop = "loop" BoxFunction = "function" )
Kinds of structure box.
const ( ArmYes = "yes" ArmNo = "no" )
Arm labels on the edges out of an if.
const StateNodeID = "state"
StateNodeID is the id of the node standing for run.state.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Edge ¶
type Edge struct {
From string `json:"from"`
To string `json:"to"`
// Via names the functions that reshaped the value on the way.
Via []string `json:"via"`
Kind string `json:"kind" example:"data"`
// Change is "removed" on an edge of a compared graph that only the older
// version had.
Change string `json:"change,omitempty"`
}
Edge is one value passed from a step to another, or the state saved for the next run.
type FuncSpan ¶ added in v1.138.1
type FuncSpan struct {
Name string `json:"name"`
Line int `json:"line"`
EndLine int `json:"end_line"`
}
FuncSpan is one def and the lines it covers.
type Function ¶ added in v1.138.1
type Function struct {
Name string `json:"name" example:"last_week"`
// Params is each parameter as the source writes it, a default included.
Params []string `json:"params" example:"today,days=7"`
// Doc is the first sentence of the function's docstring.
Doc string `json:"doc,omitempty" example:"The seven days before today."`
Line int `json:"line" example:"12"`
}
Function is one function a library defines at its top level.
type Graph ¶
type Graph struct {
// OK is false when the source does not parse or resolve. Findings then
// says why, and the diagram is empty.
OK bool `json:"ok"`
Findings []scriptrun.Finding `json:"findings"`
Nodes []Node `json:"nodes"`
Edges []Edge `json:"edges"`
Groups []Group `json:"groups"`
Params []Param `json:"params"`
// Lines is the source's line count, for the reader's scale.
Lines int `json:"lines" example:"136"`
// Truncated is true when the script expands into more steps than one
// diagram draws; the graph holds the first ones.
Truncated bool `json:"truncated"`
// Structure is the script drawn in the order it runs (#1972), the Flow
// tab's default view.
Structure Structure `json:"structure"`
// ComparedWith is the older version this graph is compared against
// (#1908), zero when it is not a comparison.
ComparedWith int `json:"compared_with,omitempty"`
// Library is present when the script is a library (#1970): the functions
// it defines for another script to load. Derive does not set it: whether
// a script is a library is recorded when it is created, and a source with
// no main() saved before libraries existed is not one, so the caller that
// holds the script attaches it with LibraryOf.
Library *Library `json:"library,omitempty"`
}
Graph is one script version's flow.
type Group ¶
type Group struct {
ID string `json:"id" example:"/load_orders"`
Label string `json:"label" example:"load_orders(day)"`
Caption string `json:"caption,omitempty"`
// Parent is the id of the enclosing box, empty at the top level.
Parent string `json:"parent,omitempty"`
DefLine int `json:"def_line" example:"12"`
CalledFrom []int `json:"called_from"`
}
Group is a function box.
type Library ¶ added in v1.138.1
type Library struct {
// Functions is every function a load can name, in source order.
Functions []Function `json:"functions"`
// Load is the statement that loads every one of them from this version,
// empty when there is none to load.
Load string `json:"load,omitempty" example:"load(\"lib:date-windows@2\", \"last_week\")"`
}
Library is what a library defines for another script to load (#1970). A library makes no platform calls, so its diagram is empty by definition; what a reader of one needs is the functions it offers and how to load them.
type Node ¶
type Node struct {
ID string `json:"id" example:"op:3"`
Role string `json:"role" example:"reads"`
Kind string `json:"kind" example:"query"`
// Title is the action and where it goes; Subtitle the operation, name or
// path; Purpose the purpose sentence the author wrote on the call.
Title string `json:"title" example:"Query warehouse"`
Subtitle string `json:"subtitle,omitempty"`
Purpose string `json:"purpose,omitempty"`
// Detail is the tables, paths or keys the step touches.
Detail []string `json:"detail"`
// Computed is true when what the step reaches is only known at run time;
// the computed part is written as {its source} in the text above.
Computed bool `json:"computed"`
// Group is the id of the function box the step is drawn in, empty at the
// top level.
Group string `json:"group,omitempty"`
// Line and EndLine are the platform call's lines. Site is the line the
// folded wrapper named in Wrapper is called from.
Line int `json:"line" example:"42"`
EndLine int `json:"end_line" example:"44"`
Site int `json:"site,omitempty"`
Wrapper string `json:"wrapper,omitempty"`
// Loops are the for statements the step repeats in, outermost first.
Loops []string `json:"loops"`
// CallSite is the position of every call on the stack that makes this
// step's call, outermost first, as "line:col": what a run records on the
// step's audited calls and outputs (#1907), so a run is drawn on the card
// that made each call.
CallSite []string `json:"call_site,omitempty"`
// Change and Was mark a node of a compared graph (#1908): added, changed
// (with what it said before) or removed (carried over from the older
// version).
Change string `json:"change,omitempty"`
Was *Was `json:"was,omitempty"`
}
Node is one step, or the run.state input.
type Param ¶
type Param struct {
Name string `json:"name" example:"day"`
// Line is where the source first reads it.
Line int `json:"line" example:"3"`
// Reaches lists the steps whose arguments the parameter's value reaches.
Reaches []string `json:"reaches"`
// Decides is true when the value is read by a condition, so it decides
// which steps run.
Decides bool `json:"decides"`
}
Param is one run parameter the source reads, with the steps its value reaches.
type StructBox ¶ added in v1.138.1
type StructBox struct {
ID string `json:"id" example:"b:2"`
Kind string `json:"kind" example:"loop"`
// Label is a loop's header or a function's signature; Caption the
// function's first comment sentence.
Label string `json:"label"`
Caption string `json:"caption,omitempty"`
Parent string `json:"parent,omitempty"`
Line int `json:"line" example:"12"`
// CallSite is where this expansion of a function was called from, the
// prefix every call made inside it carries.
CallSite []string `json:"call_site,omitempty"`
}
StructBox is a loop or a helper function around the nodes it runs.
type StructEdge ¶ added in v1.138.1
type StructEdge struct {
From string `json:"from"`
To string `json:"to"`
Label string `json:"label,omitempty" example:"yes"`
}
StructEdge is "runs next". Label is yes or no on an if's arms.
type StructNode ¶ added in v1.138.1
type StructNode struct {
ID string `json:"id" example:"s:3"`
Kind string `json:"kind" example:"if"`
// Label is the if's condition and the fail()'s message, as the source
// writes them.
Label string `json:"label,omitempty" example:"len(rows) < 1000"`
// Step is the value graph's node for a platform call.
Step string `json:"step,omitempty" example:"op:3"`
// Box is the loop or function box the node is drawn in.
Box string `json:"box,omitempty"`
Line int `json:"line" example:"42"`
// CallSite is a platform call's or a fail()'s position on the stack, as
// a run records it (#1907).
CallSite []string `json:"call_site,omitempty"`
}
StructNode is one node of the structure.
type Structure ¶ added in v1.138.1
type Structure struct {
Nodes []StructNode `json:"nodes"`
Edges []StructEdge `json:"edges"`
Boxes []StructBox `json:"boxes"`
// Functions is every def with its span, so a call site's frames can be
// named by the function each line is in.
Functions []FuncSpan `json:"functions"`
// Truncated is true when the script expands into more nodes than one
// diagram draws.
Truncated bool `json:"truncated"`
}
Structure is the script drawn in the order it runs (#1972): one Start, the statements that matter in sequence, a decision for every if that holds one, a box for every loop and helper function that holds one, and an exit for the normal end, every fail() and every early return from main(). It is the Flow tab's default view; the value graph (Graph.Nodes and Graph.Edges) is the Calls view.
The graph is acyclic by construction: a loop is a box around its body, and run.state is read at the top and saved at the bottom rather than drawn as an edge back. A platform call is a node whose Step names the value graph's card for the same call, so a run's calls, which are attributed to cards by call site, land on the same node in both views.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package flowcompare compares two versions of a script's flow graph (#1908): the newer version's diagram marked with what it reads, writes and produces that the older did not, which is what a reviewer approving a change asks first.
|
Package flowcompare compares two versions of a script's flow graph (#1908): the newer version's diagram marked with what it reads, writes and produces that the older did not, which is what a reviewer approving a change asks first. |
|
Package flowrun draws one run of a script on the flow graph of the version it executed (#1907): which cards the run reached, the audited calls each made and how long they took, what each wrote, and the card the run failed at.
|
Package flowrun draws one run of a script on the flow graph of the version it executed (#1907): which cards the run reached, the audited calls each made and how long they took, what each wrote, and the card the run failed at. |