typ

package
v0.0.0-...-7e8a755 Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2020 License: BSD-2-Clause Imports: 9 Imported by: 8

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

View Source
const (
	// both types are the same
	CmpSame = LvlEqual | (1 << iota)
	// infer type from src, dst is a unnamed ref
	CmpInfer
)
View Source
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
)
View Source
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
)
View Source
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
)
View Source
const (
	CmpAbstrPrim = LvlAbstr | (1 << iota)
	CmpAbstrCont
)
View Source
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.

View Source
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
)
View Source
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

View Source
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}
)
View Source
var (
	ErrInvalid   = cor.StrError("invalid type")
	ErrArgCount  = cor.StrError("wrong type argument count")
	ErrRefName   = cor.StrError("expect ref name")
	ErrParamType = cor.StrError("expect param type")
)

Functions

func NeedsInfo

func NeedsInfo(t Type) (ref, params bool)

NeedsInfo returns whether type t is missing reference or params information.

Types

type Bind

type Bind struct {
	Var Kind
	Type
}

Bind represents a type variable binding to another type

func (Bind) String

func (b Bind) String() string

type Binds

type Binds []Bind

Binds is a sorted set of type variable bindings.

func (Binds) Copy

func (bs Binds) Copy() Binds

Copy returns a copy of bs.

func (Binds) Del

func (bs Binds) Del(v Kind) Binds

Del removes a binding with v from bs and returns the resulting set.

func (Binds) Get

func (bs Binds) Get(v Kind) (Type, bool)

Get returns the type bound to v and a boolean indicating whether a binding was found.

func (Binds) Len

func (bs Binds) Len() int

func (Binds) Less

func (bs Binds) Less(i, j int) bool

func (Binds) Set

func (bs Binds) Set(v Kind, t Type) Binds

Set inserts a binding with v and t to bs and returns the resulting set.

func (Binds) Swap

func (bs Binds) Swap(i, j int)

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
const (
	// wrap src as some opt
	BitWrap Cmp = 1 << (iota + 20)
	// unwrap src opt
	BitUnwrap
)

func Compare

func Compare(src, dst Type) Cmp

Compare returns compatibility details for a source and destination type. When the result is not none or equal, it informs what to do with a value of the source type to arrive at the destination type. The bits, enum and rec are treated as their corresponding literal type.

func (Cmp) Mirror

func (c Cmp) Mirror() (m Cmp)

Mirror returns the approximate mirror result of a comparison with switched arguments.

type Const

type Const struct {
	Name string `json:"name"`
	Val  int64  `json:"val"`
}

Const represents named integer constant for bits or enums

func (Const) Cased

func (c Const) Cased() string

func (Const) Key

func (c Const) Key() string

type Consts

type Consts []Const

func Constants

func Constants(m map[string]int64) Consts

func (Consts) Bits

func (cs Consts) Bits(mask uint64) Consts

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

func (cs Consts) ByKey(key string) (c Const, ok bool)

ByKey finds and returns a constant with key in s. If a const was found, ok is true.

func (Consts) ByVal

func (cs Consts) ByVal(val int64) (c Const, ok bool)

ByVal finds and returns a constant with value val in s. If a const was found, ok is true.

func (Consts) FormatBits

func (cs Consts) FormatBits(mask int64) string

FormatBits returns a string representing mask. It returns the matched constants' lowercase names separated by a pip '|'.

func (Consts) FormatEnum

func (cs Consts) FormatEnum(val int64) string

FormatEnum returns the lowercase name of the constant matching val or an empty string.

func (Consts) Len

func (cs Consts) Len() int

func (Consts) Less

func (cs Consts) Less(i, j int) bool

func (Consts) Swap

func (cs Consts) Swap(i, j int)

type Ctx

type Ctx struct {
	// contains filtered or unexported fields
}

Ctx is used to check and infer type variables.

func (*Ctx) Apply

func (c *Ctx) Apply(t Type) Type

Apply returns t with variables replaced from context.

func (*Ctx) Bind

func (c *Ctx) Bind(v Kind, t Type) error

Bind binds type variable v to type t or returns an error.

func (*Ctx) Bound

func (c *Ctx) Bound(t Type, vars Vars) Vars

Bound returns vars with all type variables in t, that are bound to this context, appended.

func (*Ctx) Contains

func (c *Ctx) Contains(t Type, v Kind) bool

Contains returns whether t contains the type variable v.

func (*Ctx) Free

func (c *Ctx) Free(t Type, vars Vars) Vars

Free returns vars with all unbound type variables in t appended.

func (*Ctx) Inst

func (c *Ctx) Inst(t Type) Type

Inst instantiates type t for this context, replacing all type vars.

func (*Ctx) New

func (c *Ctx) New() Type

New returns a new type variable for this context.

func (*Ctx) Realize

func (c *Ctx) Realize(t Type) (_ Type, err error)

Realize returns the finalized type of t or an error. The finalized type is independent of this context.

func (Ctx) String

func (c Ctx) String() string

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) Equal

func (a *Info) Equal(b *Info) bool

func (*Info) HasConsts

func (a *Info) HasConsts() bool

func (*Info) HasParams

func (a *Info) HasParams() bool

func (*Info) HasRef

func (a *Info) HasRef() bool

func (*Info) IsZero

func (a *Info) IsZero() bool

func (*Info) Key

func (a *Info) Key() string

Key returns the lowercase ref key.

func (*Info) ParamByIdx

func (a *Info) ParamByIdx(idx int) (*Param, error)

ParamByIdx returns a pointer to the field at idx or an error.

