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 ¶
- func Assignable(dst, src Type) bool
- func FieldKindLabel(kind string) string
- type EachBinding
- type Kind
- type LookupLocalFn
- type LookupNodeFn
- type ObjectField
- type Scope
- type Type
- func Check(e lang.Expr, target Type, scope *Scope, errs *lang.ErrorList) Type
- func FromLang(t lang.TypeExpr) Type
- func Infer(e lang.Expr, target Type, scope *Scope, errs *lang.ErrorList) Type
- func TAny() Type
- func TBoolean() Type
- func TInteger() Type
- func TList(elem Type) Type
- func TMap(elem Type) Type
- func TNull() Type
- func TNumber() Type
- func TObject(fields []ObjectField) Type
- func TOptional(elem Type) Type
- func TSet(elem Type) Type
- func TString() Type
- func TTuple(elems []Type) Type
- func TUnknown() Type
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Assignable ¶
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 ¶
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 ¶
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.
type LookupLocalFn ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 TObject ¶
func TObject(fields []ObjectField) Type
func (Type) Equal ¶
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 ¶
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 ¶
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.