
1 // 2 // Copyright (c) 2006, Brian Frank and Andy Frank 3 // Licensed under the Academic Free License version 3.0 4 // 5 // History: 6 // 4 Jan 06 Brian Frank Creation 7 // 8 9 ** 10 ** Type defines the contract of an Obj by the slots its supports. 11 ** Types model the inheritance relationships and provide a mapping 12 ** for all the slots both inherited and declared. You can create 13 ** new types at runtime via the `Type.makeDynamic` constructor. 14 ** 15 class Type 16 { 17 18 ////////////////////////////////////////////////////////////////////////// 19 // Management 20 ////////////////////////////////////////////////////////////////////////// 21 22 ** 23 ** Find a Type by it's qualified name "pod::Type". If the type 24 ** doesn't exist and checked is false then return null, otherwise 25 ** throw UnknownTypeErr. 26 ** 27 static Type find(Str qname, Bool checked := true) 28 29 ** 30 ** Find all the types annotated with the specified facet name/value 31 ** pair. The facet name must be declared as an indexed facet 32 ** by an installed pod, otherwise Err is thrown. Return an empty 33 ** list of no matches found. 34 ** 35 ** If 'facetVal' is a 'Type', then you may pass 'true' for 'options' 36 ** to check 'facetVals' inheritance hierarchy. 37 ** 38 ** See [Facet Indexing]`docLang::TypeDatabase#facetIndexing` for details. 39 ** 40 static Type[] findByFacet(Str facetName, Obj facetVal, Obj options := null) 41 42 ////////////////////////////////////////////////////////////////////////// 43 // Constructor 44 ////////////////////////////////////////////////////////////////////////// 45 46 ** 47 ** Make a dynamic type which implements the specified list of existing 48 ** types. Only one 'class' type may be specified and it must be the 49 ** first item in the list. All other types must be mixins. None of 50 ** the 'supers' may be dynamic, abstract, final, or const. 51 ** 52 ** Refer to [Dynamic Types]`docLang::DynamicTypes` for more details. 53 ** 54 ** NOTE: creating dynamics using mixins is not supported yet. 55 ** 56 new makeDynamic(Type[] supers, Str:Obj facets := null) 57 58 ////////////////////////////////////////////////////////////////////////// 59 // Naming 60 ////////////////////////////////////////////////////////////////////////// 61 62 ** 63 ** Parent pod which defines this type. For parameterized types derived 64 ** from List, Map, or Func, this method always returns the sys pod. 65 ** Return null if dynamic type. 66 ** 67 ** Examples: 68 ** Str.type.pod -> sys 69 ** acme::Foo.type.pod -> acme 70 ** acme::Foo[].type.pod -> sys 71 ** 72 Pod pod() 73 74 ** 75 ** Simple name of the type such as "Str". For parameterized types derived 76 ** from List, Map, or Func, this method always returns "List", "Map", 77 ** or "Func" respectively. Return "dynamic" if dynamic type. 78 ** 79 ** Examples: 80 ** Str.type.name -> "Str" 81 ** acme::Foo.type.name -> "Foo" 82 ** acme::Foo[].type.name -> "List" 83 ** 84 Str name() 85 86 ** 87 ** Qualified name formatted as "pod::name". For parameterized 88 ** types derived from List, Map, or Func, this method always returns 89 ** "sys::List", "sys::Map", or "sys::Func" respectively. Return 90 ** "dynamic" if dynamic type. 91 ** 92 ** Examples: 93 ** Str.type.qname -> "sys::Str" 94 ** acme::Foo.type.qname -> "acme::Foo" 95 ** acme::Foo[].type.qname -> "sys::List" 96 ** 97 Str qname() 98 99 ** 100 ** Return the formal signature of this type. In the case of non-parameterized 101 ** types the signature is the same as qname. Return "dynamic" if dynamic type. 102 ** For parameterized types derived from List, Map, or Func the signature uses 103 ** the following special syntax: 104 ** List -> V[] 105 ** Map -> [K:V] 106 ** Func -> |A,B...->R| 107 ** 108 ** Examples: 109 ** Str.type.signature -> "sys::Str" 110 ** Int[].type.signature -> "sys::Int[]" 111 ** Int:Str.type.signature -> "[sys::Int:sys::Str]" 112 ** Str:Buf[].type.signature -> [sys::Str:sys::Buf[]] 113 ** |Float x->Bool|.type.signature -> "|sys::Float->sys::Bool|" 114 ** |Float x, Int y|.type.signature -> |sys::Float,sys::Int->sys::Void| 115 ** 116 Str signature() 117 118 ////////////////////////////////////////////////////////////////////////// 119 // Inheritance 120 ////////////////////////////////////////////////////////////////////////// 121 122 ** 123 ** The direct super class of this type (null for Obj). 124 ** Return sys::Obj for all mixin types. 125 ** 126 ** Examples: 127 ** Obj.type.base -> null 128 ** Int.type.base -> sys::Num 129 ** OutStream.type.base -> sys::Obj 130 ** 131 Type base() 132 133 ** 134 ** Return the mixins directly implemented by this type. 135 ** 136 ** Examples: 137 ** Obj.type.mixins -> [,] 138 ** Buf.type.mixins -> [sys::InStream, sys::OutStream] 139 ** OutStream.type.mixins -> [,] 140 ** 141 Type[] mixins() 142 143 ** 144 ** Return a recursive flattened list of all the types this type 145 ** inherits from. The result list always includes this type itself. 146 ** The result of this method represents the complete list of types 147 ** implemented by this type - instances of this type are assignable 148 ** to any type in this list. All types (including mixins) will 149 ** include sys::Obj in this list. 150 ** 151 ** Examples: 152 ** Obj.type.inheritance -> [sys::Obj] 153 ** Int.type.inheritance -> [sys::Int, sys::Num, sys::Obj] 154 ** 155 Type[] inheritance() 156 157 ** 158 ** Does this type implement the specified type. If true, then 159 ** this type is assignable to the specified type (although the 160 ** converse is not necessarily true). This method provides the 161 ** same semantics as the 'is' operator, but between two types 162 ** rather than an instance and a type. All types (including 163 ** mixin types) fit 'sys::Obj'. 164 ** 165 ** Example: 166 ** Float.type.fits(Float.type) -> true 167 ** Float.type.fits(Num.type) -> true 168 ** Float.type.fits(Obj.type) -> true 169 ** Float.type.fits(Str.type) -> false 170 ** Obj.type.fits(Float.type) -> false 171 ** 172 Bool fits(Type t) 173 174 ////////////////////////////////////////////////////////////////////////// 175 // Generics 176 ////////////////////////////////////////////////////////////////////////// 177 178 ** 179 ** A generic type contains slot signatures which may be parameterized - for 180 ** example Map's key and value types are generic as K and V. Fan supports 181 ** three built-in generic types: List, Map, and Func. A parameterized 182 ** type such as Str[] is not a generic type (all of its generic parameters 183 ** have been filled in). User defined generic types are not supported in Fan. 184 ** 185 ** Examples: 186 ** Str.type.isGeneric -> false 187 ** List.type.isGeneric -> true 188 ** Str[].type.isGeneric -> false 189 ** 190 Bool isGeneric() 191 192 ** 193 ** If this is a parameterized type, then return the map of names to 194 ** types. If this is not a parameterized type return an empty map. 195 ** 196 ** Examples: 197 ** Str.type.params -> [:] 198 ** Str[].type.params -> ["V":Str, "L":Str[]] 199 ** Int:Slot.type.params -> ["K":Int, "V":Slot, "M":Int:Slot] 200 ** |Int x, Float y->Bool|.type.params -> ["A":Int, "B":Float, "R":Bool] 201 ** 202 Str:Type params() 203 204 ** 205 ** If this is a generic type, then dynamically create a new parameterized 206 ** type with the specified name to type map. If this type is not generic 207 ** then throw UnsupportedErr. Throw ArgErr if params fails to specify 208 ** the required parameters: 209 ** List -> V required 210 ** Map -> K, V required 211 ** Func -> R required, A-H optional 212 ** 213 ** Examples: 214 ** List.type.parameterize(["V":Bool.type]) -> Bool[] 215 ** Map.type.parameterize(["K":Str.type, "V":Obj.type]) -> Str:Obj 216 ** 217 Type parameterize(Str:Type params) 218 219 ** 220 ** Convenience for List.type.parameterize(["V":this]) 221 ** 222 ** Examples: 223 ** Int.type.toListOf -> Int[] 224 ** Str[].type.toListOf -> Str[][] 225 ** 226 Type toListOf() 227 228 ////////////////////////////////////////////////////////////////////////// 229 // Flags 230 ////////////////////////////////////////////////////////////////////////// 231 232 ** 233 ** Return if this is a dynamic type which was created at 234 ** runtime via the `Type.makeDynamic` method. 235 ** 236 Bool isDynamic() 237 238 ** 239 ** Return if this Type is abstract and cannot be instantiated. This 240 ** method will always return true if the type is a mixin. 241 ** 242 Bool isAbstract() 243 244 ** 245 ** Return if this Type is a class (as opposed to enum or mixin) 246 ** 247 Bool isClass() 248 249 ** 250 ** Return if this is a const class which means instances of this 251 ** class are immutable. 252 ** 253 Bool isConst() 254 255 ** 256 ** Return if this Type is an Enum type. 257 ** 258 Bool isEnum() 259 260 ** 261 ** Return if this Type is marked final which means it may not be subclassed. 262 ** 263 Bool isFinal() 264 265 ** 266 ** Return if this Type has internal protection scope. 267 ** 268 Bool isInternal() 269 270 ** 271 ** Return if this Type is a mixin type and cannot be instantiated. 272 ** 273 Bool isMixin() 274 275 ** 276 ** Return if this Type has public protection scope. 277 ** 278 Bool isPublic() 279 280 ** 281 ** Return if this Type was generated by the compiler. 282 ** 283 Bool isSynthetic() 284 285 ////////////////////////////////////////////////////////////////////////// 286 // Slots 287 ////////////////////////////////////////////////////////////////////////// 288 289 ** 290 ** List of the all defined fields (including inherited fields). 291 ** 292 Field[] fields() 293 294 ** 295 ** List of the all defined methods (including inherited methods). 296 ** 297 Method[] methods() 298 299 ** 300 ** List of the all defined slots, both fields and methods (including 301 ** inherited slots). 302 ** 303 Slot[] slots() 304 305 ** 306 ** Convenience for (Field)slot(name, checked) 307 ** 308 Field field(Str name, Bool checked := true) 309 310 ** 311 ** Convenience for (Method)slot(name, checked) 312 ** 313 Method method(Str name, Bool checked := true) 314 315 ** 316 ** Lookup a slot by name. If the slot doesn't exist and checked 317 ** is false then return null, otherwise throw UnknownSlotErr. 318 ** 319 Slot slot(Str name, Bool checked := true) 320 321 ** 322 ** Add a new slot to a dynamic type. If not a dynamic 323 ** type or a duplicate slot name exists, then throw Err. 324 ** 325 ** Refer to [Dynamic Types]`docLang::DynamicTypes` for more details. 326 ** 327 Void add(Slot slot) 328 329 ** 330 ** Remove a slot from a dynamic type. If not a dynamic 331 ** type or the slot is inherited, then throw Err. 332 ** 333 ** Refer to [Dynamic Types]`docLang::DynamicTypes` for more details. 334 ** 335 Void remove(Slot slot) 336 337 ** 338 ** Create a new instance of this Type using a public constructor 339 ** called "make". Throw Err if public constructor "make" is 340 ** not available. 341 ** 342 Obj make(Obj[] args := null) 343 344 ////////////////////////////////////////////////////////////////////////// 345 // Facets 346 ////////////////////////////////////////////////////////////////////////// 347 348 ** 349 ** Return all the facets defined for this slot or an empty map 350 ** if no facets are defined. If 'inherited' is true, then this method 351 ** returns a map of all the facets of this type's `inheritance`. If 352 ** looking up a facet by name, then use the `facet` method which will 353 ** provide better performance. See the [Facets Doc]`docLang::Facets` 354 ** for details. 355 ** 356 Str:Obj facets(Bool inherited := false) 357 358 ** 359 ** Get a facet by name, or return the 'def' is the facet is not defined. 360 ** If 'inherited' is true, then this type's `inheritance` chain is 361 ** searched. See the [Facets Doc]`docLang::Facets` for details. 362 ** 363 Obj facet(Str name, Obj def := null, Bool inherited := false) 364 365 ////////////////////////////////////////////////////////////////////////// 366 // Documentation 367 ////////////////////////////////////////////////////////////////////////// 368 369 ** 370 ** Return the raw fandoc for this type or null if not available. 371 ** 372 Str doc() 373 374 ////////////////////////////////////////////////////////////////////////// 375 // Conversion 376 ////////////////////////////////////////////////////////////////////////// 377 378 ** 379 ** Always return signature(). 380 ** 381 override Str toStr() 382 383 }