func (*Info) ParamByKey

func (a *Info) ParamByKey(key string) (*Param, int, error)

ParamByKey returns a pointer to the field and its idex at key or an error.

func (*Info) ParamLen

func (a *Info) ParamLen() int

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 ParseKind

func ParseKind(str string) (Kind, error)

func VarKind

func VarKind(id uint64) Kind

func (Kind) Bits

func (Kind) Bits() map[string]int64

func (Kind) MarshalText

func (k Kind) MarshalText() ([]byte, error)

func (Kind) String

func (k Kind) String() string

func (*Kind) UnmarshalText

func (k *Kind) UnmarshalText(txt []byte) error

func (Kind) WriteBfr

func (k Kind) WriteBfr(b *bfr.Ctx) (err error)

type Param

type Param struct {
	Name string `json:"name,omitempty"`
	Type `json:"typ,omitempty"`
}

Param represents an type parameter with a name and type.

func (Param) Equal

func (p Param) Equal(o Param) bool

func (Param) Key

func (p Param) Key() string

Key returns the lowercase param key.

func (Param) Opt

func (p Param) Opt() bool

Opt returns true if the param is optional, indicated by its name ending in a question mark.

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.

func ReadPath

func ReadPath(path string) (res Path, err error)

ReadPath reads and returns the dot separated segments for the path or an error.

func (Path) String

func (p Path) String() string

type PathSeg

type PathSeg struct {
	Key string
	Idx int
	Sel bool
}

PathSeg is one segment of a path. It consists of a dot or slash, followed by a key or index.

func (PathSeg) String

func (s PathSeg) String() string

type Type

type Type struct {
	Kind Kind
	*Info
}

Type represents the full type details. It consists of a kind and additional information.

func Alt

func Alt(alts ...Type) (res Type)

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 Bits

func Bits(n string) Type

func Choose

func Choose(t Type) (_ Type, err error)

Choose returns type t with all type alternatives reduced to its most specific representation.

func Common

func Common(a, b Type) (s, t Type, err error)

func Cont

func Cont(t Type) Type

func Dict

func Dict(t Type) Type

func Enum

func Enum(n string) Type

func Form

func Form(n string, ps []Param) Type

func Func

func Func(n string, ps []Param) Type

func Idxr

func Idxr(t Type) Type

func Keyr

func Keyr(t Type) Type

func List

func List(t Type) Type

func NewAlt

func NewAlt(alts ...Type) (res Type)

func Obj

func Obj(n string) Type

func Opt

func Opt(t Type) Type

func Parse

func Parse(a *lex.Tree) (Type, error)

Parse parses the element as type and returns it or an error.

func ParseInfo

func ParseInfo(args []*lex.Tree, t Type, hist []Type) (Type, error)

func ParseSym

func ParseSym(s string, hist []Type) (res Type, err error)

ParseSym returns the type represented by the symbol s or an error.

func Read

func Read(r io.Reader) (Type, error)

Read scans and parses from r and returns a type or an error.

func Rec

func Rec(fs []Param) Type

func Ref

func Ref(n string) Type

func Sch

func Sch(n string) Type

func Select

func Select(t Type, path string) (Type, error)

Select reads path and returns the selected type from t or an error.

func SelectIdx

func SelectIdx(t Type, idx int) (Type, error)

func SelectKey

func SelectKey(t Type, key string) (Type, error)

func SelectPath

func SelectPath(t Type, p Path) (r Type, err error)

SelectPath returns the selected type from t or an error.

func Unify

func Unify(c *Ctx, a, b Type) (Type, error)

Unify returns a unified type for a and b or an error.

func Var

func Var(id uint64, alts ...Type) Type

func (Type) Deopt

func (t Type) Deopt() (_ Type, ok bool)

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) Elem

func (t Type) Elem() Type

Elem returns a generalized element type for container types and void otherwise.

func (Type) Equal

func (t Type) Equal(o Type) bool

func (Type) IsOpt

func (t Type) IsOpt() bool

IsOpt returns whether t is an optional type and not any.

func (Type) IsZero

func (t Type) IsZero() bool

func (Type) Last

func (t Type) Last() Type

Last returns the last element type if t is a list or dict type otherwise t is returned as is.

func (Type) MarshalJSON

func (t Type) MarshalJSON() ([]byte, error)

func (Type) Ordered

func (t Type) Ordered() bool

Ordered returns whether type t supports ordering.

func (Type) Resolved

func (t Type) Resolved() bool

Resolved returns whether t is fully resolved

func (Type) String

func (t Type) String() string

func (Type) Typ

func (t Type) Typ() Type

func (*Type) UnmarshalJSON

func (t *Type) UnmarshalJSON(raw []byte) error

func (Type) WriteBfr

func (t Type) WriteBfr(b *bfr.Ctx) error

type Vars

type Vars []Kind

Vars is a sorted set of type variable kinds.

func (Vars) Add

func (vs Vars) Add(v Kind) Vars

Add inserts v into vs and returns the resulting set.

func (Vars) Copy

func (vs Vars) Copy() Vars

Copy returns a copy of vs

func (Vars) Del

func (vs Vars) Del(v Kind) Vars

Del removes v from vs and returns the resulting set.

func (Vars) Has

func (vs Vars) Has(v Kind) bool

Has returns whether vs contains type variable v.

func (Vars) Len

func (vs Vars) Len() int

func (Vars) Less

func (vs Vars) Less(i, j int) bool

func (Vars) Swap

func (vs Vars) Swap(i, j int)

Jump to

Keyboard shortcuts

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