io

package
v1.5.12 Latest Latest
Warning

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

Go to latest
Published: Mar 3, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package io provides binary serialization and deserialization for Lua types.

The package supports full round-trip encoding of all type system constructs including primitives, composites (records, functions, unions), generics, and flow-sensitive constraints. Serialized types are stored in manifests for cross-module type resolution.

Primary APIs:

  • Encode/Decode: Serialize individual types to/from bytes
  • Manifest: Cross-module type information container
  • FunctionSummary: Interprocedural analysis data

The binary format uses little-endian encoding with length-prefixed strings and type-tagged values. Version numbers track format changes for backward compatibility checking.

Usage:

data, err := io.Encode(typ.String)
decoded, err := io.Decode(data)

manifest := io.NewManifest("mymodule")
manifest.SetExport(exportType)
data, err := manifest.Encode()

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidManifest indicates the file header does not contain the magic bytes.
	ErrInvalidManifest = errors.New("invalid manifest header")
	// ErrVersionMismatch indicates the manifest was created with an incompatible version.
	ErrVersionMismatch = errors.New("manifest version mismatch")
)

Manifest decoding errors.

View Source
var (
	ErrInvalidType   = errors.New("invalid type encoding")
	ErrUnknownType   = errors.New("unknown type kind")
	ErrCorruptedData = errors.New("corrupted type data")
)

Functions

func ApplyFunctionSummary

func ApplyFunctionSummary(fn *typ.Function, summary *FunctionSummary) *typ.Function

ApplyFunctionSummary enriches a function type with behavioral data from a summary.

This function merges type-level function information with runtime behavioral specifications. It is used for cross-module constraint and effect propagation.

Merge strategy:

  • Effects: Summary effects take precedence if non-empty
  • Spec: Built from summary constraints if present
  • Refinement: Built from summary ensures if present
  • Falls back to existing fn values when summary doesn't provide data

The result is a new function type; the input fn is not modified.

func Decode

func Decode(data []byte) (typ.Type, error)

func Encode

func Encode(t typ.Type) ([]byte, error)

func EncodeManifest

func EncodeManifest(m *Manifest) ([]byte, error)

EncodeManifest encodes a manifest to bytes.

func LookupEnrichedExport added in v1.5.6

func LookupEnrichedExport(manifests ManifestQuerier, path string) typ.Type

LookupEnrichedExport resolves the manifest by path and returns its enriched export type.

Types

type FunctionSummary

type FunctionSummary struct {
	Params  []typ.Type
	Returns []typ.Type
	Effects effect.Row

	// Contract constraints
	Requires     constraint.Condition
	Ensures      constraint.Condition
	ExprRequires []constraint.ExprCompare
	ExprEnsures  []constraint.ExprCompare

	// Escape analysis
	ParamEscapes []bool
	ReturnsParam int // -1 if returns fresh value
}

FunctionSummary captures function behavior for cross-module flow analysis.

Summaries enable sophisticated type checking across module boundaries without re-analyzing source code. They encode:

Type information:

  • Params: Parameter types for arity and type checking
  • Returns: Return types for result type derivation
  • Effects: Effect row for effect propagation

Contract information (Hoare-style pre/postconditions):

  • Requires: Preconditions that must hold at call sites
  • Ensures: Postconditions guaranteed after the call
  • ExprRequires/ExprEnsures: Arithmetic constraints on lengths/indices

Escape analysis information:

  • ParamEscapes: Which parameters escape (are stored, not just borrowed)
  • ReturnsParam: If >= 0, indicates which param flows to return (passthrough)

The type checker uses summaries to:

  • Check argument types against parameter types
  • Derive return types from effects and argument types
  • Propagate narrowing constraints through function calls
  • Track value ownership for optimization

func NewSummary

func NewSummary(params, returns []typ.Type) *FunctionSummary

NewSummary creates a function summary.

func (*FunctionSummary) Clone

func (s *FunctionSummary) Clone() *FunctionSummary

Clone returns a deep copy of the FunctionSummary.

type Manifest

type Manifest struct {
	// Path is the module path used for require() resolution.
	Path string
	// Version is a monotonic counter for cache invalidation.
	Version uint64

	// Export is the type returned by require(). Usually a record of functions.
	Export typ.Type
	// Types maps type names to their definitions for cross-module type references.
	Types map[string]typ.Type

	// Summaries maps function names to their behavioral specifications.
	// Enables interprocedural analysis without source code.
	Summaries map[string]*FunctionSummary

	// Globals records types assigned to _G for global namespace pollution tracking.
	Globals map[string]typ.Type
	// contains filtered or unexported fields
}

Manifest captures type information for cross-module resolution.

A manifest is the persistent representation of a module's type signature, enabling type checking across module boundaries without re-analyzing source. Manifests are serialized to binary and stored alongside compiled Lua chunks.

The manifest lifecycle:

  1. Analysis phase generates a manifest from source analysis
  2. Manifest is serialized and stored (cache or file)
  3. Dependent modules load the manifest via db.Connect()
  4. Type checker resolves cross-module references through ManifestQuerier

Thread safety: Manifest instances are immutable after creation. The db.DB handles concurrent access during Connect/Disconnect operations.

func DecodeManifest

func DecodeManifest(data []byte) (*Manifest, error)

DecodeManifest deserializes binary to manifest.

func LookupManifest added in v1.5.6

func LookupManifest(manifests ManifestQuerier, path string) *Manifest

LookupManifest resolves a manifest by path.

Resolution policy is canonical across checker layers:

  1. Direct lookup via Manifest(path)
  2. Fallback lookup via Imports()path

func NewManifest

func NewManifest(path string) *Manifest

NewManifest creates an empty manifest.

func (*Manifest) AddGlobal

func (m *Manifest) AddGlobal(name string, t typ.Type)

AddGlobal records a _G assignment.

func (*Manifest) AllGlobals

func (m *Manifest) AllGlobals() map[string]typ.Type

AllGlobals returns a copy of all global definitions.

func (*Manifest) AllSummaries

func (m *Manifest) AllSummaries() map[string]*FunctionSummary

AllSummaries returns a deep copy of all function summaries.

func (*Manifest) AllTypes

func (m *Manifest) AllTypes() map[string]typ.Type

AllTypes returns a copy of all type definitions.

func (*Manifest) DefineSummary

func (m *Manifest) DefineSummary(name string, s *FunctionSummary)

DefineSummary adds a function summary.

func (*Manifest) DefineType

func (m *Manifest) DefineType(name string, t typ.Type)

DefineType adds a type definition.

func (*Manifest) Encode

func (m *Manifest) Encode() ([]byte, error)

Encode serializes manifest to binary.

func (*Manifest) EnrichedExport

func (m *Manifest) EnrichedExport() typ.Type

EnrichedExport returns the Export type with function summaries applied.

This method combines the structural Export type with behavioral information from Summaries. For each function field in the export record, if a matching summary exists, the function type is enriched with:

  • Effects from the summary's effect row
  • Spec from the summary's contract constraints
  • Refinement from the summary's ensures condition

This enables cross-module constraint propagation and effect tracking without storing redundant information in both Export and Summaries.

func (*Manifest) LookupSummary

func (m *Manifest) LookupSummary(name string) (*FunctionSummary, bool)

LookupSummary finds a function summary.

func (*Manifest) LookupType

func (m *Manifest) LookupType(name string) (typ.Type, bool)

LookupType finds a type by name.

func (*Manifest) LookupValue added in v1.5.6

func (m *Manifest) LookupValue(name string) (typ.Type, bool)

LookupValue finds an exported value field by name from the enriched export type.

func (*Manifest) SetExport

func (m *Manifest) SetExport(t typ.Type)

SetExport sets the module's export type.

type ManifestQuerier

type ManifestQuerier interface {
	// Manifest returns the manifest for the given module path, or nil if not loaded.
	Manifest(path string) *Manifest
	// Imports returns all loaded manifests keyed by module path.
	Imports() map[string]*Manifest
}

ManifestQuerier provides read-only access to module manifests.

This interface decouples manifest consumers from the storage implementation. It is implemented by db.DB for the analysis context.

Architecture:

  • types/io defines Manifest structure and serialization
  • types/db provides storage and caching via the DB type
  • Analysis code accesses manifests through ManifestQuerier

This layering prevents import cycles and allows different storage backends.

Jump to

Keyboard shortcuts

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