Documentation
¶
Overview ¶
Package tsvsheet is the engine for the tsvsheet single-file spreadsheet: a .tsvt is a single TAB-separated grid whose cells are literal values or =formulas that address other cells in A1 notation (B2, D2:D5), computed in place.
The package parses a grid (Parse, ReadTSV), computes it with an Excel- and Google-Sheets-faithful expression evaluator that carries error values (#REF!, #DIV/0!, #CIRC!, …) through a dependency-ordered, memoized pass (Compute, ComputeWith), and inspects the result (Check diagnostics, Explain traces) before rendering it back to TSV (WriteTSV). Formula compilation reuses the grammar repo's ANTLR-generated expression parser through the internal/tsvt seam; no ANTLR type escapes into the public surface.
The engine is filesystem- and network-free by construction: cross-sheet embedding (SHEET/INPUT/OUTPUT) and imports (IMPORT*) resolve only through the Loader and Fetcher a caller injects, and every allocation is bounded by an injected Limits ceiling. Errors returned to callers are the errs.Const sentinels re-exported from errors.go, matchable with errors.Is.
This package is a thin facade: every type, function, and constant it exposes re-exports the implementation in internal/engine unchanged, so the public surface is documented here while the engine stays an internal package.
Index ¶
- Constants
- func WriteTSV(w io.Writer, g Grid) error
- type Address
- type AddressText
- type CellInfo
- type ComputeOptions
- type Diagnostic
- type ErrorValue
- type FetchResult
- type Fetcher
- type Grid
- type ImportURL
- type Limits
- type Loader
- type MediaType
- type Path
- type Sheet
- type Span
- type Trace
- type TraceInput
- type Value
Examples ¶
Constants ¶
const ( ErrSyntax = constants.ErrSyntax ErrInvalidValue = constants.ErrInvalidValue ErrNotFound = constants.ErrNotFound ErrReadInput = constants.ErrReadInput ErrWriteFile = constants.ErrWriteFile )
Engine error sentinels returned to callers, matchable with errors.Is.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Address ¶
Address is a cell coordinate in spreadsheet notation (`F4`): column letters plus a 1-based row. It carries 0-based indices internally.
func ParseAddress ¶
func ParseAddress(s AddressText) (Address, error)
ParseAddress parses spreadsheet notation (`A1`, `F4`, `AA10`) into an Address. The column is one or more ASCII uppercase letters, the row a positive integer; anything else is constants.ErrInvalidValue.
type AddressText ¶
type AddressText = engine.AddressText
AddressText is spreadsheet-address source text (`A1`, `F4`) accepted by ParseAddress. It is exported so callers in other packages can convert their string input at the call site.
type CellInfo ¶
CellInfo describes one non-empty cell: its address, source text, and whether it is a formula — the projection the parse command emits.
type ComputeOptions ¶
type ComputeOptions = engine.ComputeOptions
ComputeOptions configures a compute pass. Loader and Base enable embedded sub-sheets; a zero Loader disables SHEET (it resolves to #REF!).
type Diagnostic ¶
type Diagnostic = engine.Diagnostic
Diagnostic is an advisory finding about a formula cell: currently an unknown function call (which computes to #NAME?).
func Check ¶
func Check(s Sheet) []Diagnostic
Check reports the static diagnostics of a parsed sheet: each unknown function call. Syntax errors are already rejected by Parse, and every reference the narrowed grammar admits is a valid A1 form, so Check never reports those.
Example ¶
Check reports static diagnostics — unknown functions, provable arity errors, non-A1 references — without computing.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
func main() {
sheet, _ := tsvsheet.Parse([]byte("=BOGUS(1)\n"))
for _, d := range tsvsheet.Check(sheet) {
fmt.Printf("%s: %s\n", d.Cell, d.Message)
}
}
Output: A1: unknown function: BOGUS
type ErrorValue ¶
type ErrorValue = engine.ErrorValue
ErrorValue is a spreadsheet error value — a cell value, not a Go error. It propagates through expressions per ADR 0003 (rules 3, 8, 12, 14).
const ( ErrRef ErrorValue = engine.ErrRef ErrValue ErrorValue = engine.ErrValue ErrName ErrorValue = engine.ErrName ErrDiv ErrorValue = engine.ErrDiv ErrCirc ErrorValue = engine.ErrCirc ErrNA ErrorValue = engine.ErrNA ErrNum ErrorValue = engine.ErrNum ErrNull ErrorValue = engine.ErrNull ErrSpill ErrorValue = engine.ErrSpill ErrImport ErrorValue = engine.ErrImport )
The error values. #REF! (out-of-grid), #VALUE! (type), #NAME? (unknown function), #DIV/0! (division by zero), #CIRC! (a formula whose evaluation depends on itself), #N/A (lookup miss / NA()), #NUM! (numeric domain), #NULL! (empty range intersection), #SPILL! (blocked dynamic-array spill), #IMPORT! (a content-typed import failed — disabled, denied, or a bad handshake).
type FetchResult ¶
type FetchResult = engine.FetchResult
FetchResult is a Fetcher's response: the raw body and the media type the server declared, which must match the requested Accept for the handshake to succeed (ADR 0006 §2).
type Fetcher ¶
Fetcher retrieves the content-typed import at url, sending accept as the requested media type. The engine holds only this interface; the concrete net/http fetcher, allowlist, and caching are injected by a frontend. A nil Fetcher disables imports (every IMPORT* is #IMPORT!).
Example ¶
The engine is network-free: IMPORT* cells resolve only through a Fetcher injected via ComputeOptions. With none, they are #IMPORT!; with one, they resolve to the fetched value.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
// stubFetcher is a trivial Fetcher for the example below: it answers every
// request with the value 42, echoing the requested media type so the handshake
// succeeds.
type stubFetcher struct{}
func (stubFetcher) Fetch(_ tsvsheet.ImportURL, accept tsvsheet.MediaType) (tsvsheet.FetchResult, error) {
return tsvsheet.FetchResult{ContentType: accept, Body: []byte("42")}, nil
}
func main() {
sheet, _ := tsvsheet.Parse([]byte(`=IMPORTCELL("https://example/v")` + "\n"))
fmt.Println(sheet.Compute()[0][0])
fmt.Println(sheet.ComputeWith(tsvsheet.ComputeOptions{Fetcher: stubFetcher{}})[0][0])
}
Output: #IMPORT! 42
type Grid ¶
Grid is a rectangular value grid indexed [row][col], 0-based. Cells are raw strings: a literal's own text on input, or a formula cell's computed value after ComputeAt.
func ReadTSV ¶
ReadTSV reads a tab-separated value grid. Rows are newline-separated; a trailing newline does not add an empty row. Full-line comments are skipped and do not occupy a grid row: a leading `#!` on the first line (a shebang, so a .tsvt can be `chmod +x` and run via `#!/usr/bin/env tsvsheet`) and any line beginning with `# ` (hash-space). An error-value cell like `#N/A` (hash then a non-space) is data, not a comment. A read failure surfaces as ErrReadInput.
type ImportURL ¶
ImportURL is the location an IMPORT* function fetches — the (already evaluated) string value of its single argument.
type Limits ¶
Limits bounds the sizes an untrusted sheet may drive an allocation to.
func BrowserLimits ¶
func BrowserLimits() Limits
BrowserLimits are the tighter ceilings the WASM build applies, sized for a browser tab rather than a workstation.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits are generous for real spreadsheets while still bounding OOM.
type Loader ¶
Loader resolves the sheet referenced by ref, relative to the embedding sheet's own path base, returning the parsed sub-sheet and its resolved path (used for cycle detection and as the base for the sub-sheet's own SHEET calls). The frontend injects it, keeping the engine filesystem-free; a resolution or containment failure is reported as an error and surfaces as #REF!.
type MediaType ¶
MediaType is a content-typed import's RFC 6838 media type — the Accept header an IMPORT* function requests, which the response Content-Type must match.
type Path ¶
Path identifies a sheet to a Loader: the reference written in a SHEET(...) call, and (as the loader's result) the sheet's own resolved path.
type Sheet ¶
Sheet is a parsed spreadsheet grid of literal and formula cells.
func Parse ¶
Parse reads a .tsvt grid: each TAB-separated field is a literal, or — when it begins with `=` — a formula compiled from the expression that follows. A malformed formula is a syntax error naming its cell.
Example ¶
Parse compiles a .tsvt grid; Compute evaluates every =formula in dependency order and returns the value grid ([][]string), literals passing through.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
func main() {
sheet, err := tsvsheet.Parse([]byte("2\t3\n=A1*B1\t=A1+B1\n"))
if err != nil {
fmt.Println(err)
return
}
grid := sheet.Compute()
fmt.Println(grid[1][0], grid[1][1])
}
Output: 6 5
Example (ErrorValues) ¶
A cell that fails to evaluate carries a spreadsheet error value, which propagates through the formulas that read it — it is data, not a Go error.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
func main() {
sheet, _ := tsvsheet.Parse([]byte("=1/0\t=A1+1\n"))
grid := sheet.Compute()
fmt.Println(grid[0][0], grid[0][1])
}
Output: #DIV/0! #DIV/0!
Example (SyntaxError) ¶
A malformed formula is reported as ErrSyntax, matchable with errors.Is.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
func main() {
_, err := tsvsheet.Parse([]byte("=1 +\n"))
fmt.Println(err != nil)
}
Output: true
type Span ¶
Span is a rectangular reference target resolved to 0-based addresses: a single cell (From == To) or a range (From is the top-left, To the bottom-right as written). It is the projection a frontend highlights.
type Trace ¶
Trace explains how one cell was produced: its value, the formula (empty for a literal), and the resolved value of each cell the formula reads.
func Explain ¶
Explain computes the sheet and describes the cell at at: its value, and — when the cell is a formula — that formula and each reference it reads.
Example ¶
Explain traces how a cell was produced: its value, formula, and the inputs the formula read.
package main
import (
"fmt"
tsvsheet "github.com/uplang/go-tsvsheet"
)
func main() {
sheet, _ := tsvsheet.Parse([]byte("2\t3\n=A1+B1\t\n"))
trace, _ := tsvsheet.Explain(sheet, tsvsheet.Address{Row: 1, Col: 0})
fmt.Printf("%s = %s (from %s, %d inputs)\n", trace.Cell, trace.Value, trace.Formula, len(trace.Inputs))
}
Output: A2 = 5 (from A1 + B1, 2 inputs)
type TraceInput ¶
type TraceInput = engine.TraceInput
TraceInput is one reference a formula reads, with its resolved value.
Directories
¶
| Path | Synopsis |
|---|---|
|
Command browser exposes the tsvsheet engine to the browser as a set of STATELESS functions: the caller holds the .tsvt source, and each call parses it, applies one immutable engine operation, and returns the result as a JSON string.
|
Command browser exposes the tsvsheet engine to the browser as a set of STATELESS functions: the caller holds the .tsvt source, and each call parses it, applies one immutable engine operation, and returns the result as a JSON string. |
|
internal
|
|
|
constants
Package constants declares the tsvsheet engine's sentinel error values.
|
Package constants declares the tsvsheet engine's sentinel error values. |
|
engine
TSV serialization for the sheet engine: reading a .tsvt grid into a Grid of raw cell strings and writing a computed Grid back out.
|
TSV serialization for the sheet engine: reading a .tsvt grid into a Grid of raw cell strings and writing a computed Grid back out. |
|
tsvt
Package tsvt is the covered seam over the ANTLR-generated formula parser: it turns a cell's formula source (the text after its leading `=`) into an immutable typed AST — an Expr over A1 references and literals — or a sentinel syntax error, and hides every ANTLR type from the rest of the program.
|
Package tsvt is the covered seam over the ANTLR-generated formula parser: it turns a cell's formula source (the text after its leading `=`) into an immutable typed AST — an Expr over A1 references and literals — or a sentinel syntax error, and hides every ANTLR type from the rest of the program. |