Documentation
¶
Overview ¶
Package typ provides a restricted but combinable type system.
There are five groups of types that share some behaviour: numeric, character, indexer, keyer and special types. Special types are void, any, the special typ type representing a type literals and type variables, alternatives and references, as well as the exp types dyn, form, func and tag.
The other four groups each have a base type, which are num, char, idxr and keyr. Base types are usually only used as long as no specific type could be resolved.
There is a number of specific types for each base type:
bool, int, real, time and span are numeric types str, raw, uuid, time and span are character types list, rec and obj are indexer types dict, rec and obj are keyer types
The character, numeric types and special base type are represented by their name:
bool, void, time any, num, keyr, dyn
The time and span type represents a time or a time duration/interval/delta that can either be represented as numeric value in milliseconds since epoch and ms delta or in a character format as specified in the cor package. Their default representation is the character format.
The list and dict type can have a type parameters and can be nested.
list, list|int, dict|bool, list|list|list|int, dict|list|dict|list|dict|list|str
The record types rec and obj have type parameters representing fields, that can be accessed by key or index, therefor a record type is both an indexer and keyer type. Records must have at least one parameter and must be enclosed in angle brackets. Optional fields have names ending with a question mark, otherwise a field is considered required.
<rec x:int y:int z?:int>, <list|rec name:str val; extra?;>
Optional types are nullable type-variants. The any, list, dict and exp types are always optional and the void and typ and exp types never are. All the other primitive, record and reference types can be marked as optional by a question mark suffix.
<rec top10:<list|rec? name:str score:int?> err:str?>
The exp types form and func also use the type parameters syntax used as argument and result type signature. The last parameter signifies the result type and is usually unnamed. All other parameters represent the form arguments. Function parameters must have a type and may be named. Form parameters must be name and can omit the type.
Type variables start with an at sign '@123' followed by a type id. They represent an unresolved type during type inference. An variable without var id '@' means a new id must be assigned.
Type references start with an at sign '@name' followed by a symbol and represent the type of what the symbol resolves to. References need to be resolved in a declaration context for this reason.
The @name form can be used as an alias in place of any type definition. Type references in unnamed field declarations are embedded. Embedding a record type has the same effect as copying all of its fields into the new type, while for all other references fields are named by the last simple name part in the reference name.
(let kind: int named: <rec id:uuid name:str?> cat: <rec @named _:@kind? prods:list|@named> )
Self references of the form '~1' are a special references to the current '~0' or the parent '~1' or the grand parent '~2' type and so on for the whole record type ancestry.
Schema types are also a kind of type references, that are treated as a specific type in most cases. Schema types reference a global type definition and as such must be resolved. Other than normal references the identifier is kept alongside the full type data after resolution.
bits is a named int type bit-set that consists of multiple bit constants enum is a named str type that consists of one string constant of an enumeration obj is a named rec type that has additional type and field details
The global identifier allows users to associate extra data and behaviour to these types.
All non-special types and the any type are called literal types. Concrete literal types are all literal types except the base types. All the other special types are not considered literal types. Even though references may resolve to a literal type, they can be considered a literal.
Minimum restrictions apply for compatibility with JavaScript and JSON:
map keys are restricted to string int is limited to 53bit precision real has no NaN or infinities time has millisecond granularity
Types don't usually need to be written as JSON, because both client and server expect a given schema. But when they need to be serialized, it serializes the type in the xelf representations to a json object field 'typ':
{ "kind": {"typ": "int"}, "named":{"typ": "<rec id:uuid name:str?>"}, "cat": {"typ": "<rec @named _:@kind? prods:list|@named>"} }
Index ¶
- Constants
- Variables
- func NeedsInfo(t Type) (ref, params bool)
- type Bind
- type Binds
- type Cmp
- type Const
- type Consts
- func (cs Consts) Bits(mask uint64) Consts
- func (cs Consts) ByKey(key string) (c Const, ok bool)
- func (cs Consts) ByVal(val int64) (c Const, ok bool)
- func (cs Consts) FormatBits(mask int64) string
- func (cs Consts) FormatEnum(val int64) string
- func (cs Consts) Len() int
- func (cs Consts) Less(i, j int) bool
- func (cs Consts) Swap(i, j int)
- type Ctx
- func (c *Ctx) Apply(t Type) Type
- func (c *Ctx) Bind(v Kind, t Type) error
- func (c *Ctx) Bound(t Type, vars Vars) Vars
- func (c *Ctx) Contains(t Type, v Kind) bool
- func (c *Ctx) Free(t Type, vars Vars) Vars
- func (c *Ctx) Inst(t Type) Type
- func (c *Ctx) New() Type
- func (c *Ctx) Realize(t Type) (_ Type, err error)
- func (c Ctx) String() string
- type Info
- func (a *Info) Equal(b *Info) bool
- func (a *Info) HasConsts() bool
- func (a *Info) HasParams() bool
- func (a *Info) HasRef() bool
- func (a *Info) IsZero() bool
- func (a *Info) Key() string
- func (a *Info) ParamByIdx(idx int) (*Param, error)
- func (a *Info) ParamByKey(key string) (*Param, int, error)
- func (a *Info) ParamLen() int
- type Kind
- type Param
- type Path
- type PathSeg
- type Type
- func Alt(alts ...Type) (res Type)
- func Bits(n string) Type
- func Choose(t Type) (_ Type, err error)
- func Common(a, b Type) (s, t Type, err error)
- func Cont(t Type) Type
- func Dict(t Type) Type
- func Enum(n string) Type
- func Form(n string, ps []Param) Type
- func Func(n string, ps []Param) Type
- func Idxr(t Type) Type
- func Keyr(t Type) Type
- func List(t Type) Type
- func NewAlt(alts ...Type) (res Type)
- func Obj(n string) Type
- func Opt(t Type) Type
- func Parse(a *lex.Tree) (Type, error)
- func ParseInfo(args []*lex.Tree, t Type, hist []Type) (Type, error)
- func ParseSym(s string, hist []Type) (res Type, err error)
- func Read(r io.Reader) (Type, error)
- func Rec(fs []Param) Type
- func Ref(n string) Type
- func Sch(n string) Type
- func Select(t Type, path string) (Type, error)
- func SelectIdx(t Type, idx int) (Type, error)
- func SelectKey(t Type, key string) (Type, error)
- func SelectPath(t Type, p Path) (r Type, err error)
- func Unify(c *Ctx, a, b Type) (Type, error)
- func Var(id uint64, alts ...Type) Type
- func (t Type) Deopt() (_ Type, ok bool)
- func (t Type) Elem() Type
- func (t Type) Equal(o Type) bool
- func (t Type) IsOpt() bool
- func (t Type) IsZero() bool
- func (t Type) Last() Type
- func (t Type) MarshalJSON() ([]byte, error)
- func (t Type) Ordered() bool
- func (t Type) Resolved() bool
- func (t Type) String() string
- func (t Type) Typ() Type
- func (t *Type) UnmarshalJSON(raw []byte) error
- func (t Type) WriteBfr(b *bfr.Ctx) error
- type Vars
Constants ¶
const ( // both types are the same CmpSame = LvlEqual | (1 << iota) // infer type from src, dst is a unnamed ref CmpInfer )
const ( // convert src to the any type CmpCompAny = LvlComp | (1 << iota) // convert src from spec to base type CmpCompBase // convert src from base to spec type CmpCompSpec // convert idxer to list CmpCompList // convert keyer to dict CmpCompDict )
const ( // convert from one to another list CmpConvList = LvlConv | (1 << iota) // convert from one to another dict CmpConvDict // convert from rec to another rec CmpConvRec )
const ( // resolve unresolved type references in either src or dst CmpCheckRef = LvlCheck | (1 << iota) // compare src any value type to dst CmpCheckAny // parse base to spec type CmpCheckSpec // compare list element value types to dst arr or rec CmpCheckListAny // compare dict element value types to dst map or rec CmpCheckDictAny // try to convert arr to another arr CmpCheckList // try to convert map to another map CmpCheckDict // try to convert rec to another rec CmpCheckRec )
const ( CmpAbstrPrim = LvlAbstr | (1 << iota) CmpAbstrCont )
const ( SlotSize = 12 SlotMask = 0xfff )
A Kind describes a type in a slot that uses the 12 least significant bits. The rest of the bits are reserved to be used by specific types. Type variables use it to store a unique type id and other types might use it in the future to optimization access the most important type parameter details without chasing pointers.
const ( MaskUber = KindExpr | KindMeta // 0000 0011 0000 MaskBits = 0xf00 // 1111 0000 0000 MaskBase = KindAny | MaskUber // 0000 0011 1111 MaskElem = MaskBase | MaskBits // 1111 0011 1111 MaskRef = MaskElem | KindCtx // 1111 0111 1111 )
const ( KindVoid = 0x00 KindPrim = KindNum | KindChar // 0000 0000 0011 KindCont = KindIdxr | KindKeyr // 0000 0000 1100 KindAny = KindPrim | KindCont // 0000 0000 1111 KindBool = KindNum | KindBit1 // 0x101 KindInt = KindNum | KindBit2 // 0x201 KindReal = KindNum | KindBit3 // 0x401 KindSpan = KindNum | KindBit4 // 0x801 KindStr = KindChar | KindBit1 // 0x102 KindRaw = KindChar | KindBit2 // 0x202 KindUUID = KindChar | KindBit3 // 0x402 KindTime = KindChar | KindBit4 // 0x802 KindList = KindIdxr | KindBit1 // 0x104 KindDict = KindKeyr | KindBit2 // 0x208 KindRec = KindCont | KindBit3 // 0x30c KindBits = KindCtx | KindInt // 0x241 KindEnum = KindCtx | KindStr // 0x142 KindObj = KindCtx | KindRec // 0x34c KindTyp = KindExpr | KindBit1 // 0x110 KindFunc = KindExpr | KindBit2 // 0x210 KindDyn = KindExpr | KindBit3 // 0x410 KindTag = KindExpr | KindBit4 // 0x810 KindForm = KindCtx | KindFunc // 0x250 KindCall = KindCtx | KindDyn // 0x450 KindSym = KindCtx | KindTag // 0x850 KindVar = KindMeta | KindBit1 // 0x120 KindRef = KindMeta | KindBit2 // 0x220 KindSch = KindMeta | KindBit3 // 0x420 KindAlt = KindMeta | KindBit4 // 0x820 )
Variables ¶
var ( Void = Type{Kind: KindVoid} Any = Type{Kind: KindAny} Typ = Type{Kind: KindTyp} Num = Type{Kind: KindNum} Bool = Type{Kind: KindBool} Int = Type{Kind: KindInt} Real = Type{Kind: KindReal} Char = Type{Kind: KindChar} Str = Type{Kind: KindStr} Raw = Type{Kind: KindRaw} UUID = Type{Kind: KindUUID} Time = Type{Kind: KindTime} Span = Type{Kind: KindSpan} Expr = Type{Kind: KindExpr} Sym = Type{Kind: KindSym} Dyn = Type{Kind: KindDyn} Call = Type{Kind: KindCall} Tag = Type{Kind: KindTag} )
Functions ¶
Types ¶
type Binds ¶
type Binds []Bind
Binds is a sorted set of type variable bindings.
func (Binds) Get ¶
Get returns the type bound to v and a boolean indicating whether a binding was found.
type Cmp ¶
type Cmp uint64
Cmp is a bit-set for detailed type comparisons results
const ( LvlAbstr Cmp = 1 << (iota + 24) LvlCheck LvlConv LvlComp LvlEqual LvlMask Cmp = 0x7 << 24 CmpNone Cmp = 0 )
Exclusive level bits define the meaning of the other bits. Levels are check, conv, wrap and equal. These level bits are the most significant in the set and allow simple compatibility tests.
res < LvlConv
type Consts ¶
type Consts []Const
func (Consts) Bits ¶
Bits returns the matching constants s contained in mask. The given constants are checked in reverse and thus should match combined, more specific constants first.
func (Consts) ByKey ¶
ByKey finds and returns a constant with key in s. If a const was found, ok is true.
func (Consts) ByVal ¶
ByVal finds and returns a constant with value val in s. If a const was found, ok is true.
func (Consts) FormatBits ¶
FormatBits returns a string representing mask. It returns the matched constants' lowercase names separated by a pip '|'.
func (Consts) FormatEnum ¶
FormatEnum returns the lowercase name of the constant matching val or an empty string.
type Ctx ¶
type Ctx struct {
// contains filtered or unexported fields
}
Ctx is used to check and infer type variables.
func (*Ctx) Bound ¶
Bound returns vars with all type variables in t, that are bound to this context, appended.
type Info ¶
type Info struct { Ref string `json:"ref,omitempty"` Params []Param `json:"params,omitempty"` Consts Consts `json:"consts,omitempty"` }
Info represents the reference name and type parameters or constants.
func (*Info) ParamByIdx ¶
ParamByIdx returns a pointer to the field at idx or an error.
func (*Info) ParamByKey ¶
ParamByKey returns a pointer to the field and its idex at key or an error.
type Kind ¶
type Kind uint64
Kind is a bit-set describing a type. It represents all type information except reference names and type parameters. It is a handy implementation detail, but not part of the xelf specification.
const ( KindNum Kind = 1 << iota // 0x001 KindChar // 0x002 KindIdxr // 0x004 KindKeyr // 0x008 KindExpr // 0x010 KindMeta // 0x020 KindCtx // 0x040 KindOpt // 0x080 KindBit1 // 0x100 KindBit2 // 0x200 KindBit3 // 0x400 KindBit4 // 0x800 )
Each bit in a slot has a certain meaning. The first six bits specify a base type, next two bits flag the type a context or optional variant.
func (Kind) MarshalText ¶
func (*Kind) UnmarshalText ¶
type Path ¶
type Path []PathSeg
Path consists of non-empty segments separated by dots '.' or slashes '/'. Segments starting with a digit or minus sign are idx segments that try to select into an idxer literal, otherwise the segment represents a key used to select into a keyer literal. Segments starting with a slash signify a selection from a idxer literal.
type PathSeg ¶
PathSeg is one segment of a path. It consists of a dot or slash, followed by a key or index.
type Type ¶
Type represents the full type details. It consists of a kind and additional information.
func Alt ¶
Alt returns a new type alternative for a list of types. Other alternatives are flattened. If the first type is already an alternative, the following types are added.
func Choose ¶
Choose returns type t with all type alternatives reduced to its most specific representation.
func SelectPath ¶
SelectPath returns the selected type from t or an error.
func (Type) Deopt ¶
Deopt returns the non-optional type of t if t is a optional type and not any, otherwise t is returned as is.
func (Type) Last ¶
Last returns the last element type if t is a list or dict type otherwise t is returned as is.