typecheck

package
v0.5.0-1a Latest Latest
Warning

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

Go to latest
Published: May 31, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package typecheck holds unobin's semantic type model and the static type checker that runs after parsing. Type values carry no source position so the same value compares cleanly whether it came from a written declaration or was inferred from a literal.

The parser's lang.TypeExpr is the syntactic form of a written type declaration; convert it to a Type with FromLang before reasoning about it here.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Assignable

func Assignable(dst, src Type) bool

Assignable reports whether a value of type src can flow into a slot declared with type dst. Either side being Unknown returns true so partial schema information fails open rather than producing spurious errors.

Rules in plain terms:

  • any accepts anything; null is assignable only into a slot that includes null (an optional() wrapper or the null atom).
  • integer widens into number but not the other way.
  • optional(T) accepts T or null; the source side is unwrapped before comparing, so an optional value flows into a non- optional slot when the underlying types match (the runtime enforces non-nullness at decode time).
  • list/set/map/tuple compare element-wise.
  • object types compare structurally: every required dst field must have a compatible src field; extra src fields are allowed (open against the source) and missing-optional dst fields are tolerated.

func FieldKindLabel

func FieldKindLabel(kind string) string

FieldKindLabel returns the lowercase singular noun for a node kind ("resource", "data source", "action") used in error messages. Lives here so check_refs.go and the inferrer agree.

Types

type EachBinding

type EachBinding struct {
	Key   Type
	Value Type
}

EachBinding is the type pair bound by an enclosing @for-each. Key is the index type (integer for lists, string for maps, element type for sets). Value is the iterated element type.

type Kind

type Kind int

Kind discriminates the Type variants. The zero value Unknown stands in for a type the walker could not determine; the checker skips compatibility comparisons involving Unknown so source the inferrer cannot reason about fails open rather than producing noise.

const (
	Unknown Kind = iota
	Any
	String
	Integer
	Number
	Boolean
	Null
	List
	Set
	Map
	Object
	Tuple
	Optional
)

type LookupLocalFn

type LookupLocalFn func(name string) (Type, bool)

LookupLocalFn returns the inferred Type of a `locals:` entry by name. The boolean is false when no such local is declared; the inferrer then returns Unknown without an error (the reference checker reports an unknown local name).

type LookupNodeFn

type LookupNodeFn func(kind, alias, typ, name string) (Type, bool)

LookupNodeFn returns the output Type of a node by kind, alias, type, and name. The boolean is false when the node is not known; the inferrer then returns Unknown without an error (the existing reference checker has the responsibility to report unresolved node addresses).

type ObjectField

type ObjectField struct {
	Name     string
	Type     Type
	Optional bool
}

ObjectField is one named field of an Object type. Optional is true when the field may be absent (e.g. it came from a *T Go field or an optional() declaration).

func InputsFromBlock

func InputsFromBlock(decl *lang.ObjectLit) []ObjectField

InputsFromBlock walks an `inputs:` block object literal and returns each input's name to its semantic type. Inputs declared with `optional()` carry the inner type and are marked optional on the resulting ObjectField; the caller decides what to do with that (typically: treat var.X as the inner type when optional, since missing inputs default to null and unobin treats null as the missing case).

type Scope

type Scope struct {
	Inputs      []ObjectField
	Each        *EachBinding
	LookupNode  LookupNodeFn
	LookupLocal LookupLocalFn
	// Bindings holds comprehension-bound names. They resolve as bare
	// values and as dot-path roots ahead of var/resource/data/action,
	// so an inner binding shadows an outer one.
	Bindings map[string]Type
}

Scope carries the lexical information the inferrer needs to type an expression: local input declarations, an optional @each binding, and a callback that returns the output Type for a node address (resource/data/action.<alias>.<type>.<name>). LookupNode may be nil when the caller has no node table; the walker returns Unknown for any node reference in that case.

type Type

type Type struct {
	Kind   Kind
	Elem   *Type
	Elems  []Type
	Fields []ObjectField
}

Type is a structural type description. The Kind field discrim- inates which of the value-bearing fields is populated:

  • List/Set/Map/Optional read Elem.
  • Tuple reads Elems.
  • Object reads Fields.

Pass Type around by value; the recursive children live on the pointer fields so a deeply nested type still copies in constant time at the top level.

func Check

func Check(e lang.Expr, target Type, scope *Scope, errs *lang.ErrorList) Type

Check infers the type of e and verifies it is assignable to the declared target. Returns the inferred type and appends a mismatch diagnostic to errs when the types are incompatible. Container and object targets are already enforced bidirectionally inside Infer (mismatches are reported at the element or field level); Check's own Assignable comparison runs only for atomic targets so the same mistake is not reported twice.

func FromLang

func FromLang(t lang.TypeExpr) Type

FromLang turns a parsed lang.TypeExpr into a semantic Type. Returns TUnknown when the input is nil or names a constructor the converter does not understand; the checker treats Unknown as a silent skip.

func Infer

func Infer(e lang.Expr, target Type, scope *Scope, errs *lang.ErrorList) Type

Infer walks e and returns its inferred type. The target steers how ambiguous literals decide between list/tuple and how object literals match against a declared type; pass TUnknown when no target is in effect. Errors found during inference are appended to errs; the return value is best-effort and may be Unknown when nothing useful can be determined.

func TAny

func TAny() Type

func TBoolean

func TBoolean() Type

func TInteger

func TInteger() Type

func TList

func TList(elem Type) Type

func TMap

func TMap(elem Type) Type

func TNull

func TNull() Type

func TNumber

func TNumber() Type

func TObject

func TObject(fields []ObjectField) Type

func TOptional

func TOptional(elem Type) Type

func TSet

func TSet(elem Type) Type

func TString

func TString() Type

func TTuple

func TTuple(elems []Type) Type

func TUnknown

func TUnknown() Type

func (Type) Equal

func (t Type) Equal(other Type) bool

Equal reports whether two types describe the same thing. It is recursive and order-sensitive for tuples; object fields compare by name regardless of declaration order so two object types that declare the same fields in different orders match.

func (Type) Field

func (t Type) Field(name string) (ObjectField, bool)

Field returns the named field of an Object type, ok=false when the field is absent or the type is not an Object.

func (Type) IsKnown

func (t Type) IsKnown() bool

IsKnown returns false when the Type is Unknown or wraps Unknown through an Optional. The checker uses this to bail out of comparisons it cannot reason about.

func (Type) String

func (t Type) String() string

String renders the type in the unobin type vocabulary the operator would have written: `list(string)`, `optional(integer)`, `object({ a: string b: integer })`. Object field order follows the order the type was constructed in so error messages stay stable with respect to the source.

func (Type) Unwrap

func (t Type) Unwrap() Type

Unwrap returns the inner type when t is Optional, else t itself. The checker peels optionality before comparing the underlying types.

Jump to

Keyboard shortcuts

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