Assignability & inference¶
Assignability is the load-bearing operation of a type system.
pcore.IsAssignable(a, b) answers is b a subtype of a — is every
instance of b also an instance of a?
a, _ := pcore.Parse("Integer[0,10]")
b, _ := pcore.Parse("Integer[2,5]")
pcore.IsAssignable(a, b) // true
The lattice¶
Anyis the top: everything is assignable to it.Scalar⊇ScalarData⊇Numeric⊇Integer/Float, andString⊇Enum/Pattern.DataisVariant[ScalarData, Undef, Array[Data], Hash[String, Data]], checked structurally and recursively.Collectionaccepts anyArray,Hash,TupleorStructwithin its size range.- Numeric and string ranges use containment:
Integer[0,10]acceptsInteger[2,5];String[1,3]acceptsEnum['a','bb'](each value's length is in range). Variantdistributes:bis assignable when every member ofb's union is assignable, anda(aVariant) acceptsbwhen some branch does.Optional[T]isVariant[Undef, T];NotUndef[T]accepts a non-undef type assignable toT.Structis closed: assignability checks every required key is present and compatible, with no extra keys.
The assignability arms are covered exhaustively by the test suite.
Inference¶
Infer(v) returns the most specific type of a value; ranges collapse to the
observed value:
pcore.Infer(int64(5)) // Integer[5, 5]
pcore.Infer("hello") // String[5, 5]
pcore.Infer([]pcore.Value{int64(1), "x"}) // Array[ScalarData, 2, 2]
Generalize widens a type by dropping range/size constraints; CommonType
returns the narrowest single supertype of two types: