type.go 8.16 KB
Newer Older
Eric Myhre's avatar
Eric Myhre committed
1
package schema
Eric Myhre's avatar
Eric Myhre committed
2

3
import (
tavit ohanian's avatar
tavit ohanian committed
4
	ld "gitlab.dms3.io/ld/go-ld-prime"
5 6
)

Eric Myhre's avatar
Eric Myhre committed
7
type TypeName string // = ast.TypeName
8

9 10
func (tn TypeName) String() string { return string(tn) }

11 12 13 14 15 16 17 18 19 20 21 22 23 24
// typesystem.Type is an union interface; each of the `Type*` concrete types
// in this package are one of its members.
//
// Specifically,
//
// 	TypeBool
// 	TypeString
// 	TypeBytes
// 	TypeInt
// 	TypeFloat
// 	TypeMap
// 	TypeList
// 	TypeLink
// 	TypeUnion
Eric Myhre's avatar
Eric Myhre committed
25
// 	TypeStruct
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
// 	TypeEnum
//
// are all of the kinds of Type.
//
// This is a closed union; you can switch upon the above members without
// including a default case.  The membership is closed by the unexported
// '_Type' method; you may use the BurntSushi/go-sumtype tool to check
// your switches for completeness.
//
// Many interesting properties of each Type are only defined for that specific
// type, so it's typical to use a type switch to handle each type of Type.
// (Your humble author is truly sorry for the word-mash that results from
// attempting to describe the types that describe the typesystem.Type.)
//
// For example, to inspect the kind of fields in a struct: you might
// cast a `Type` interface into `TypeStruct`, and then the `Fields()` on
// that `TypeStruct` can be inspected.  (`Fields()` isn't defined for any
// other kind of Type.)
type Type interface {
	// Unexported marker method to force the union closed.
46 47
	// Also used to set the internal pointer back to the universe its part of.
	_Type(*TypeSystem)
48

49
	// Returns a pointer to the TypeSystem this Type is a member of.
Eric Myhre's avatar
Eric Myhre committed
50
	TypeSystem() *TypeSystem
51

52 53 54 55 56
	// Returns the string name of the Type.  This name is unique within the
	// universe this type is a member of, *unless* this type is Anonymous,
	// in which case a string describing the type will still be returned, but
	// that string will not be required to be unique.
	Name() TypeName
Eric Myhre's avatar
Eric Myhre committed
57

58
	// Returns the TypeKind of this Type.
59
	//
60 61 62
	// The returned value is a 1:1 association with which of the concrete
	// "schema.Type*" structs this interface can be cast to.
	//
tavit ohanian's avatar
tavit ohanian committed
63
	// Note that a schema.TypeKind is a different enum than ld.Kind;
64
	// and furthermore, there's no strict relationship between them.
65
	// schema.TypedNode values can be described by *two* distinct Kinds:
66 67 68
	// one which describes how the Node itself will act,
	// and another which describes how the Node presents for serialization.
	// For some combinations of Type and representation strategy, one or both
69
	// of the Kinds can be determined statically; but not always:
70
	// it can sometimes be necessary to inspect the value quite concretely
71
	// (e.g., `schema.TypedNode{}.Representation().Kind()`) in order to find
72 73 74
	// out exactly how a node will be serialized!  This is because some types
	// can vary in representation kind based on their value (specifically,
	// kinded-representation unions have this property).
75
	TypeKind() TypeKind
76 77

	// RepresentationBehavior returns a description of how the representation
78
	// of this type will behave in terms of the LD Data Model.
79 80 81 82 83 84 85 86 87 88
	// This property varies based on the representation strategy of a type.
	//
	// In one case, the representation behavior cannot be known statically,
	// and varies based on the data: kinded unions have this trait.
	//
	// This property is used by kinded unions, which require that their members
	// all have distinct representation behavior.
	// (It follows that a kinded union cannot have another kinded union as a member.)
	//
	// You may also be interested in a related property that might have been called "TypeBehavior".
89 90
	// However, this method doesn't exist, because it's a deterministic property of `TypeKind()`!
	// You can use `TypeKind.ActsLike()` to get type-level behavioral information.
tavit ohanian's avatar
tavit ohanian committed
91
	RepresentationBehavior() ld.Kind
Eric Myhre's avatar
Eric Myhre committed
92 93
}

94
var (
95 96 97 98 99 100 101 102 103 104 105
	_ Type = &TypeBool{}
	_ Type = &TypeString{}
	_ Type = &TypeBytes{}
	_ Type = &TypeInt{}
	_ Type = &TypeFloat{}
	_ Type = &TypeMap{}
	_ Type = &TypeList{}
	_ Type = &TypeLink{}
	_ Type = &TypeUnion{}
	_ Type = &TypeStruct{}
	_ Type = &TypeEnum{}
106 107
)

108
type typeBase struct {
109
	name     TypeName
Eric Myhre's avatar
Eric Myhre committed
110
	universe *TypeSystem
111 112
}

Eric Myhre's avatar
Eric Myhre committed
113
type TypeBool struct {
114
	typeBase
Eric Myhre's avatar
Eric Myhre committed
115
}
116

Eric Myhre's avatar
Eric Myhre committed
117
type TypeString struct {
118
	typeBase
Eric Myhre's avatar
Eric Myhre committed
119
}
120

Eric Myhre's avatar
Eric Myhre committed
121
type TypeBytes struct {
122
	typeBase
Eric Myhre's avatar
Eric Myhre committed
123
}
124

Eric Myhre's avatar
Eric Myhre committed
125
type TypeInt struct {
126
	typeBase
Eric Myhre's avatar
Eric Myhre committed
127
}
128

Eric Myhre's avatar
Eric Myhre committed
129
type TypeFloat struct {
130
	typeBase
Eric Myhre's avatar
Eric Myhre committed
131
}
132

Eric Myhre's avatar
Eric Myhre committed
133
type TypeMap struct {
134
	typeBase
135
	anonymous     bool
136
	keyType       TypeName // must be Kind==string (e.g. Type==String|Enum).
137
	valueType     TypeName
138
	valueNullable bool
Eric Myhre's avatar
Eric Myhre committed
139
}
140

Eric Myhre's avatar
Eric Myhre committed
141
type TypeList struct {
142
	typeBase
143
	anonymous     bool
144
	valueType     TypeName
145
	valueNullable bool
Eric Myhre's avatar
Eric Myhre committed
146
}
147

Eric Myhre's avatar
Eric Myhre committed
148
type TypeLink struct {
149
	typeBase
150
	referencedType    TypeName
151
	hasReferencedType bool
Eric Myhre's avatar
Eric Myhre committed
152 153 154 155
	// ...?
}

type TypeUnion struct {
156
	typeBase
157 158 159 160 161
	// Members are listed in the order they appear in the schema.
	// To find the discriminant info, you must look inside the representation; they all contain a 'table' of some kind in which the member types are the values.
	// Note that multiple appearances of the same type as distinct members of the union is not possible.
	//  While we could do this... A: that's... odd, and nearly never called for; B: not possible with kinded mode; C: imagine the golang-native type switch!  it's impossible.
	//  We rely on this clarity in many ways: most visibly, the type-level Node implementation for a union always uses the type names as if they were map keys!  This behavior is consistent for all union representations.
162
	members        []TypeName
163
	representation UnionRepresentation
Eric Myhre's avatar
Eric Myhre committed
164
}
165

166
type UnionRepresentation interface{ _UnionRepresentation() }
Eric Myhre's avatar
Eric Myhre committed
167

168 169 170 171 172
func (UnionRepresentation_Keyed) _UnionRepresentation()        {}
func (UnionRepresentation_Kinded) _UnionRepresentation()       {}
func (UnionRepresentation_Envelope) _UnionRepresentation()     {}
func (UnionRepresentation_Inline) _UnionRepresentation()       {}
func (UnionRepresentation_Stringprefix) _UnionRepresentation() {}
173

174 175 176 177 178
// A bunch of these tables in union representation might be easier to use if flipped;
//  we almost always index into them by type (since that's what we have an ordered list of);
//  and they're unique in both directions, so it's equally valid either way.
//  The order they're currently written in matches the serial form in the schema AST.

179
type UnionRepresentation_Keyed struct {
180
	table map[string]TypeName // key is user-defined freetext
181 182
}
type UnionRepresentation_Kinded struct {
tavit ohanian's avatar
tavit ohanian committed
183
	table map[ld.Kind]TypeName
184 185 186 187
}
type UnionRepresentation_Envelope struct {
	discriminantKey string
	contentKey      string
188
	table           map[string]TypeName // key is user-defined freetext
189 190 191
}
type UnionRepresentation_Inline struct {
	discriminantKey string
192
	table           map[string]TypeName // key is user-defined freetext
193
}
194 195 196 197
type UnionRepresentation_Stringprefix struct {
	delim string
	table map[string]TypeName // key is user-defined freetext
}
Eric Myhre's avatar
Eric Myhre committed
198

Eric Myhre's avatar
Eric Myhre committed
199
type TypeStruct struct {
200
	typeBase
201 202 203 204
	// n.b. `Fields` is an (order-preserving!) map in the schema-schema;
	//  but it's a list here, with the keys denormalized into the value,
	//   because that's typically how we use it.
	fields         []StructField
205
	fieldsMap      map[string]StructField // same content, indexed for lookup.
206
	representation StructRepresentation
Eric Myhre's avatar
Eric Myhre committed
207
}
Eric Myhre's avatar
Eric Myhre committed
208
type StructField struct {
209
	parent   *TypeStruct
210
	name     string
211
	typ      TypeName
212 213
	optional bool
	nullable bool
Eric Myhre's avatar
Eric Myhre committed
214 215
}

216 217 218 219 220
type StructRepresentation interface{ _StructRepresentation() }

func (StructRepresentation_Map) _StructRepresentation()         {}
func (StructRepresentation_Tuple) _StructRepresentation()       {}
func (StructRepresentation_StringPairs) _StructRepresentation() {}
221
func (StructRepresentation_Stringjoin) _StructRepresentation()  {}
222 223 224

type StructRepresentation_Map struct {
	renames   map[string]string
225
	implicits map[string]ImplicitValue
226 227 228
}
type StructRepresentation_Tuple struct{}
type StructRepresentation_StringPairs struct{ sep1, sep2 string }
229
type StructRepresentation_Stringjoin struct{ sep string }
230

Eric Myhre's avatar
Eric Myhre committed
231
type TypeEnum struct {
232
	typeBase
233
	members []string
Eric Myhre's avatar
Eric Myhre committed
234
}
235 236 237 238 239 240 241 242 243 244 245

// ImplicitValue is an sum type holding values that are implicits.
// It's not an 'Any' value because it can't be recursive
// (or to be slightly more specific, it can be one of the recursive kinds,
// but if so, only its empty value is valid here).
type ImplicitValue interface{ _ImplicitValue() }

type ImplicitValue_EmptyList struct{}
type ImplicitValue_EmptyMap struct{}
type ImplicitValue_String struct{ x string }
type ImplicitValue_Int struct{ x int }