Help us shape the future of Go! Take the 2026 Go Developer Survey

analysis

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: BSD-3-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package analysis finds what each code cell of a notebook defines and uses, and orders the cells by those dependencies.

A cell is Go with statements allowed at the top level, as in a REPL:

import "math"
func sq(x float64) float64 { return x * x }
y := sq(math.Pi)
y

Its top-level func, type and import declarations are declarations of the notebook; everything else is a statement of the cell, run in order. The names a cell defines at its top level (by :=, var, const, func or type) are the notebook's variables: every cell can read them, and exactly one cell may define each — the rule that makes the execution order a function of the code, not of the order cells were run in. Names starting with an underscore, and err, stay local to their cell (see Private). A cell may not assign to a variable another cell defines, for the same reason: the change would be invisible to the dependency graph. (Mutation through a method or a slice element cannot be seen statically and is not refused, as in marimo.)

The analysis is syntactic: it needs no type information and works on code that does not compile yet. A cell's final expression statement is its display value.

Index

Constants

View Source
const (
	Go   = "go"
	Ruby = "ruby"
)

Languages of code cells.

View Source
const Julia = "julia"

Julia is the language of ```julia cells.

View Source
const JuliaNotRun = "Julia cells are parsed and checked, but not run yet: execution arrives with go-embedded-julia's runtime (milestone M3)"

JuliaNotRun is the failure of every Julia cell, in the kernel and in the playground: go-embedded-julia parses Julia exactly as julia 1.12 does, but has no interpreter yet, and go-notebook runs no external julia.

Variables

This section is empty.

Functions

func GoName added in v0.3.0

func GoName(name string) bool

GoName reports whether a Ruby local can be a Go variable of the same name: an identifier that is neither a Go keyword nor predeclared.

func JuliaBlocked added in v0.6.0

func JuliaBlocked(julia int) string

JuliaBlocked is the failure of a cell that reads, directly or through other cells, what Julia cell julia defines.

func Private

func Private(name string) bool

Private reports whether a name defined at a cell's top level stays local to the cell instead of becoming a notebook variable: a name starting with an underscore (marimo's convention), and err, which nearly every cell declares and none means to share.

func Shared added in v0.3.0

func Shared(owner, user *Cell, name string) bool

Shared reports whether the cell user sees the name that cell owner defines. Within a language every name is shared. Across languages only variables are:

  • a Go cell sees a Ruby cell's top-level local variables, but not its methods, constants or classes, nor a local named like a Go keyword or a predeclared identifier (len, int, type, …), which stays Ruby's;
  • a Ruby cell sees a Go cell's variables, but not its funcs or types;
  • a Julia cell's variables, not its functions, macros, constants or types, are seen by the other languages as a Ruby cell's are, and a Julia cell sees their variables. Julia cells do not run yet, so a cell that reads one of their variables is blocked (see gen), but the edge is there.

Types

type Cell

type Cell struct {
	Index  int    // position among the notebook's code cells
	Source string // the cell's source
	Lang   string // Go, or Ruby (see AnalyzeRubyCell)

	Chunks []Chunk

	// Defines lists the notebook variables the cell defines: those of its
	// declarations, then those of its statements, each in order of
	// appearance. Funcs and Types are the subsets declared with func and
	// type. Imports maps a package name to its import path.
	Defines []string
	Funcs   []string
	Types   []string
	Imports map[string]string

	// Consts are the constants, classes and modules a Ruby cell defines.
	Consts []string

	// RubyDisplay reports that a Ruby cell ends in an expression, whose value
	// it shows. (A Go cell's is Display.)
	RubyDisplay bool

	// Uses lists the free identifiers the cell reads, sorted: notebook
	// variables, package names other cells import, builtins, and names
	// that are not defined anywhere (the compiler reports those).
	Uses []string

	// OwnPackages lists, sorted, the names of the packages the cell imports
	// itself and refers to.
	OwnPackages []string

	// Display is the cell's final expression statement, if any, and its
	// byte range in Source.
	Display                  ast.Expr
	DisplayStart, DisplayEnd int

	// Assigns lists the free identifiers the cell assigns to (=, op=, ++,
	// --), with the offset of each assignment.
	Assigns []Use

	// Errors are syntax errors, with offsets in Source.
	Errors []Error
}

Cell is the analysis of one code cell.

func AnalyzeCell

func AnalyzeCell(index int, src string) *Cell

AnalyzeCell analyses the source of code cell number index.

func AnalyzeJuliaCell added in v0.6.0

func AnalyzeJuliaCell(index int, src string) *Cell

AnalyzeJuliaCell analyses the source of Julia code cell number index, with go-embedded-julia's parser (a port of JuliaSyntax, the parser of Julia 1.12, which gives the Expr trees julia itself gives).

The names follow Julia's scope rules ("Scope of Variables" in the Julia manual, 1.12) as they apply to the top level of a notebook, which Julia treats as an interactive context:

  • the top level, and if, begin and other blocks in it, are the global scope: an assignment there (x = 1, a, b = …, x::Int = 1, global x = 1) defines a global, a notebook variable;
  • function, macro, struct, let, do, -> and comprehension or generator bodies are hard local scopes: an assignment there makes a local, and the names read there that no enclosing scope binds are globals the cell uses;
  • for, while and try bodies at the top level are soft scopes: an assignment there to a name that is a global already (defined earlier in the cell, or by another cell) assigns that global, as in the REPL and IJulia; otherwise it makes a local of the loop.

Functions (function f, f(x) = …) and macros (@m) are in Funcs; constants, structs, abstract and primitive types, modules and the names using and import bind are in Consts; all are in Defines. Names starting with an underscore stay private to the cell, as in the other languages.

func AnalyzeRubyCell added in v0.3.0

func AnalyzeRubyCell(index int, src string) *Cell

AnalyzeRubyCell analyses the source of Ruby code cell number index, with go-ruby-parser, the front end of the Ruby that runs it.

A Ruby cell's top level is a program evaluated in one binding shared by every Ruby cell, so the names it defines are of two kinds:

  • the local variables it assigns at its top level (x = 1, a, b = …): notebook variables, which Go cells can read too;
  • the methods it defines at its top level with def (Funcs), and its constants, classes and modules (Consts): visible to later Ruby cells only, but defined by one cell, as any name is.

Both are in Defines. The cell uses every name it reads that it has not assigned before: a local of the top level or of a block, a method called without a receiver, a constant. Names starting with an underscore stay private to the cell. The display is the value of the final statement when that statement is an expression rather than an assignment or a definition.

type Chunk

type Chunk struct {
	Decl       bool
	Start, End int // byte offsets in the cell's source
}

Chunk is a run of a cell's text that is either one top-level declaration (func, type or import) or a sequence of statements.

type Error

type Error struct {
	Cell int
	Pos  int
	Msg  string
}

Error is a problem found in a cell, at a byte offset of its source.

func (Error) Error

func (e Error) Error() string

type Graph

type Graph struct {
	Cells []*Cell

	// Owner maps each notebook variable to the cell that defines it.
	Owner map[string]int

	// Deps[i] lists the cells cell i reads from, sorted; Dependents is the
	// reverse relation.
	Deps, Dependents [][]int

	// Order is an execution order: every cell after the cells it reads, and
	// otherwise in document order. It holds every cell when Errors is empty.
	Order []int

	// Errors lists syntax errors, names defined twice, assignments to
	// another cell's variable, and dependency cycles.
	Errors []Error
}

Graph is the dependency graph of a notebook's code cells.

func Analyze

func Analyze(sources []string) *Graph

Analyze analyses the sources of a notebook's Go code cells, in document order, and builds their dependency graph.

func AnalyzeSources added in v0.3.0

func AnalyzeSources(sources []Source) *Graph

AnalyzeSources is Analyze for cells in Go and in Ruby. The two languages share their variables (see Shared), so a Go cell can read what a Ruby cell defines and the reverse, and the graph orders them together.

func (*Graph) Downstream

func (g *Graph) Downstream(changed ...int) []int

Downstream returns the cells that must re-run when the given cells change: those cells and everything that depends on them, in execution order.

func (*Graph) Upstream

func (g *Graph) Upstream(cells ...int) []int

Upstream returns the cells the given cells need, transitively, themselves included, in execution order.

type Source added in v0.3.0

type Source struct {
	Lang   string // Go or Ruby; "" is Go
	Source string
}

Source is a code cell's language and text.

type Use

type Use struct {
	Name string
	Pos  int
}

Use is a name and the offset in a cell's source where it appears.

Jump to

Keyboard shortcuts

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