analyze

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package analyze turns notebook source into a graph.Graph.

The Analyzer interface is the seam that lets the source-analysis backend be swapped without touching the graph algorithms or the engine. Today the only implementation is TypesAnalyzer, which loads the package with go/packages and reads the type checker's results. When re-analysis on every keystroke starts to hurt (the largest engineering risk in the design), a gopls-backed implementation can replace it behind the same interface.

Everything go/types-specific lives in this package. The graph package it produces is plain data.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func LoadForPurity

func LoadForPurity(dir string) (*packages.Package, error)

LoadForPurity loads the notebook package with full dependency source (LoadAllSyntax implies NeedDeps) so its call graph can be built. This is the heavy load; keep it off the interactive path.

func NotebookWASMable

func NotebookWASMable(g *graph.Graph) (ok bool, blockers []graph.CellID)

NotebookWASMable reports whether the whole notebook can run in the browser: every runnable cell must be WASM-able. It returns the offending cells (not WASM-able) so the caller can name them. A notebook with a fold or other deferred feature is judged on its runnable cells only.

func RefineGraphPurity added in v0.5.0

func RefineGraphPurity(dir string, g *graph.Graph) error

RefineGraphPurity is the cold-path convenience that build/run/check use to light up the cache: it does the heavy NeedDeps load (LoadForPurity) and runs RefinePurity over g in place. It is deliberately NOT on the interactive Session path — that path drops NeedDeps to hit its ~sub-ms budget and leaves every cell at the safe impure default (a cache miss, never a wrong answer). The one-shot commands already pay ~1s for codegen+compile, so they can afford the heavy load, and doing it here is what makes "cacheability is derived" true of a built binary rather than only of a unit test.

Best-effort like RefinePurity: a load failure is returned so a caller can decide, but a cell whose SSA can't be built simply keeps its impure default.

func RefinePurity

func RefinePurity(pkg *packages.Package, g *graph.Graph)

RefinePurity computes the Pure flag for every cell in g from the package call graph, mutating the cells in place. It requires a package loaded with NeedDeps (full dependency source) — use LoadForPurity.

It uses a CHA call graph rather than VTA: purity needs only a sound over-approximation of "does this reach time.Now / rand / os / net", and CHA provides that far more cheaply. CHA over-approximates interface dispatch, so it may occasionally mark a pure cell impure — which costs a cache hit and nothing else, the safe direction.

RefinePurity is best-effort: if SSA cannot be built or a cell's function cannot be found, that cell keeps its (safe, impure) default and no error is returned.

func WASMability

func WASMability(pkg *packages.Package, g *graph.Graph)

WASMability marks every cell in g with whether it can run under GOOS=js GOARCH=wasm, from the call graph — not by hand, and not from the purity pass. A cell is WASM-able iff it transitively reaches none of the non-portable primitives. Results are written to graph.Cell.WASMable.

Best-effort like RefinePurity: a cell whose SSA function can't be found keeps the safe default (false — not provably portable). Requires a package loaded with full dependency source (use LoadForPurity).

Types

type Analysis

type Analysis struct {
	Graph       *graph.Graph
	Package     PackageInfo
	Diagnostics []graph.Diagnostic
}

Analysis is the full result of analyzing a notebook package for codegen: the dependency graph, the package identity, and any diagnostics.

func LoadPackage

func LoadPackage(dir string) (Analysis, error)

LoadPackage is the codegen entry point: it derives the graph exactly as TypesAnalyzer.Analyze does, and additionally returns the package identity codegen needs. The graph and diagnostics are identical to Analyze; this just surfaces the package metadata that the Analyzer interface intentionally omits (the interface is the gopls seam and stays graph-only).

type Analyzer

type Analyzer interface {
	Analyze(dir string) (*graph.Graph, []graph.Diagnostic, error)
}

Analyzer derives a notebook's dependency graph from source.

Analyze returns the graph together with any diagnostics. A non-nil error is reserved for failures to load or analyze at all (bad directory, package that does not compile at the syntax level); ordinary notebook problems — a missing producer, a cycle, an unnamed result — are returned as diagnostics on a graph that is otherwise as complete as possible, so the caller can report several at once rather than one per run.

type PackageInfo

type PackageInfo struct {
	// ImportPath is the notebook package's import path, e.g.
	// "github.com/scttfrdmn/go-notebook/examples/capacity".
	ImportPath string
	// Name is the package clause name, e.g. "capacity".
	Name string
	// Dir is the absolute directory containing the package's source.
	Dir string
	// GoFiles are the absolute paths of the package's non-generated Go files.
	GoFiles []string
}

PackageInfo is the identity of the notebook package that codegen needs but the graph IR deliberately does not carry: where the package lives and what it is called. The graph is about dataflow; this is about where to write the generated registry so it can see the notebook's unexported cells.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is the interactive re-analysis path: it loads the notebook package once, caches its dependency types, and thereafter re-derives the graph by re-typechecking only the notebook package's source against that cache.

This is the number the whole milestone exists to produce (KC2: re-analysis after a one-cell edit). A full packages.Load reruns `go list` and reloads the world (~hundreds of ms); a re-typecheck against a cached importer is sub-millisecond, because the dependency graph has not changed on an edit — only the notebook's own file contents have.

A Session is not safe for concurrent use; drive it from a single edit loop.

func NewSession

func NewSession(dir string) (*Session, error)

NewSession primes a Session for the notebook package in dir. It performs one graph-mode load (no NeedDeps) to obtain the dependency types and the file list, then holds them for fast re-analysis. The prime cost is the ~cold-load number; every subsequent Reanalyze is the interactive number.

func (*Session) Reanalyze

func (s *Session) Reanalyze() (*graph.Graph, []graph.Diagnostic, error)

Reanalyze re-parses and re-typechecks the notebook package from disk and derives the graph. Dependency types are served from the primed cache, so no packages.Load and no `go list` runs. This is the KC2 path.

type TypesAnalyzer

type TypesAnalyzer struct{}

TypesAnalyzer derives a notebook graph using go/packages and go/types. It is the only Analyzer implementation in this milestone.

The zero value is ready to use. Analyze performs a cold, one-shot derivation. For the interactive re-analysis path (a one-cell edit), use a Session, which primes the importer once and then re-typechecks only the notebook package — orders of magnitude faster than reloading.

func (TypesAnalyzer) Analyze

func (TypesAnalyzer) Analyze(dir string) (*graph.Graph, []graph.Diagnostic, error)

Analyze loads the package in dir (graph mode, no NeedDeps), finds the notebook file, and derives the graph. Purity is NOT computed here: cells default to impure, which is the always-safe default (a conservative impure verdict only costs a cache miss). Refine purity separately with RefinePurity when the cache needs it; never on an interactive edit.

Load failures return an error; notebook-level problems are returned as diagnostics on the fullest graph the analyzer could build.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL